another intent to remove sync1 and replace it with sync2 completely

This commit is contained in:
CamilleLaVey
2026-09-22 18:35:26 -04:00
parent e6fe763afa
commit 6ffd65adaf
23 changed files with 1005 additions and 1033 deletions
+63 -59
View File
@@ -454,12 +454,15 @@ VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) { VkImageLayout source_layout = VK_IMAGE_LAYOUT_GENERAL) {
constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | constexpr VkAccessFlags2 flags{VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
const VkImageMemoryBarrier barrier{ VK_ACCESS_2_SHADER_READ_BIT};
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, const VkImageMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.srcAccessMask = flags, .srcAccessMask = flags,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = flags, .dstAccessMask = flags,
.oldLayout = source_layout, .oldLayout = source_layout,
.newLayout = target_layout, .newLayout = target_layout,
@@ -474,8 +477,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
.layerCount = 1, .layerCount = 1,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(barrier);
0, barrier);
} }
void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view) { void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view) {
@@ -483,14 +485,22 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
const VkImageSubresourceRange subresource_range = SubresourceRangeFromView(image_view); const VkImageSubresourceRange subresource_range = SubresourceRangeFromView(image_view);
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([image, subresource_range](vk::CommandBuffer cmdbuf) { scheduler.Record([image, subresource_range](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier barrier{ const VkImageMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_ACCESS_SHADER_WRITE_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT |
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -498,17 +508,7 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view)
.image = image, .image = image,
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}; };
cmdbuf.PipelineBarrier( cmdbuf.PipelineBarrier(barrier);
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0,
barrier);
}); });
} }
@@ -991,10 +991,12 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}; };
const std::array pre_barriers{ const std::array pre_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = aspect_info.pre_src_stages,
.srcAccessMask = aspect_info.pre_src_access, .srcAccessMask = aspect_info.pre_src_access,
.dstStageMask = aspect_info.pre_dst_stages,
.dstAccessMask = aspect_info.pre_src_dst_access, .dstAccessMask = aspect_info.pre_src_dst_access,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1003,10 +1005,12 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
.image = src, .image = src,
.subresourceRange = barrier_range, .subresourceRange = barrier_range,
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = aspect_info.pre_src_stages,
.srcAccessMask = aspect_info.pre_src_access, .srcAccessMask = aspect_info.pre_src_access,
.dstStageMask = aspect_info.pre_dst_stages,
.dstAccessMask = aspect_info.pre_dst_dst_access, .dstAccessMask = aspect_info.pre_dst_dst_access,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1016,8 +1020,7 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
.subresourceRange = barrier_range, .subresourceRange = barrier_range,
}, },
}; };
cmdbuf.PipelineBarrier(aspect_info.pre_src_stages, aspect_info.pre_dst_stages, 0, cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers);
nullptr, nullptr, pre_barriers);
const VkRenderPassBeginInfo renderpass_bi{ const VkRenderPassBeginInfo renderpass_bi{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.pNext = nullptr, .pNext = nullptr,
@@ -1053,10 +1056,12 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants); cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants);
cmdbuf.Draw(3, 1, 0, 0); cmdbuf.Draw(3, 1, 0, 0);
cmdbuf.EndRenderPass(); cmdbuf.EndRenderPass();
const VkImageMemoryBarrier post_barrier{ const VkImageMemoryBarrier2 post_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = aspect_info.post_src_stages,
.srcAccessMask = aspect_info.post_src_access, .srcAccessMask = aspect_info.post_src_access,
.dstStageMask = aspect_info.post_dst_stages,
.dstAccessMask = aspect_info.post_dst_access, .dstAccessMask = aspect_info.post_dst_access,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1065,8 +1070,7 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline,
.image = dst, .image = dst,
.subresourceRange = barrier_range, .subresourceRange = barrier_range,
}; };
cmdbuf.PipelineBarrier(aspect_info.post_src_stages, aspect_info.post_dst_stages, 0, cmdbuf.PipelineBarrier(post_barrier);
post_barrier);
}); });
msaa_copy_resources.push_back(MSAACopyResources{ msaa_copy_resources.push_back(MSAACopyResources{
.tick = scheduler.CurrentTick(), .tick = scheduler.CurrentTick(),
@@ -1115,21 +1119,21 @@ void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_i
.src_view_aspect = VK_IMAGE_ASPECT_COLOR_BIT, .src_view_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
.attachment_aspect = VK_IMAGE_ASPECT_COLOR_BIT, .attachment_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
.barrier_aspect = VK_IMAGE_ASPECT_COLOR_BIT, .barrier_aspect = VK_IMAGE_ASPECT_COLOR_BIT,
.pre_src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | .pre_src_access = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.pre_src_dst_access = VK_ACCESS_SHADER_READ_BIT, .pre_src_dst_access = VK_ACCESS_2_SHADER_READ_BIT,
.pre_dst_dst_access = .pre_dst_dst_access =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
.pre_src_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | .pre_src_stages = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.pre_dst_stages = .pre_dst_stages =
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.post_src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .post_src_access = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
.post_dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, .post_dst_access = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_TRANSFER_READ_BIT,
.post_src_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .post_src_stages = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.post_dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | .post_dst_stages = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
}; };
const VkFormat src_vk_format = const VkFormat src_vk_format =
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format; MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format;
@@ -1625,19 +1629,19 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage
.attachment_aspect = attachment_aspect, .attachment_aspect = attachment_aspect,
.barrier_aspect = attachment_aspect, .barrier_aspect = attachment_aspect,
.pre_src_access = .pre_src_access =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.pre_src_dst_access = VK_ACCESS_SHADER_READ_BIT, .pre_src_dst_access = VK_ACCESS_2_SHADER_READ_BIT,
.pre_dst_dst_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | .pre_dst_dst_access = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.pre_src_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | .pre_src_stages = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.pre_dst_stages = .pre_dst_stages =
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
.post_src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .post_src_access = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.post_dst_access = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | .post_dst_access = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_TRANSFER_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
.post_src_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, .post_src_stages = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
.post_dst_stages = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, .post_dst_stages = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
}; };
const VkFormat src_vk_format = const VkFormat src_vk_format =
+9 -9
View File
@@ -140,15 +140,15 @@ private:
VkImageAspectFlags src_view_aspect; VkImageAspectFlags src_view_aspect;
VkImageAspectFlags attachment_aspect; VkImageAspectFlags attachment_aspect;
VkImageAspectFlags barrier_aspect; VkImageAspectFlags barrier_aspect;
VkAccessFlags pre_src_access; VkAccessFlags2 pre_src_access;
VkAccessFlags pre_src_dst_access; VkAccessFlags2 pre_src_dst_access;
VkAccessFlags pre_dst_dst_access; VkAccessFlags2 pre_dst_dst_access;
VkPipelineStageFlags pre_src_stages; VkPipelineStageFlags2 pre_src_stages;
VkPipelineStageFlags pre_dst_stages; VkPipelineStageFlags2 pre_dst_stages;
VkAccessFlags post_src_access; VkAccessFlags2 post_src_access;
VkAccessFlags post_dst_access; VkAccessFlags2 post_dst_access;
VkPipelineStageFlags post_src_stages; VkPipelineStageFlags2 post_src_stages;
VkPipelineStageFlags post_dst_stages; VkPipelineStageFlags2 post_dst_stages;
}; };
void BlitImpl(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, void BlitImpl(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
@@ -113,13 +113,17 @@ void WriteColorPpm(const std::filesystem::path& path, VkExtent2D extent,
WritePortablePixmap(path, "P6", extent, rgb); WritePortablePixmap(path, "P6", extent, rgb);
} }
VkImageMemoryBarrier MakeTransitionBarrier(VkImage image, VkAccessFlags src_access, VkImageMemoryBarrier2 MakeTransitionBarrier(VkImage image, VkPipelineStageFlags2 src_stage,
VkAccessFlags dst_access, VkImageLayout old_layout, VkAccessFlags2 src_access,
VkImageLayout new_layout) { VkPipelineStageFlags2 dst_stage,
return VkImageMemoryBarrier{ VkAccessFlags2 dst_access, VkImageLayout old_layout,
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, VkImageLayout new_layout) {
return VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = src_stage,
.srcAccessMask = src_access, .srcAccessMask = src_access,
.dstStageMask = dst_stage,
.dstAccessMask = dst_access, .dstAccessMask = dst_access,
.oldLayout = old_layout, .oldLayout = old_layout,
.newLayout = new_layout, .newLayout = new_layout,
@@ -160,29 +164,31 @@ void CopyPresentedFrame(vk::CommandBuffer cmdbuf, VkImage source, LsfgImage& des
VkExtent2D extent) { VkExtent2D extent) {
const auto make_barrier = MakeTransitionBarrier; const auto make_barrier = MakeTransitionBarrier;
static constexpr VkPipelineStageFlags2 present_stage =
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
const std::array before{ const std::array before{
make_barrier(source, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, make_barrier(source, present_stage, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
make_barrier(destination.Handle(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, make_barrier(destination.Handle(), present_stage, VK_ACCESS_2_SHADER_READ_BIT,
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
destination.Layout(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), destination.Layout(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | cmdbuf.PipelineBarrier(0, {}, {}, before);
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, {}, before);
cmdbuf.CopyImage(source, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destination.Handle(), cmdbuf.CopyImage(source, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, destination.Handle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, MakeCopyRegion(extent)); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, MakeCopyRegion(extent));
const std::array after{ const std::array after{
make_barrier(source, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, make_barrier(source, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT,
present_stage, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL),
make_barrier(destination.Handle(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, make_barrier(destination.Handle(), VK_PIPELINE_STAGE_2_TRANSFER_BIT,
VK_ACCESS_2_TRANSFER_WRITE_BIT, present_stage, VK_ACCESS_2_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL),
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, after);
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, {}, {}, after);
destination.SetLayout(VK_IMAGE_LAYOUT_GENERAL); destination.SetLayout(VK_IMAGE_LAYOUT_GENERAL);
} }
@@ -364,11 +364,13 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i
}; };
scheduler.Record([this, copy, index = image_index](vk::CommandBuffer cmdbuf) { scheduler.Record([this, copy, index = image_index](vk::CommandBuffer cmdbuf) {
const VkImage image = *raw_images[index]; const VkImage image = *raw_images[index];
const VkImageMemoryBarrier base_barrier{ const VkImageMemoryBarrier2 base_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = 0, .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
.dstAccessMask = 0, .srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = VK_PIPELINE_STAGE_2_NONE,
.dstAccessMask = VK_ACCESS_2_NONE,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -382,23 +384,24 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i
.layerCount = 1, .layerCount = 1,
}, },
}; };
VkImageMemoryBarrier read_barrier = base_barrier; VkImageMemoryBarrier2 read_barrier = base_barrier;
read_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; read_barrier.srcStageMask = VK_PIPELINE_STAGE_2_HOST_BIT;
read_barrier.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
read_barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
read_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; read_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
read_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; read_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
VkImageMemoryBarrier write_barrier = base_barrier; VkImageMemoryBarrier2 write_barrier = base_barrier;
write_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; write_barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
write_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; write_barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
write_barrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
write_barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT;
write_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; write_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, cmdbuf.PipelineBarrier(read_barrier);
read_barrier);
cmdbuf.CopyBufferToImage(*buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy); cmdbuf.CopyBufferToImage(*buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(write_barrier);
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, write_barrier);
}); });
} }
@@ -67,12 +67,14 @@ vk::Buffer CreateUniformBuffer(MemoryAllocator& memory_allocator, VkDeviceSize s
return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::Upload); return memory_allocator.CreateBuffer(buffer_ci, MemoryUsage::Upload);
} }
VkImageMemoryBarrier MakeBarrier(const LsfgImage& image, VkAccessFlags src_access, VkImageMemoryBarrier2 MakeBarrier(const LsfgImage& image, VkAccessFlags2 src_access,
VkAccessFlags dst_access) { VkAccessFlags2 dst_access) {
return VkImageMemoryBarrier{ return VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.srcAccessMask = src_access, .srcAccessMask = src_access,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = dst_access, .dstAccessMask = dst_access,
.oldLayout = image.Layout(), .oldLayout = image.Layout(),
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -98,19 +100,19 @@ LsfgImage::LsfgImage(const Device& device, MemoryAllocator& memory_allocator, Vk
view = CreateWrappedImageView(device, image, format); view = CreateWrappedImageView(device, image, format);
} }
LsfgBarriers& LsfgBarriers::Push(LsfgImage& image, VkAccessFlags src_access, LsfgBarriers& LsfgBarriers::Push(LsfgImage& image, VkAccessFlags2 src_access,
VkAccessFlags dst_access) { VkAccessFlags2 dst_access) {
barriers.push_back(MakeBarrier(image, src_access, dst_access)); barriers.push_back(MakeBarrier(image, src_access, dst_access));
image.SetLayout(VK_IMAGE_LAYOUT_GENERAL); image.SetLayout(VK_IMAGE_LAYOUT_GENERAL);
return *this; return *this;
} }
LsfgBarriers& LsfgBarriers::WriteToRead(LsfgImage& image) { LsfgBarriers& LsfgBarriers::WriteToRead(LsfgImage& image) {
return Push(image, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); return Push(image, VK_ACCESS_2_SHADER_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT);
} }
LsfgBarriers& LsfgBarriers::ReadToWrite(LsfgImage& image) { LsfgBarriers& LsfgBarriers::ReadToWrite(LsfgImage& image) {
return Push(image, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT); return Push(image, VK_ACCESS_2_SHADER_READ_BIT, VK_ACCESS_2_SHADER_WRITE_BIT);
} }
LsfgBarriers& LsfgBarriers::WriteToRead(LsfgImage* image) { LsfgBarriers& LsfgBarriers::WriteToRead(LsfgImage* image) {
@@ -122,11 +124,13 @@ LsfgBarriers& LsfgBarriers::ReadToWrite(LsfgImage* image) {
} }
LsfgBarriers& LsfgBarriers::DiscardToWrite(VkImage image) { LsfgBarriers& LsfgBarriers::DiscardToWrite(VkImage image) {
barriers.push_back(VkImageMemoryBarrier{ barriers.push_back(VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = 0, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -199,8 +203,7 @@ void LsfgBarriers::Build() {
if (barriers.empty()) { if (barriers.empty()) {
return; return;
} }
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, barriers);
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, {}, {}, barriers);
barriers.clear(); barriers.clear();
} }
@@ -147,10 +147,10 @@ public:
void Build(); void Build();
private: private:
LsfgBarriers& Push(LsfgImage& image, VkAccessFlags src_access, VkAccessFlags dst_access); LsfgBarriers& Push(LsfgImage& image, VkAccessFlags2 src_access, VkAccessFlags2 dst_access);
vk::CommandBuffer cmdbuf; vk::CommandBuffer cmdbuf;
std::vector<VkImageMemoryBarrier> barriers; std::vector<VkImageMemoryBarrier2> barriers;
}; };
class LsfgDescriptorWriter { class LsfgDescriptorWriter {
@@ -22,12 +22,15 @@ constexpr u32 DISPATCH_TILE_SHIFT = 4;
return (size + (1u << DISPATCH_TILE_SHIFT) - 1) >> DISPATCH_TILE_SHIFT; return (size + (1u << DISPATCH_TILE_SHIFT) - 1) >> DISPATCH_TILE_SHIFT;
} }
VkImageMemoryBarrier MakeTargetBarrier(VkImage image, VkAccessFlags src_access, VkImageMemoryBarrier2 MakeTargetBarrier(VkImage image, VkPipelineStageFlags2 src_stage,
VkAccessFlags dst_access, VkImageLayout old_layout) { VkAccessFlags2 src_access, VkPipelineStageFlags2 dst_stage,
return VkImageMemoryBarrier{ VkAccessFlags2 dst_access, VkImageLayout old_layout) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, return VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = src_stage,
.srcAccessMask = src_access, .srcAccessMask = src_access,
.dstStageMask = dst_stage,
.dstAccessMask = dst_access, .dstAccessMask = dst_access,
.oldLayout = old_layout, .oldLayout = old_layout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -118,13 +121,11 @@ void LsfgGenerate::Dispatch(vk::CommandBuffer cmdbuf, u64 frame_count, size_t sl
cmdbuf.Dispatch(GroupCount(extent.width), GroupCount(extent.height), 1); cmdbuf.Dispatch(GroupCount(extent.width), GroupCount(extent.height), 1);
const std::array after{MakeTargetBarrier( const std::array after{MakeTargetBarrier(
image, VK_ACCESS_SHADER_WRITE_BIT, image, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_GENERAL)}; VK_IMAGE_LAYOUT_GENERAL)};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, after);
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT,
0, {}, {}, after);
} }
} // namespace Vulkan } // namespace Vulkan
+28 -22
View File
@@ -49,12 +49,15 @@ vk::Image CreateWrappedImage(MemoryAllocator& allocator, VkExtent2D dimensions,
void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout, void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayout target_layout,
VkImageLayout source_layout) { VkImageLayout source_layout) {
constexpr VkFlags flags{VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | constexpr VkAccessFlags2 flags{VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT}; VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
const VkImageMemoryBarrier barrier{ VK_ACCESS_2_SHADER_READ_BIT};
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, const VkImageMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.srcAccessMask = flags, .srcAccessMask = flags,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = flags, .dstAccessMask = flags,
.oldLayout = source_layout, .oldLayout = source_layout,
.newLayout = target_layout, .newLayout = target_layout,
@@ -69,8 +72,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
.layerCount = 1, .layerCount = 1,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(barrier);
0, barrier);
} }
void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler, void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& scheduler,
@@ -116,11 +118,13 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffer, void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffer,
VkExtent3D extent) { VkExtent3D extent) {
const VkImageMemoryBarrier read_barrier{ const VkImageMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -134,11 +138,13 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
const VkImageMemoryBarrier image_write_barrier{ const VkImageMemoryBarrier2 image_write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = 0, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -152,11 +158,13 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
static constexpr VkMemoryBarrier memory_write_barrier{ static constexpr VkMemoryBarrier2 memory_write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
const VkBufferImageCopy copy{ const VkBufferImageCopy copy{
.bufferOffset = 0, .bufferOffset = 0,
@@ -171,11 +179,9 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
.imageOffset{.x = 0, .y = 0, .z = 0}, .imageOffset{.x = 0, .y = 0, .z = 0},
.imageExtent{extent}, .imageExtent{extent},
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, cmdbuf.PipelineBarrier(read_barrier);
read_barrier);
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy); cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, cmdbuf.PipelineBarrier(0, memory_write_barrier, {}, image_write_barrier);
memory_write_barrier, nullptr, image_write_barrier);
} }
vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) { vk::ImageView CreateWrappedImageView(const Device& device, vk::Image& image, VkFormat format) {
@@ -227,11 +227,13 @@ public:
.dstOffset = 0, .dstOffset = 0,
.size = size_bytes, .size = size_bytes,
}; };
const VkBufferMemoryBarrier write_barrier{ const VkBufferMemoryBarrier2 write_barrier{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_INDEX_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT,
.dstAccessMask = VK_ACCESS_2_INDEX_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = dst_buffer, .buffer = dst_buffer,
@@ -239,8 +241,7 @@ public:
.size = size_bytes, .size = size_bytes,
}; };
cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(write_barrier);
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, write_barrier);
}); });
} else { } else {
buffer.Flush(); buffer.Flush();
@@ -456,17 +457,21 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
if (dst_buffer == VK_NULL_HANDLE || src_buffer == VK_NULL_HANDLE) { if (dst_buffer == VK_NULL_HANDLE || src_buffer == VK_NULL_HANDLE) {
return; return;
} }
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
}; };
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
// Measuring a popular game, this number never exceeds the specified size once data is warmed up // Measuring a popular game, this number never exceeds the specified size once data is warmed up
@@ -483,42 +488,42 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) { scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
if (barrier) { if (barrier) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, cmdbuf.PipelineBarrier(READ_BARRIER);
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
} }
cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies)); cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies));
if (barrier) { if (barrier) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER);
} }
}); });
} }
void BufferCacheRuntime::PreCopyBarrier() { void BufferCacheRuntime::PreCopyBarrier() {
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([](vk::CommandBuffer cmdbuf) { scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(READ_BARRIER);
0, READ_BARRIER);
}); });
} }
void BufferCacheRuntime::PostCopyBarrier() { void BufferCacheRuntime::PostCopyBarrier() {
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([](vk::CommandBuffer cmdbuf) { scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(WRITE_BARRIER);
0, WRITE_BARRIER);
}); });
} }
@@ -526,26 +531,28 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
if (dest_buffer == VK_NULL_HANDLE) { if (dest_buffer == VK_NULL_HANDLE) {
return; return;
} }
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
}; };
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) { scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(READ_BARRIER);
0, READ_BARRIER);
cmdbuf.FillBuffer(dest_buffer, offset, size, value); cmdbuf.FillBuffer(dest_buffer, offset, size, value);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(WRITE_BARRIER);
0, WRITE_BARRIER);
}); });
} }
@@ -322,19 +322,20 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, num_vertices](vk::CommandBuffer cmdbuf) { scheduler.Record([this, descriptor_data, num_vertices](vk::CommandBuffer cmdbuf) {
static constexpr u32 DISPATCH_SIZE = 1024; static constexpr u32 DISPATCH_SIZE = 1024;
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT,
.dstAccessMask = VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT,
}; };
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.Dispatch(Common::DivCeil(num_vertices, DISPATCH_SIZE), 1, 1); cmdbuf.Dispatch(Common::DivCeil(num_vertices, DISPATCH_SIZE), 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, WRITE_BARRIER);
}); });
return {staging.buffer, staging.offset}; return {staging.buffer, staging.offset};
} }
@@ -391,11 +392,13 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, index_shift, scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, index_shift,
is_strip](vk::CommandBuffer cmdbuf) { is_strip](vk::CommandBuffer cmdbuf) {
static constexpr u32 DISPATCH_SIZE = 1024; static constexpr u32 DISPATCH_SIZE = 1024;
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_INDEX_READ_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT,
.dstAccessMask = VK_ACCESS_2_INDEX_READ_BIT,
}; };
const std::array<u32, 3> push_constants{base_vertex, index_shift, is_strip ? 1u : 0u}; const std::array<u32, 3> push_constants{base_vertex, index_shift, is_strip ? 1u : 0u};
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
@@ -405,8 +408,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants), cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants),
&push_constants); &push_constants);
cmdbuf.Dispatch(Common::DivCeil(num_tri_vertices, DISPATCH_SIZE), 1, 1); cmdbuf.Dispatch(Common::DivCeil(num_tri_vertices, DISPATCH_SIZE), 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, WRITE_BARRIER);
}); });
return {staging.buffer, staging.offset}; return {staging.buffer, staging.offset};
} }
@@ -441,11 +443,13 @@ std::pair<VkBuffer, VkDeviceSize> IndirectQuadsPass::Assemble(u32 num_draws, u32
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, num_draws, src_stride](vk::CommandBuffer cmdbuf) { scheduler.Record([this, descriptor_data, num_draws, src_stride](vk::CommandBuffer cmdbuf) {
static constexpr u32 DISPATCH_SIZE = 32; static constexpr u32 DISPATCH_SIZE = 32;
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT,
.dstAccessMask = VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT,
}; };
const std::array<u32, 2> push_constants{num_draws, src_stride}; const std::array<u32, 2> push_constants{num_draws, src_stride};
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
@@ -455,8 +459,7 @@ std::pair<VkBuffer, VkDeviceSize> IndirectQuadsPass::Assemble(u32 num_draws, u32
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants), cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants),
&push_constants); &push_constants);
cmdbuf.Dispatch(Common::DivCeil(num_draws, DISPATCH_SIZE), 1, 1); cmdbuf.Dispatch(Common::DivCeil(num_draws, DISPATCH_SIZE), 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, WRITE_BARRIER);
}); });
return {staging.buffer, staging.offset}; return {staging.buffer, staging.offset};
} }
@@ -484,17 +487,21 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, compare_to_zero](vk::CommandBuffer cmdbuf) { scheduler.Record([this, descriptor_data, compare_to_zero](vk::CommandBuffer cmdbuf) {
static constexpr VkMemoryBarrier read_barrier{ static constexpr VkMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
}; };
static constexpr VkMemoryBarrier write_barrier{ static constexpr VkMemoryBarrier2 write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT,
.dstAccessMask = VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT,
}; };
const ConditionalRenderingResolvePushConstants uniforms{ const ConditionalRenderingResolvePushConstants uniforms{
.compare_to_zero = compare_to_zero ? 1U : 0U, .compare_to_zero = compare_to_zero ? 1U : 0U,
@@ -502,15 +509,12 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, cmdbuf.PipelineBarrier(read_barrier);
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms); cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
cmdbuf.Dispatch(1, 1, 1); cmdbuf.Dispatch(1, 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(write_barrier);
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT, 0,
write_barrier);
}); });
} }
@@ -532,14 +536,14 @@ QueriesPrefixScanPass::QueriesPrefixScanPass(
void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffer, void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffer,
VkBuffer src_buffer, size_t number_of_sums, VkBuffer src_buffer, size_t number_of_sums,
size_t min_accumulation_limit, size_t max_accumulation_limit) { size_t min_accumulation_limit, size_t max_accumulation_limit) {
constexpr VkAccessFlags BASE_DST_ACCESS = VK_ACCESS_SHADER_READ_BIT | constexpr VkAccessFlags2 BASE_DST_ACCESS = VK_ACCESS_2_SHADER_READ_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_READ_BIT |
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT |
VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT |
VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_2_INDEX_READ_BIT |
VK_ACCESS_UNIFORM_READ_BIT; VK_ACCESS_2_UNIFORM_READ_BIT;
const VkAccessFlags conditional_access = const VkAccessFlags2 conditional_access =
device.IsExtConditionalRendering() ? VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT : 0; device.IsExtConditionalRendering() ? VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT : 0;
size_t current_runs = number_of_sums; size_t current_runs = number_of_sums;
size_t offset = 0; size_t offset = 0;
while (current_runs != 0) { while (current_runs != 0) {
@@ -557,16 +561,20 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, min_accumulation_limit, max_accumulation_limit, scheduler.Record([this, descriptor_data, min_accumulation_limit, max_accumulation_limit,
runs_to_do, used_offset, conditional_access](vk::CommandBuffer cmdbuf) { runs_to_do, used_offset, conditional_access](vk::CommandBuffer cmdbuf) {
static constexpr VkMemoryBarrier read_barrier{ static constexpr VkMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
}; };
const VkMemoryBarrier write_barrier{ const VkMemoryBarrier2 write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = BASE_DST_ACCESS | conditional_access, .dstAccessMask = BASE_DST_ACCESS | conditional_access,
}; };
const QueriesPrefixScanPushConstants uniforms{ const QueriesPrefixScanPushConstants uniforms{
@@ -578,14 +586,12 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(read_barrier);
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms); cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
cmdbuf.Dispatch(1, 1, 1); cmdbuf.Dispatch(1, 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(write_barrier);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, write_barrier);
}); });
} }
} }
@@ -594,21 +600,23 @@ namespace {
void RecordUnswizzleBeginBarrier(Scheduler& scheduler, VkPipeline vk_pipeline, VkImage vk_image, void RecordUnswizzleBeginBarrier(Scheduler& scheduler, VkPipeline vk_pipeline, VkImage vk_image,
VkImageAspectFlags aspect_mask, bool is_initialized) { VkImageAspectFlags aspect_mask, bool is_initialized) {
VkAccessFlags src_access = VK_ACCESS_NONE; VkAccessFlags2 src_access = VK_ACCESS_2_NONE;
VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkPipelineStageFlags src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkPipelineStageFlags2 src_stage = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
if (is_initialized) { if (is_initialized) {
src_access = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; src_access = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
old_layout = VK_IMAGE_LAYOUT_GENERAL; old_layout = VK_IMAGE_LAYOUT_GENERAL;
src_stage = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER; src_stage = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER;
} }
scheduler.Record([vk_pipeline, vk_image, aspect_mask, src_access, old_layout, scheduler.Record([vk_pipeline, vk_image, aspect_mask, src_access, old_layout,
src_stage](vk::CommandBuffer cmdbuf) { src_stage](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier image_barrier{ const VkImageMemoryBarrier2 image_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = src_stage,
.srcAccessMask = src_access, .srcAccessMask = src_access,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT,
.oldLayout = old_layout, .oldLayout = old_layout,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -622,7 +630,7 @@ void RecordUnswizzleBeginBarrier(Scheduler& scheduler, VkPipeline vk_pipeline, V
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(src_stage, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); cmdbuf.PipelineBarrier(image_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
}); });
} }
@@ -630,12 +638,14 @@ void RecordUnswizzleBeginBarrier(Scheduler& scheduler, VkPipeline vk_pipeline, V
void RecordUnswizzleEndBarrier(Scheduler& scheduler, VkImage vk_image, void RecordUnswizzleEndBarrier(Scheduler& scheduler, VkImage vk_image,
VkImageAspectFlags aspect_mask) { VkImageAspectFlags aspect_mask) {
scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) { scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier image_barrier{ const VkImageMemoryBarrier2 image_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -649,8 +659,7 @@ void RecordUnswizzleEndBarrier(Scheduler& scheduler, VkImage vk_image,
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(image_barrier);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, 0, image_barrier);
}); });
} }
@@ -65,7 +65,8 @@ private:
class DescriptorPool { class DescriptorPool {
public: public:
DescriptorPool();
DescriptorPool();
~DescriptorPool(); ~DescriptorPool();
DescriptorPool& operator=(const DescriptorPool&) = delete; DescriptorPool& operator=(const DescriptorPool&) = delete;
@@ -121,8 +121,9 @@ VkResult MasterSemaphore::SubmitQueue(vk::CommandBuffer& cmdbuf, vk::CommandBuff
} }
} }
static constexpr VkPipelineStageFlags wait_stage_mask = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | static constexpr VkPipelineStageFlags2 wait_stage_mask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf, VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
vk::CommandBuffer& upload_cmdbuf, vk::CommandBuffer& upload_cmdbuf,
@@ -130,130 +131,35 @@ VkResult MasterSemaphore::SubmitQueueTimeline(vk::CommandBuffer& cmdbuf,
VkSemaphore wait_semaphore, u64 host_tick) { VkSemaphore wait_semaphore, u64 host_tick) {
const VkSemaphore timeline_semaphore = *semaphore; const VkSemaphore timeline_semaphore = *semaphore;
if (device.HasSynchronization2()) { const std::array<VkCommandBufferSubmitInfo, 2> cmdbuffer_infos{{
const std::array<VkCommandBufferSubmitInfo, 2> cmdbuffer_infos{{ {
{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, .pNext = nullptr,
.pNext = nullptr, .commandBuffer = *upload_cmdbuf,
.commandBuffer = *upload_cmdbuf, .deviceMask = 0,
.deviceMask = 0, },
}, {
{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, .pNext = nullptr,
.pNext = nullptr, .commandBuffer = *cmdbuf,
.commandBuffer = *cmdbuf, .deviceMask = 0,
.deviceMask = 0, },
}, }};
}};
std::array<VkSemaphoreSubmitInfo, 2> signal_infos{{ std::array<VkSemaphoreSubmitInfo, 2> signal_infos{{
{ {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = timeline_semaphore,
.value = host_tick,
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0,
},
{},
}};
u32 num_signal_semaphores = 1;
if (signal_semaphore) {
signal_infos[1] = VkSemaphoreSubmitInfo{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = signal_semaphore,
.value = 0,
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0,
};
num_signal_semaphores = 2;
}
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo wait_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.semaphore = wait_semaphore, .semaphore = timeline_semaphore,
.value = 0, .value = host_tick,
.stageMask = static_cast<VkPipelineStageFlags2>(wait_stage_mask), .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0, .deviceIndex = 0,
}; },
{},
const VkSubmitInfo2 submit_info2{ }};
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, u32 num_signal_semaphores = 1;
.pNext = nullptr, if (signal_semaphore) {
.flags = 0, signal_infos[1] = VkSemaphoreSubmitInfo{
.waitSemaphoreInfoCount = num_wait_semaphores,
.pWaitSemaphoreInfos = num_wait_semaphores ? &wait_info : nullptr,
.commandBufferInfoCount = static_cast<u32>(cmdbuffer_infos.size()),
.pCommandBufferInfos = cmdbuffer_infos.data(),
.signalSemaphoreInfoCount = num_signal_semaphores,
.pSignalSemaphoreInfos = signal_infos.data(),
};
return device.GetGraphicsQueue().Submit2(submit_info2);
}
const u32 num_signal_semaphores = signal_semaphore ? 2 : 1;
const std::array signal_values{host_tick, u64(0)};
const std::array signal_semaphores{timeline_semaphore, signal_semaphore};
const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf};
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
// Pointers must be null when the count is zero (best-practices)
const VkSemaphore* p_wait_sems =
(num_wait_semaphores > 0) ? &wait_semaphore : nullptr;
const VkPipelineStageFlags* p_wait_masks =
(num_wait_semaphores > 0) ? &wait_stage_mask : nullptr;
const VkSemaphore* p_signal_sems =
(num_signal_semaphores > 0) ? signal_semaphores.data() : nullptr;
const u64 wait_zero = 0; // dummy for binary wait
const VkTimelineSemaphoreSubmitInfo timeline_si{
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.waitSemaphoreValueCount = num_wait_semaphores,
.pWaitSemaphoreValues = num_wait_semaphores ? &wait_zero : nullptr,
.signalSemaphoreValueCount = num_signal_semaphores,
.pSignalSemaphoreValues = signal_values.data(),
};
const VkSubmitInfo submit_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = &timeline_si,
.waitSemaphoreCount = num_wait_semaphores,
.pWaitSemaphores = p_wait_sems,
.pWaitDstStageMask = p_wait_masks,
.commandBufferCount = static_cast<u32>(cmdbuffers.size()),
.pCommandBuffers = cmdbuffers.data(),
.signalSemaphoreCount = num_signal_semaphores,
.pSignalSemaphores = p_signal_sems,
};
return device.GetGraphicsQueue().Submit(submit_info);
}
VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf,
vk::CommandBuffer& upload_cmdbuf,
VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
u64 host_tick) {
if (device.HasSynchronization2()) {
const std::array<VkCommandBufferSubmitInfo, 2> cmdbuffer_infos{{
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr,
.commandBuffer = *upload_cmdbuf,
.deviceMask = 0,
},
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr,
.commandBuffer = *cmdbuf,
.deviceMask = 0,
},
}};
const u32 num_signal_semaphores = signal_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo signal_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.semaphore = signal_semaphore, .semaphore = signal_semaphore,
@@ -261,66 +167,86 @@ VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf,
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0, .deviceIndex = 0,
}; };
num_signal_semaphores = 2;
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo wait_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = wait_semaphore,
.value = 0,
.stageMask = static_cast<VkPipelineStageFlags2>(wait_stage_mask),
.deviceIndex = 0,
};
const VkSubmitInfo2 submit_info2{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.pNext = nullptr,
.flags = 0,
.waitSemaphoreInfoCount = num_wait_semaphores,
.pWaitSemaphoreInfos = num_wait_semaphores ? &wait_info : nullptr,
.commandBufferInfoCount = static_cast<u32>(cmdbuffer_infos.size()),
.pCommandBufferInfos = cmdbuffer_infos.data(),
.signalSemaphoreInfoCount = num_signal_semaphores,
.pSignalSemaphoreInfos = num_signal_semaphores ? &signal_info : nullptr,
};
auto fence = GetFreeFence();
auto result = device.GetGraphicsQueue().Submit2(submit_info2, *fence);
if (result == VK_SUCCESS) {
std::scoped_lock lock{wait_mutex};
wait_queue.emplace(host_tick, std::move(fence));
wait_cv.notify_one();
}
return result;
} }
const u32 num_signal_semaphores = signal_semaphore ? 1 : 0;
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0; const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo wait_info{
const VkSemaphore* p_wait_sems = .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
(num_wait_semaphores > 0) ? &wait_semaphore : nullptr;
const VkPipelineStageFlags* p_wait_masks =
(num_wait_semaphores > 0) ? &wait_stage_mask : nullptr;
const VkSemaphore* p_signal_sems =
(num_signal_semaphores > 0) ? &signal_semaphore : nullptr;
const std::array cmdbuffers{*upload_cmdbuf, *cmdbuf};
const VkSubmitInfo submit_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = num_wait_semaphores, .semaphore = wait_semaphore,
.pWaitSemaphores = p_wait_sems, .value = 0,
.pWaitDstStageMask = p_wait_masks, .stageMask = wait_stage_mask,
.commandBufferCount = static_cast<u32>(cmdbuffers.size()), .deviceIndex = 0,
.pCommandBuffers = cmdbuffers.data(), };
.signalSemaphoreCount = num_signal_semaphores,
.pSignalSemaphores = p_signal_sems, const VkSubmitInfo2 submit_info2{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.pNext = nullptr,
.flags = 0,
.waitSemaphoreInfoCount = num_wait_semaphores,
.pWaitSemaphoreInfos = num_wait_semaphores ? &wait_info : nullptr,
.commandBufferInfoCount = static_cast<u32>(cmdbuffer_infos.size()),
.pCommandBufferInfos = cmdbuffer_infos.data(),
.signalSemaphoreInfoCount = num_signal_semaphores,
.pSignalSemaphoreInfos = signal_infos.data(),
};
return device.GetGraphicsQueue().Submit(submit_info2);
}
VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf,
vk::CommandBuffer& upload_cmdbuf,
VkSemaphore signal_semaphore, VkSemaphore wait_semaphore,
u64 host_tick) {
const std::array<VkCommandBufferSubmitInfo, 2> cmdbuffer_infos{{
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr,
.commandBuffer = *upload_cmdbuf,
.deviceMask = 0,
},
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr,
.commandBuffer = *cmdbuf,
.deviceMask = 0,
},
}};
const u32 num_signal_semaphores = signal_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo signal_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = signal_semaphore,
.value = 0,
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0,
};
const u32 num_wait_semaphores = wait_semaphore ? 1 : 0;
const VkSemaphoreSubmitInfo wait_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = wait_semaphore,
.value = 0,
.stageMask = wait_stage_mask,
.deviceIndex = 0,
};
const VkSubmitInfo2 submit_info2{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.pNext = nullptr,
.flags = 0,
.waitSemaphoreInfoCount = num_wait_semaphores,
.pWaitSemaphoreInfos = num_wait_semaphores ? &wait_info : nullptr,
.commandBufferInfoCount = static_cast<u32>(cmdbuffer_infos.size()),
.pCommandBufferInfos = cmdbuffer_infos.data(),
.signalSemaphoreInfoCount = num_signal_semaphores,
.pSignalSemaphoreInfos = num_signal_semaphores ? &signal_info : nullptr,
}; };
auto fence = GetFreeFence(); auto fence = GetFreeFence();
auto result = device.GetGraphicsQueue().Submit(submit_info, *fence); auto result = device.GetGraphicsQueue().Submit(submit_info2, *fence);
if (result == VK_SUCCESS) { if (result == VK_SUCCESS) {
std::scoped_lock lock{wait_mutex}; std::scoped_lock lock{wait_mutex};
@@ -378,18 +378,24 @@ void PresentManager::SetImageCount() {
} }
void PresentManager::DiscardFrame(Frame* frame) { void PresentManager::DiscardFrame(Frame* frame) {
static constexpr VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; const VkSemaphoreSubmitInfo wait_info{
const VkSemaphore render_ready = *frame->render_ready; .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
const VkSubmitInfo submit_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = 1U, .semaphore = *frame->render_ready,
.pWaitSemaphores = &render_ready, .value = 0,
.pWaitDstStageMask = &wait_stage, .stageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
.commandBufferCount = 0U, .deviceIndex = 0,
.pCommandBuffers = nullptr, };
.signalSemaphoreCount = 0U, const VkSubmitInfo2 submit_info{
.pSignalSemaphores = nullptr, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.pNext = nullptr,
.flags = 0,
.waitSemaphoreInfoCount = 1U,
.pWaitSemaphoreInfos = &wait_info,
.commandBufferInfoCount = 0U,
.pCommandBufferInfos = nullptr,
.signalSemaphoreInfoCount = 0U,
.pSignalSemaphoreInfos = nullptr,
}; };
std::scoped_lock submit_lock{scheduler.submit_mutex}; std::scoped_lock submit_lock{scheduler.submit_mutex};
@@ -449,11 +455,13 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
const VkImage image{swapchain.CurrentImage()}; const VkImage image{swapchain.CurrentImage()};
const VkExtent2D extent = swapchain.GetExtent(); const VkExtent2D extent = swapchain.GetExtent();
const std::array pre_barriers{ const std::array pre_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = 0, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -467,11 +475,13 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -487,11 +497,13 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
}, },
}; };
const std::array post_barriers{ const std::array post_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -505,11 +517,13 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -525,8 +539,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, {}, cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers);
{}, {}, pre_barriers);
if (blit_supported) { if (blit_supported) {
cmdbuf.BlitImage(*frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, cmdbuf.BlitImage(*frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image,
@@ -539,30 +552,55 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
MakeImageCopy(frame->width, frame->height, extent.width, extent.height)); MakeImageCopy(frame->width, frame->height, extent.width, extent.height));
} }
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, {}, cmdbuf.PipelineBarrier(0, {}, {}, post_barriers);
{}, {}, post_barriers);
cmdbuf.End(); cmdbuf.End();
const VkSemaphore present_semaphore = swapchain.CurrentPresentSemaphore(); const VkSemaphore present_semaphore = swapchain.CurrentPresentSemaphore();
const VkSemaphore render_semaphore = swapchain.CurrentRenderSemaphore(); const VkSemaphore render_semaphore = swapchain.CurrentRenderSemaphore();
const std::array wait_semaphores = {present_semaphore, *frame->render_ready}; const std::array<VkSemaphoreSubmitInfo, 2> wait_infos{{
{
static constexpr std::array<VkPipelineStageFlags, 2> wait_stage_masks{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
VK_PIPELINE_STAGE_TRANSFER_BIT, .pNext = nullptr,
VK_PIPELINE_STAGE_TRANSFER_BIT, .semaphore = present_semaphore,
.value = 0,
.stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.deviceIndex = 0,
},
{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = *frame->render_ready,
.value = 0,
.stageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.deviceIndex = 0,
},
}};
const VkCommandBufferSubmitInfo cmdbuf_info{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr,
.commandBuffer = *cmdbuf,
.deviceMask = 0,
};
const VkSemaphoreSubmitInfo signal_info{
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
.semaphore = render_semaphore,
.value = 0,
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.deviceIndex = 0,
}; };
const VkSubmitInfo submit_info{ const VkSubmitInfo2 submit_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = 2U, .flags = 0,
.pWaitSemaphores = wait_semaphores.data(), .waitSemaphoreInfoCount = 2U,
.pWaitDstStageMask = wait_stage_masks.data(), .pWaitSemaphoreInfos = wait_infos.data(),
.commandBufferCount = 1, .commandBufferInfoCount = 1U,
.pCommandBuffers = cmdbuf.address(), .pCommandBufferInfos = &cmdbuf_info,
.signalSemaphoreCount = 1U, .signalSemaphoreInfoCount = 1U,
.pSignalSemaphores = &render_semaphore, .pSignalSemaphoreInfos = &signal_info,
}; };
// Submit the image copy/blit to the swapchain // Submit the image copy/blit to the swapchain
@@ -260,11 +260,13 @@ public:
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([start, amount, base_offset, query_pool, scheduler.Record([start, amount, base_offset, query_pool,
buffer = *resolve_buffer](vk::CommandBuffer cmdbuf) { buffer = *resolve_buffer](vk::CommandBuffer cmdbuf) {
const VkBufferMemoryBarrier copy_query_pool_barrier{ const VkBufferMemoryBarrier2 copy_query_pool_barrier{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffer, .buffer = buffer,
@@ -276,8 +278,7 @@ public:
query_pool, static_cast<u32>(start), static_cast<u32>(amount), buffer, query_pool, static_cast<u32>(start), static_cast<u32>(amount), buffer,
static_cast<u32>(base_offset), SamplesQueryBank::QUERY_SIZE, static_cast<u32>(base_offset), SamplesQueryBank::QUERY_SIZE,
VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(copy_query_pool_barrier);
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, copy_query_pool_barrier);
}); });
offsets[bank_id] = {start, base_offset}; offsets[bank_id] = {start, base_offset};
base_offset += amount * SamplesQueryBank::QUERY_SIZE; base_offset += amount * SamplesQueryBank::QUERY_SIZE;
@@ -862,16 +863,17 @@ public:
offset_base += TFBQueryBank::QUERY_SIZE; offset_base += TFBQueryBank::QUERY_SIZE;
bank.CloseReference(); bank.CloseReference();
} }
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_HOST,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([](vk::CommandBuffer cmdbuf) { scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
vk::PIPELINE_STAGE_HOST, 0, WRITE_BARRIER);
}); });
std::scoped_lock lk(flush_guard); std::scoped_lock lk(flush_guard);
@@ -928,16 +930,16 @@ private:
}); });
return; return;
} }
static constexpr VkMemoryBarrier COUNTER_RESUME_BARRIER{ static constexpr VkMemoryBarrier2 COUNTER_RESUME_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT,
.dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, .srcAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT,
.dstAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
}; };
scheduler.Record([this, total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) { scheduler.Record([this, total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, cmdbuf.PipelineBarrier(COUNTER_RESUME_BARRIER);
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, 0,
COUNTER_RESUME_BARRIER);
cmdbuf.BeginTransformFeedbackEXT(0, total, counter_buffers.data(), offsets.data()); cmdbuf.BeginTransformFeedbackEXT(0, total, counter_buffers.data(), offsets.data());
}); });
} }
@@ -1024,33 +1026,35 @@ private:
const size_t slot = other; // workaround to compile bug. const size_t slot = other; // workaround to compile bug.
current_bank->AddReference(); current_bank->AddReference();
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
}; };
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT,
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dst_buffer = current_bank->GetBuffer(), scheduler.Record([dst_buffer = current_bank->GetBuffer(),
src_buffer = counter_buffers[slot_index], src_buffer = counter_buffers[slot_index],
src_offset = offsets[slot_index], src_offset = offsets[slot_index],
slot](vk::CommandBuffer cmdbuf) { slot](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, cmdbuf.PipelineBarrier(READ_BARRIER);
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
std::array<VkBufferCopy, 1> copy{VkBufferCopy{ std::array<VkBufferCopy, 1> copy{VkBufferCopy{
.srcOffset = src_offset, .srcOffset = src_offset,
.dstOffset = slot * TFBQueryBank::QUERY_SIZE, .dstOffset = slot * TFBQueryBank::QUERY_SIZE,
.size = TFBQueryBank::QUERY_SIZE, .size = TFBQueryBank::QUERY_SIZE,
}}; }};
cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy); cmdbuf.CopyBuffer(src_buffer, dst_buffer, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
0, WRITE_BARRIER);
}); });
return {current_bank_id, slot}; return {current_bank_id, slot};
} }
@@ -1573,28 +1577,30 @@ VideoCommon::StreamerInterface* QueryCacheRuntime::GetStreamerInterface(QueryTyp
} }
void QueryCacheRuntime::Barriers(bool is_prebarrier) { void QueryCacheRuntime::Barriers(bool is_prebarrier) {
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
}; };
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
impl->scheduler.RequestOutsideRenderPassOperationContext(); impl->scheduler.RequestOutsideRenderPassOperationContext();
if (is_prebarrier) { if (is_prebarrier) {
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, cmdbuf.PipelineBarrier(READ_BARRIER);
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
}); });
} else { } else {
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) { impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(WRITE_BARRIER);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST, 0, WRITE_BARRIER);
}); });
} }
} }
@@ -649,14 +649,15 @@ void RasterizerVulkan::DispatchCompute() {
return; return;
} }
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT,
}; };
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(READ_BARRIER); });
0, READ_BARRIER); });
scheduler.Record([pipeline, dim](vk::CommandBuffer cmdbuf) { scheduler.Record([pipeline, dim](vk::CommandBuffer cmdbuf) {
if (!pipeline->IsBound()) { if (!pipeline->IsBound()) {
return; return;
@@ -882,22 +883,42 @@ void RasterizerVulkan::FlushAndInvalidateRegion(DAddr addr, u64 size,
void RasterizerVulkan::WaitForIdle() { void RasterizerVulkan::WaitForIdle() {
// Everything but wait pixel operations. This intentionally includes FRAGMENT_SHADER_BIT because // Everything but wait pixel operations. This intentionally includes FRAGMENT_SHADER_BIT because
// fragment shaders can still write storage buffers. // fragment shaders can still write storage buffers.
VkPipelineStageFlags flags = VkPipelineStageFlags2 flags =
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT |
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT |
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT;
if (device.IsExtTransformFeedbackSupported()) { if (device.IsExtTransformFeedbackSupported()) {
flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT; flags |= VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT;
} }
query_cache.NotifyWFI(); query_cache.NotifyWFI();
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([event = *wfi_event, flags](vk::CommandBuffer cmdbuf) { scheduler.Record([event = *wfi_event, flags](vk::CommandBuffer cmdbuf) {
cmdbuf.SetEvent(event, flags); const VkMemoryBarrier2 barrier{
cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {}); .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr,
.srcStageMask = flags,
.srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
.dstAccessMask = VK_ACCESS_2_NONE,
};
const VkDependencyInfo dependency_info{
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pNext = nullptr,
.dependencyFlags = 0,
.memoryBarrierCount = 1,
.pMemoryBarriers = &barrier,
.bufferMemoryBarrierCount = 0,
.pBufferMemoryBarriers = nullptr,
.imageMemoryBarrierCount = 0,
.pImageMemoryBarriers = nullptr,
};
cmdbuf.SetEvent(event, dependency_info);
cmdbuf.WaitEvents(event, dependency_info);
}); });
fence_manager.SignalOrdering(); fence_manager.SignalOrdering();
} }
@@ -43,10 +43,10 @@ using VideoCore::Surface::SurfaceType;
} }
} }
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, VkAttachmentDescription2 AttachmentDescription(const Device& device, PixelFormat format,
VkSampleCountFlagBits samples, VkSampleCountFlagBits samples,
VkAttachmentLoadOp load_op, VkAttachmentLoadOp load_op,
VkAttachmentStoreOp store_op) { VkAttachmentStoreOp store_op) {
using MaxwellToVK::SurfaceFormat; using MaxwellToVK::SurfaceFormat;
const SurfaceType surface_type = GetSurfaceType(format); const SurfaceType surface_type = GetSurfaceType(format);
@@ -54,6 +54,8 @@ using VideoCore::Surface::SurfaceType;
surface_type == SurfaceType::Stencil; surface_type == SurfaceType::Stencil;
return { return {
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
.pNext = nullptr,
.flags = {}, .flags = {},
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format, .format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
.samples = samples, .samples = samples,
@@ -141,16 +143,19 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
} }
static constexpr size_t MAX_ATTACHMENTS = static constexpr size_t MAX_ATTACHMENTS =
2 * std::tuple_size_v<decltype(RenderPassKey::color_formats)> + 2; 2 * std::tuple_size_v<decltype(RenderPassKey::color_formats)> + 2;
boost::container::static_vector<VkAttachmentDescription, MAX_ATTACHMENTS> descriptions; boost::container::static_vector<VkAttachmentDescription2, MAX_ATTACHMENTS> descriptions;
std::array<VkAttachmentReference, 8> references{}; std::array<VkAttachmentReference2, 8> references{};
u32 num_attachments{}; u32 num_attachments{};
u32 num_colors{}; u32 num_colors{};
for (size_t index = 0; index < key.color_formats.size(); ++index) { for (size_t index = 0; index < key.color_formats.size(); ++index) {
const PixelFormat format{key.color_formats[index]}; const PixelFormat format{key.color_formats[index]};
const bool is_valid{format != PixelFormat::Invalid}; const bool is_valid{format != PixelFormat::Invalid};
references[index] = VkAttachmentReference{ references[index] = VkAttachmentReference2{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED, .attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED,
.layout = VK_IMAGE_LAYOUT_GENERAL, .layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
}; };
if (is_valid) { if (is_valid) {
const VkAttachmentLoadOp load_op = (key.color_clear_mask & (1u << index)) != 0 const VkAttachmentLoadOp load_op = (key.color_clear_mask & (1u << index)) != 0
@@ -166,11 +171,14 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
} }
} }
const bool has_depth{key.depth_format != PixelFormat::Invalid}; const bool has_depth{key.depth_format != PixelFormat::Invalid};
VkAttachmentReference depth_reference{}; VkAttachmentReference2 depth_reference{};
if (key.depth_format != PixelFormat::Invalid) { if (has_depth) {
depth_reference = VkAttachmentReference{ depth_reference = VkAttachmentReference2{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = num_colors, .attachment = num_colors,
.layout = VK_IMAGE_LAYOUT_GENERAL, .layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
}; };
const VkAttachmentLoadOp depth_load_op = key.depth_stencil_clear const VkAttachmentLoadOp depth_load_op = key.depth_stencil_clear
? VK_ATTACHMENT_LOAD_OP_CLEAR ? VK_ATTACHMENT_LOAD_OP_CLEAR
@@ -181,19 +189,23 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples, descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples,
depth_load_op, depth_store_op)); depth_load_op, depth_store_op));
} }
std::array<VkAttachmentReference, 8> resolve_references{}; std::array<VkAttachmentReference2, 8> resolve_references{};
const bool do_resolve_color = const bool do_resolve_color =
key.resolve_color && key.samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0; key.resolve_color && key.samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0;
if (do_resolve_color) { if (do_resolve_color) {
for (size_t index = 0; index < key.color_formats.size(); ++index) { for (size_t index = 0; index < key.color_formats.size(); ++index) {
const PixelFormat format{key.color_formats[index]}; const PixelFormat format{key.color_formats[index]};
const bool is_valid{format != PixelFormat::Invalid}; const bool is_valid{format != PixelFormat::Invalid};
resolve_references[index] = VkAttachmentReference{ resolve_references[index] = VkAttachmentReference2{
.attachment = is_valid ? static_cast<u32>(descriptions.size()) : VK_ATTACHMENT_UNUSED, .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = is_valid ? static_cast<u32>(descriptions.size())
: VK_ATTACHMENT_UNUSED,
.layout = VK_IMAGE_LAYOUT_GENERAL, .layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
}; };
if (is_valid) { if (is_valid) {
VkAttachmentDescription resolve_desc = VkAttachmentDescription2 resolve_desc =
AttachmentDescription(*device, format, VK_SAMPLE_COUNT_1_BIT, AttachmentDescription(*device, format, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE); VK_ATTACHMENT_STORE_OP_STORE);
@@ -205,21 +217,35 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
const bool do_resolve_depth_stencil = key.resolve_depth_stencil && has_depth && const bool do_resolve_depth_stencil = key.resolve_depth_stencil && has_depth &&
key.samples != VK_SAMPLE_COUNT_1_BIT && key.samples != VK_SAMPLE_COUNT_1_BIT &&
SupportsDepthStencilResolve(*device, key.depth_format); SupportsDepthStencilResolve(*device, key.depth_format);
VkAttachmentReference depth_resolve_reference{}; VkAttachmentReference2 depth_resolve_reference{};
if (do_resolve_depth_stencil) { if (do_resolve_depth_stencil) {
depth_resolve_reference = VkAttachmentReference{ depth_resolve_reference = VkAttachmentReference2{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = static_cast<u32>(descriptions.size()), .attachment = static_cast<u32>(descriptions.size()),
.layout = VK_IMAGE_LAYOUT_GENERAL, .layout = VK_IMAGE_LAYOUT_GENERAL,
.aspectMask = 0,
}; };
VkAttachmentDescription resolve_desc = VkAttachmentDescription2 resolve_desc =
AttachmentDescription(*device, key.depth_format, VK_SAMPLE_COUNT_1_BIT, AttachmentDescription(*device, key.depth_format, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE);
resolve_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; resolve_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
descriptions.push_back(resolve_desc); descriptions.push_back(resolve_desc);
} }
const VkSubpassDescription subpass{ const ResolveModes resolve_modes = PickResolveModes(*device, key.depth_format);
const VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
.pNext = nullptr,
.depthResolveMode = resolve_modes.depth,
.stencilResolveMode = resolve_modes.stencil,
.pDepthStencilResolveAttachment = &depth_resolve_reference,
};
const VkSubpassDescription2 subpass{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
.pNext = do_resolve_depth_stencil ? &depth_stencil_resolve : nullptr,
.flags = 0, .flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.viewMask = 0,
.inputAttachmentCount = 0, .inputAttachmentCount = 0,
.pInputAttachments = nullptr, .pInputAttachments = nullptr,
.colorAttachmentCount = num_attachments, .colorAttachmentCount = num_attachments,
@@ -229,106 +255,31 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
.preserveAttachmentCount = 0, .preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr, .pPreserveAttachments = nullptr,
}; };
const VkSubpassDependency dependency{ const VkMemoryBarrier2 dependency_barrier{
.srcSubpass = 0, // Current subpass .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.dstSubpass = 0, // Same subpass (self-dependency) .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT, .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT
}; };
const VkSubpassDependency2 dependency{
if (device->IsKhrCreateRenderPass2Supported()) { .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
boost::container::static_vector<VkAttachmentDescription2, MAX_ATTACHMENTS> descriptions2; .pNext = &dependency_barrier,
for (const VkAttachmentDescription& description : descriptions) { .srcSubpass = 0,
descriptions2.push_back(VkAttachmentDescription2{ .dstSubpass = 0,
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, .srcStageMask = 0,
.pNext = nullptr, .dstStageMask = 0,
.flags = description.flags, .srcAccessMask = 0,
.format = description.format, .dstAccessMask = 0,
.samples = description.samples, .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
.loadOp = description.loadOp, .viewOffset = 0,
.storeOp = description.storeOp, };
.stencilLoadOp = description.stencilLoadOp, pair->second = device->GetLogical().CreateRenderPass2({
.stencilStoreOp = description.stencilStoreOp, .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
.initialLayout = description.initialLayout,
.finalLayout = description.finalLayout,
});
}
const auto promote = [](const VkAttachmentReference& reference) {
return VkAttachmentReference2{
.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
.pNext = nullptr,
.attachment = reference.attachment,
.layout = reference.layout,
.aspectMask = 0,
};
};
std::array<VkAttachmentReference2, 8> references2{};
std::array<VkAttachmentReference2, 8> resolve_references2{};
for (size_t index = 0; index < references.size(); ++index) {
references2[index] = promote(references[index]);
resolve_references2[index] = promote(resolve_references[index]);
}
const VkAttachmentReference2 depth_reference2 = promote(depth_reference);
const VkAttachmentReference2 depth_resolve_reference2 = promote(depth_resolve_reference);
const ResolveModes resolve_modes = PickResolveModes(*device, key.depth_format);
const VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
.pNext = nullptr,
.depthResolveMode = resolve_modes.depth,
.stencilResolveMode = resolve_modes.stencil,
.pDepthStencilResolveAttachment = &depth_resolve_reference2,
};
const VkSubpassDescription2 subpass2{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
.pNext = do_resolve_depth_stencil ? &depth_stencil_resolve : nullptr,
.flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.viewMask = 0,
.inputAttachmentCount = 0,
.pInputAttachments = nullptr,
.colorAttachmentCount = num_attachments,
.pColorAttachments = references2.data(),
.pResolveAttachments = do_resolve_color ? resolve_references2.data() : nullptr,
.pDepthStencilAttachment = has_depth ? &depth_reference2 : nullptr,
.preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr,
};
const VkSubpassDependency2 dependency2{
.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
.pNext = nullptr,
.srcSubpass = dependency.srcSubpass,
.dstSubpass = dependency.dstSubpass,
.srcStageMask = dependency.srcStageMask,
.dstStageMask = dependency.dstStageMask,
.srcAccessMask = dependency.srcAccessMask,
.dstAccessMask = dependency.dstAccessMask,
.dependencyFlags = dependency.dependencyFlags,
.viewOffset = 0,
};
pair->second = device->GetLogical().CreateRenderPass2({
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
.pNext = nullptr,
.flags = 0,
.attachmentCount = static_cast<u32>(descriptions2.size()),
.pAttachments = descriptions2.empty() ? nullptr : descriptions2.data(),
.subpassCount = 1,
.pSubpasses = &subpass2,
.dependencyCount = 1,
.pDependencies = &dependency2,
.correlatedViewMaskCount = 0,
.pCorrelatedViewMasks = nullptr,
});
return *pair->second;
}
pair->second = device->GetLogical().CreateRenderPass({
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.attachmentCount = static_cast<u32>(descriptions.size()), .attachmentCount = static_cast<u32>(descriptions.size()),
@@ -337,6 +288,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
.pSubpasses = &subpass, .pSubpasses = &subpass,
.dependencyCount = 1, .dependencyCount = 1,
.pDependencies = &dependency, .pDependencies = &dependency,
.correlatedViewMaskCount = 0,
.pCorrelatedViewMasks = nullptr,
}); });
return *pair->second; return *pair->second;
} }
+35 -29
View File
@@ -343,13 +343,15 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
const u64 signal_value = master_semaphore->NextTick(); const u64 signal_value = master_semaphore->NextTick();
RecordWithUploadBuffer([signal_semaphore, wait_semaphore, signal_value, RecordWithUploadBuffer([signal_semaphore, wait_semaphore, signal_value,
this](vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) { this](vk::CommandBuffer cmdbuf, vk::CommandBuffer upload_cmdbuf) {
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER); upload_cmdbuf.PipelineBarrier(WRITE_BARRIER);
upload_cmdbuf.End(); upload_cmdbuf.End();
cmdbuf.End(); cmdbuf.End();
@@ -365,7 +367,7 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
if (GPU::Logging::IsActive() && if (GPU::Logging::IsActive() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) { Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogVulkanCall( GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
"vkQueueSubmit", "", VK_SUCCESS); "vkQueueSubmit2", "", VK_SUCCESS);
} }
break; break;
case VK_ERROR_DEVICE_LOST: case VK_ERROR_DEVICE_LOST:
@@ -416,7 +418,7 @@ void Scheduler::EndRenderPass()
ranges = renderpass_image_ranges, ranges = renderpass_image_ranges,
has_transform_feedback = device.IsExtTransformFeedbackSupported()]( has_transform_feedback = device.IsExtTransformFeedbackSupported()](
vk::CommandBuffer cmdbuf) { vk::CommandBuffer cmdbuf) {
std::array<VkImageMemoryBarrier, 9> barriers; std::array<VkImageMemoryBarrier2, 9> barriers;
for (size_t i = 0; i < num_images; ++i) { for (size_t i = 0; i < num_images; ++i) {
const VkImageSubresourceRange& range = ranges[i]; const VkImageSubresourceRange& range = ranges[i];
const bool is_color = (range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0; const bool is_color = (range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
@@ -424,25 +426,29 @@ void Scheduler::EndRenderPass()
& (VK_IMAGE_ASPECT_DEPTH_BIT & (VK_IMAGE_ASPECT_DEPTH_BIT
| VK_IMAGE_ASPECT_STENCIL_BIT)) !=0; | VK_IMAGE_ASPECT_STENCIL_BIT)) !=0;
VkAccessFlags src_access = 0; VkAccessFlags2 src_access = 0;
if (is_color) if (is_color)
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; src_access |= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
else if (is_depth_stencil) else if (is_depth_stencil)
src_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; src_access |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
else else
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT src_access |= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
barriers[i] = VkImageMemoryBarrier{ barriers[i] = VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
| VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = src_access, .srcAccessMask = src_access,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -452,19 +458,19 @@ void Scheduler::EndRenderPass()
}; };
} }
cmdbuf.EndRenderPass(); cmdbuf.EndRenderPass();
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | cmdbuf.PipelineBarrier(0, {}, {}, vk::Span(barriers.data(), num_images));
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, nullptr, nullptr, vk::Span(barriers.data(), num_images));
if (has_transform_feedback) { if (has_transform_feedback) {
static constexpr VkMemoryBarrier XFB_OUTPUT_BARRIER{ static constexpr VkMemoryBarrier2 XFB_OUTPUT_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT,
.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT
| VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT
| VK_ACCESS_2_TRANSFER_READ_BIT,
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, cmdbuf.PipelineBarrier(XFB_OUTPUT_BARRIER);
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
0, XFB_OUTPUT_BARRIER);
} }
}); });
@@ -689,12 +689,12 @@ struct RangedBarrierRange {
void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image, void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image,
VkImageAspectFlags aspect_mask, bool is_initialized, VkImageAspectFlags aspect_mask, bool is_initialized,
std::span<const VkBufferImageCopy> copies) { std::span<const VkBufferImageCopy> copies) {
static constexpr VkAccessFlags WRITE_ACCESS_FLAGS = static constexpr VkAccessFlags2 WRITE_ACCESS_FLAGS =
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
static constexpr VkAccessFlags READ_ACCESS_FLAGS = VK_ACCESS_SHADER_READ_BIT | static constexpr VkAccessFlags2 READ_ACCESS_FLAGS = VK_ACCESS_2_SHADER_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
// Compute exact mip/layer range being written to // Compute exact mip/layer range being written to
RangedBarrierRange range; RangedBarrierRange range;
@@ -703,11 +703,15 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
} }
const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask); const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask);
const VkImageMemoryBarrier read_barrier{ const VkImageMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
.srcAccessMask = WRITE_ACCESS_FLAGS, .srcAccessMask = WRITE_ACCESS_FLAGS,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -716,10 +720,14 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}; };
const VkImageMemoryBarrier write_barrier{ const VkImageMemoryBarrier2 write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstAccessMask = WRITE_ACCESS_FLAGS | READ_ACCESS_FLAGS, .dstAccessMask = WRITE_ACCESS_FLAGS | READ_ACCESS_FLAGS,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -729,18 +737,10 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | cmdbuf.PipelineBarrier(read_barrier);
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
read_barrier);
cmdbuf.CopyBufferToImage(src_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copies); cmdbuf.CopyBufferToImage(src_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copies);
// TODO: Move this to another API // TODO: Move this to another API
cmdbuf.PipelineBarrier( cmdbuf.PipelineBarrier(0, {}, {}, write_barrier);
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, nullptr, nullptr, write_barrier);
} }
[[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region,
@@ -940,11 +940,13 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}; };
const std::array read_barriers{ const std::array read_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -952,13 +954,15 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.image = src_image, .image = src_image,
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, // Discard contents .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, // Discard contents
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -968,11 +972,13 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
}, },
}; };
const std::array write_barriers{ const std::array write_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT, .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -980,11 +986,13 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.image = src_image, .image = src_image,
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT | VK_ACCESS_2_MEMORY_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -993,12 +1001,10 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.subresourceRange = subresource_range, .subresourceRange = subresource_range,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, read_barriers);
0, nullptr, nullptr, read_barriers);
cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image, cmdbuf.BlitImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions, vk_filter);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(0, {}, {}, write_barriers);
0, nullptr, nullptr, write_barriers);
}); });
} }
} // Anonymous namespace } // Anonymous namespace
@@ -1253,26 +1259,32 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
for (const VkBufferImageCopy& copy : vk_out_copies) { for (const VkBufferImageCopy& copy : vk_out_copies) {
dst_range.AddLayers(copy.imageSubresource); dst_range.AddLayers(copy.imageSubresource);
} }
static constexpr VkMemoryBarrier READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
}; };
static constexpr VkMemoryBarrier WRITE_BARRIER{ static constexpr VkMemoryBarrier2 WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
const std::array pre_barriers{ const std::array pre_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1282,10 +1294,12 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
}, },
}; };
const std::array middle_in_barrier{ const std::array middle_in_barrier{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = 0, .dstAccessMask = 0,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1296,13 +1310,15 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
}, },
}; };
const std::array middle_out_barrier{ const std::array middle_out_barrier{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1312,16 +1328,18 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
}, },
}; };
const std::array post_barriers{ const std::array post_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1330,19 +1348,15 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
.subresourceRange = dst_range.SubresourceRange(dst_aspect_mask), .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers);
0, {}, {}, pre_barriers);
cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer, cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
vk_in_copies); vk_in_copies);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(0, WRITE_BARRIER, {}, middle_in_barrier);
0, WRITE_BARRIER, nullptr, middle_in_barrier);
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, READ_BARRIER, {}, middle_out_barrier);
0, READ_BARRIER, {}, middle_out_barrier);
cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies); cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(0, {}, {}, post_barriers);
0, {}, {}, post_barriers);
}); });
} }
@@ -1421,13 +1435,15 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
scheduler.Record([filter, dst_region, src_region, dst_image, src_image, dst_layers, src_layers, scheduler.Record([filter, dst_region, src_region, dst_image, src_image, dst_layers, src_layers,
aspect_mask, is_resolve](vk::CommandBuffer cmdbuf) { aspect_mask, is_resolve](vk::CommandBuffer cmdbuf) {
const std::array read_barriers{ const std::array read_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1441,13 +1457,15 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1462,14 +1480,16 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
}, },
}, },
}; };
VkImageMemoryBarrier write_barrier{ VkImageMemoryBarrier2 write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1483,8 +1503,7 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, read_barriers);
0, nullptr, nullptr, read_barriers);
if (is_resolve) { if (is_resolve) {
cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, cmdbuf.ResolveImage(src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@@ -1496,8 +1515,7 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, src_image, VK_IMAGE_LAYOUT_GENERAL, dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
MakeImageBlit(dst_region, src_region, dst_layers, src_layers), vk_filter); MakeImageBlit(dst_region, src_region, dst_layers, src_layers), vk_filter);
} }
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(write_barrier);
0, write_barrier);
}); });
} }
@@ -1661,13 +1679,18 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
src_range.AddLayers(copy.srcSubresource); src_range.AddLayers(copy.srcSubresource);
} }
const std::array pre_barriers{ const std::array pre_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .srcStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1675,13 +1698,18 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
.image = src_image, .image = src_image,
.subresourceRange = src_range.SubresourceRange(aspect_mask), .subresourceRange = src_range.SubresourceRange(aspect_mask),
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | .srcStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1691,10 +1719,15 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
}, },
}; };
const std::array post_barriers{ const std::array post_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = 0, .dstAccessMask = 0,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1703,16 +1736,21 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
.image = src_image, .image = src_image,
.subresourceRange = src_range.SubresourceRange(aspect_mask), .subresourceRange = src_range.SubresourceRange(aspect_mask),
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | .dstStageMask = VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT |
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1721,18 +1759,10 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
.subresourceRange = dst_range.SubresourceRange(aspect_mask), .subresourceRange = dst_range.SubresourceRange(aspect_mask),
}, },
}; };
cmdbuf.PipelineBarrier( cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers);
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0, nullptr, nullptr, pre_barriers);
cmdbuf.CopyImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image, cmdbuf.CopyImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VideoCommon::FixSmallVectorADL(vk_copies)); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VideoCommon::FixSmallVectorADL(vk_copies));
cmdbuf.PipelineBarrier( cmdbuf.PipelineBarrier(0, {}, {}, post_barriers);
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
0, nullptr, nullptr, post_barriers);
}); });
} }
@@ -1752,16 +1782,16 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
static_cast<u32>(copy.src_subresource.base_layer + copy.src_subresource.num_layers) <= static_cast<u32>(copy.src_subresource.base_layer + copy.src_subresource.num_layers) <=
shadow->layers) { shadow->layers) {
const VkImageAspectFlags aspect_mask = shadow->aspect_mask; const VkImageAspectFlags aspect_mask = shadow->aspect_mask;
VkPipelineStageFlags attachment_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkPipelineStageFlags2 attachment_stage = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
VkAccessFlags attachment_write = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkAccessFlags2 attachment_write = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
VkAccessFlags attachment_read_write = VkAccessFlags2 attachment_read_write =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) { if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) {
attachment_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | attachment_stage = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT;
attachment_write = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; attachment_write = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
attachment_read_write = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | attachment_read_write = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
} }
const VkImage shadow_image = *shadow->image; const VkImage shadow_image = *shadow->image;
const VkImage dst_image = dst.Handle(); const VkImage dst_image = dst.Handle();
@@ -1787,11 +1817,13 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
attachment_write, attachment_write,
attachment_read_write](vk::CommandBuffer cmdbuf) { attachment_read_write](vk::CommandBuffer cmdbuf) {
const std::array pre_barriers{ const std::array pre_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = attachment_stage | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = attachment_write, .srcAccessMask = attachment_write,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1800,12 +1832,14 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
.subresourceRange{aspect_mask, 0, VK_REMAINING_MIP_LEVELS, 0, .subresourceRange{aspect_mask, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS}, VK_REMAINING_ARRAY_LAYERS},
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | attachment_write | .srcStageMask = attachment_stage | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | attachment_write |
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1816,10 +1850,12 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
}, },
}; };
const std::array post_barriers{ const std::array post_barriers{
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.dstAccessMask = 0, .dstAccessMask = 0,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -1829,12 +1865,14 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
.subresourceRange{aspect_mask, 0, VK_REMAINING_MIP_LEVELS, 0, .subresourceRange{aspect_mask, 0, VK_REMAINING_MIP_LEVELS, 0,
VK_REMAINING_ARRAY_LAYERS}, VK_REMAINING_ARRAY_LAYERS},
}, },
VkImageMemoryBarrier{ VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | attachment_read_write | .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT | attachment_read_write |
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -1844,14 +1882,10 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
VK_REMAINING_ARRAY_LAYERS}, VK_REMAINING_ARRAY_LAYERS},
}, },
}; };
cmdbuf.PipelineBarrier(attachment_stage | VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers);
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, nullptr,
pre_barriers);
cmdbuf.CopyImage(shadow_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image, cmdbuf.CopyImage(shadow_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(0, {}, {}, post_barriers);
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, nullptr,
post_barriers);
}); });
return; return;
} }
@@ -2148,23 +2182,25 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
const VkImage temp_vk_image = runtime->AcquireMsaaScratchImage(image_ci); const VkImage temp_vk_image = runtime->AcquireMsaaScratchImage(image_ci);
const VkImageAspectFlags temp_aspect_mask = aspect_mask; const VkImageAspectFlags temp_aspect_mask = aspect_mask;
const VkAccessFlags attachment_access = const VkAccessFlags2 attachment_access =
msaa_download_is_depth ? (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | msaa_download_is_depth ? (VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
: (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | : (VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT);
const VkPipelineStageFlags attachment_stage = const VkPipelineStageFlags2 attachment_stage =
msaa_download_is_depth ? (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | msaa_download_is_depth ? (VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT)
: VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; : VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
scheduler->RequestOutsideRenderPassOperationContext(); scheduler->RequestOutsideRenderPassOperationContext();
scheduler->Record([temp_vk_image, temp_aspect_mask, attachment_access, scheduler->Record([temp_vk_image, temp_aspect_mask, attachment_access,
attachment_stage](vk::CommandBuffer cmdbuf) { attachment_stage](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier init_barrier{ const VkImageMemoryBarrier2 init_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstStageMask = attachment_stage,
.dstAccessMask = attachment_access, .dstAccessMask = attachment_access,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
@@ -2179,8 +2215,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, attachment_stage, 0, cmdbuf.PipelineBarrier(init_barrier);
init_barrier);
}); });
boost::container::small_vector<VideoCommon::ImageCopy, 16> image_copies; boost::container::small_vector<VideoCommon::ImageCopy, 16> image_copies;
@@ -2220,11 +2255,13 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
scheduler->RequestOutsideRenderPassOperationContext(); scheduler->RequestOutsideRenderPassOperationContext();
scheduler->Record([buffers = std::move(buffers_vector), image = temp_vk_image, scheduler->Record([buffers = std::move(buffers_vector), image = temp_vk_image,
aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier read_barrier{ const VkImageMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -2238,25 +2275,28 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(read_barrier);
0, read_barrier);
for (size_t index = 0; index < buffers.size(); index++) { for (size_t index = 0; index < buffers.size(); index++) {
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffers[index], cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffers[index],
vk_copies[index]); vk_copies[index]);
} }
const VkMemoryBarrier memory_write_barrier{ const VkMemoryBarrier2 memory_write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
const VkImageMemoryBarrier image_write_barrier{ const VkImageMemoryBarrier2 image_write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -2270,8 +2310,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(0, memory_write_barrier, {}, image_write_barrier);
0, memory_write_barrier, nullptr, image_write_barrier);
}); });
runtime->ReleaseMsaaScratchImage(temp_vk_image); runtime->ReleaseMsaaScratchImage(temp_vk_image);
} }
@@ -2291,11 +2330,13 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
scheduler->RequestOutsideRenderPassOperationContext(); scheduler->RequestOutsideRenderPassOperationContext();
scheduler->Record([buffers = std::move(buffers_vector), image = *original_image, scheduler->Record([buffers = std::move(buffers_vector), image = *original_image,
aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier read_barrier{ const VkImageMemoryBarrier2 read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
.oldLayout = VK_IMAGE_LAYOUT_GENERAL, .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -2309,25 +2350,28 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, cmdbuf.PipelineBarrier(read_barrier);
0, read_barrier);
for (size_t index = 0; index < buffers.size(); index++) { for (size_t index = 0; index < buffers.size(); index++) {
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffers[index], cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffers[index],
vk_copies[index]); vk_copies[index]);
} }
const VkMemoryBarrier memory_write_barrier{ const VkMemoryBarrier2 memory_write_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
}; };
const VkImageMemoryBarrier image_write_barrier{ const VkImageMemoryBarrier2 image_write_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, .dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -2341,8 +2385,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
.layerCount = VK_REMAINING_ARRAY_LAYERS, .layerCount = VK_REMAINING_ARRAY_LAYERS,
}, },
}; };
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(0, memory_write_barrier, {}, image_write_barrier);
0, memory_write_barrier, nullptr, image_write_barrier);
}); });
} }
@@ -3198,11 +3241,13 @@ void TextureCacheRuntime::AccelerateImageUpload(
void TextureCacheRuntime::TransitionImageLayout(Image& image) { void TextureCacheRuntime::TransitionImageLayout(Image& image) {
if (!image.ExchangeInitialization()) { if (!image.ExchangeInitialization()) {
VkImageMemoryBarrier barrier{ VkImageMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr, .pNext = nullptr,
.srcAccessMask = VK_ACCESS_NONE, .srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, .srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL, .newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -3218,8 +3263,7 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) {
}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([barrier](vk::CommandBuffer cmdbuf) { scheduler.Record([barrier](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, cmdbuf.PipelineBarrier(barrier);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, barrier);
}); });
} }
} }
@@ -208,16 +208,22 @@ void TurboMode::Run(std::stop_token stop_token) {
// Finish. // Finish.
cmdbuf.End(); cmdbuf.End();
const VkSubmitInfo submit_info{ const VkCommandBufferSubmitInfo cmdbuf_info{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.pNext = nullptr, .pNext = nullptr,
.waitSemaphoreCount = 0, .commandBuffer = *cmdbuf,
.pWaitSemaphores = nullptr, .deviceMask = 0,
.pWaitDstStageMask = nullptr, };
.commandBufferCount = 1, const VkSubmitInfo2 submit_info{
.pCommandBuffers = cmdbuf.address(), .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.signalSemaphoreCount = 0, .pNext = nullptr,
.pSignalSemaphores = nullptr, .flags = 0,
.waitSemaphoreInfoCount = 0,
.pWaitSemaphoreInfos = nullptr,
.commandBufferInfoCount = 1,
.pCommandBufferInfos = &cmdbuf_info,
.signalSemaphoreInfoCount = 0,
.pSignalSemaphoreInfos = nullptr,
}; };
m_device.GetGraphicsQueue().Submit(std::array{submit_info}, *fence); m_device.GetGraphicsQueue().Submit(std::array{submit_info}, *fence);
@@ -1427,10 +1427,10 @@ void Device::RemoveUnsuitableExtensions() {
VK_KHR_MAINTENANCE_5_EXTENSION_NAME); VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
// VK_KHR_synchronization2
extensions.synchronization2 = features.synchronization2.synchronization2; extensions.synchronization2 = features.synchronization2.synchronization2;
RemoveExtensionFeatureIfUnsuitable(extensions.synchronization2, features.synchronization2, if (!extensions.synchronization2 || !IsKhrCreateRenderPass2Supported()) {
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
}
} }
void Device::SetupFamilies(VkSurfaceKHR surface) { void Device::SetupFamilies(VkSurfaceKHR surface) {
+1 -7
View File
@@ -640,8 +640,7 @@ FN_MAX_LIMIT_LIST
/// Returns true if the device supports VK_KHR_depth_stencil_resolve. /// Returns true if the device supports VK_KHR_depth_stencil_resolve.
bool IsKhrDepthStencilResolveSupported() const { bool IsKhrDepthStencilResolveSupported() const {
return (extensions.depth_stencil_resolve || instance_version >= VK_API_VERSION_1_2) && return extensions.depth_stencil_resolve || instance_version >= VK_API_VERSION_1_2;
IsKhrCreateRenderPass2Supported();
} }
/// Returns the supported resolve modes for the depth aspect. /// Returns the supported resolve modes for the depth aspect.
@@ -905,11 +904,6 @@ FN_MAX_LIMIT_LIST
bool HasTimelineSemaphore() const; bool HasTimelineSemaphore() const;
/// Returns true if the device supports VK_KHR_synchronization2.
bool HasSynchronization2() const {
return extensions.synchronization2;
}
/// Returns the minimum supported version of SPIR-V. /// Returns the minimum supported version of SPIR-V.
u32 SupportedSpirvVersion() const { u32 SupportedSpirvVersion() const {
if (instance_version >= VK_API_VERSION_1_3) { if (instance_version >= VK_API_VERSION_1_3) {
@@ -123,7 +123,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdEndTransformFeedbackEXT); X(vkCmdEndTransformFeedbackEXT);
X(vkCmdEndDebugUtilsLabelEXT); X(vkCmdEndDebugUtilsLabelEXT);
X(vkCmdFillBuffer); X(vkCmdFillBuffer);
X(vkCmdPipelineBarrier);
X(vkCmdPipelineBarrier2); X(vkCmdPipelineBarrier2);
X(vkCmdPushConstants); X(vkCmdPushConstants);
X(vkCmdPushDescriptorSetWithTemplateKHR); X(vkCmdPushDescriptorSetWithTemplateKHR);
@@ -131,13 +130,13 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetDepthBias); X(vkCmdSetDepthBias);
X(vkCmdSetDepthBias2EXT); X(vkCmdSetDepthBias2EXT);
X(vkCmdSetDepthBounds); X(vkCmdSetDepthBounds);
X(vkCmdSetEvent); X(vkCmdSetEvent2);
X(vkCmdSetScissor); X(vkCmdSetScissor);
X(vkCmdSetStencilCompareMask); X(vkCmdSetStencilCompareMask);
X(vkCmdSetStencilReference); X(vkCmdSetStencilReference);
X(vkCmdSetStencilWriteMask); X(vkCmdSetStencilWriteMask);
X(vkCmdSetViewport); X(vkCmdSetViewport);
X(vkCmdWaitEvents); X(vkCmdWaitEvents2);
X(vkCmdBindVertexBuffers2EXT); X(vkCmdBindVertexBuffers2EXT);
X(vkCmdSetCullModeEXT); X(vkCmdSetCullModeEXT);
X(vkCmdSetDepthBoundsTestEnableEXT); X(vkCmdSetDepthBoundsTestEnableEXT);
@@ -232,7 +231,6 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkGetSemaphoreCounterValue); X(vkGetSemaphoreCounterValue);
X(vkMapMemory); X(vkMapMemory);
X(vkQueueBindSparse); X(vkQueueBindSparse);
X(vkQueueSubmit);
X(vkQueueSubmit2); X(vkQueueSubmit2);
X(vkResetFences); X(vkResetFences);
X(vkResetQueryPool); X(vkResetQueryPool);
@@ -280,6 +278,12 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
if (!dld.vkQueueSubmit2) { if (!dld.vkQueueSubmit2) {
Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device); Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device);
} }
if (!dld.vkCmdSetEvent2) {
Proc(dld.vkCmdSetEvent2, dld, "vkCmdSetEvent2KHR", device);
}
if (!dld.vkCmdWaitEvents2) {
Proc(dld.vkCmdWaitEvents2, dld, "vkCmdWaitEvents2KHR", device);
}
if (!dld.vkCreateRenderPass2) { if (!dld.vkCreateRenderPass2) {
Proc(dld.vkCreateRenderPass2, dld, "vkCreateRenderPass2KHR", device); Proc(dld.vkCreateRenderPass2, dld, "vkCreateRenderPass2KHR", device);
+49 -115
View File
@@ -147,16 +147,16 @@ inline VkResult Filter(VkResult result) {
return result; return result;
} }
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE = inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_GRAPHICS_COMPUTE =
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER = inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER =
PIPELINE_STAGE_GRAPHICS_COMPUTE | VK_PIPELINE_STAGE_TRANSFER_BIT; PIPELINE_STAGE_GRAPHICS_COMPUTE | VK_PIPELINE_STAGE_2_TRANSFER_BIT;
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST = inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_HOST =
PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER | VK_PIPELINE_STAGE_HOST_BIT; PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER | VK_PIPELINE_STAGE_2_HOST_BIT;
inline constexpr VkPipelineStageFlags PIPELINE_STAGE_HOST = VK_PIPELINE_STAGE_HOST_BIT; inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_HOST = VK_PIPELINE_STAGE_2_HOST_BIT;
/// Table holding Vulkan instance function pointers. /// Table holding Vulkan instance function pointers.
@@ -239,7 +239,6 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdEndRenderPass vkCmdEndRenderPass{}; PFN_vkCmdEndRenderPass vkCmdEndRenderPass{};
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{};
PFN_vkCmdFillBuffer vkCmdFillBuffer{}; PFN_vkCmdFillBuffer vkCmdFillBuffer{};
PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{};
PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2{}; PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2{};
PFN_vkCmdPushConstants vkCmdPushConstants{}; PFN_vkCmdPushConstants vkCmdPushConstants{};
PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{}; PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{};
@@ -265,7 +264,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{}; PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{};
PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT{}; PFN_vkCmdSetLogicOpEnableEXT vkCmdSetLogicOpEnableEXT{};
PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT{}; PFN_vkCmdSetDepthClampEnableEXT vkCmdSetDepthClampEnableEXT{};
PFN_vkCmdSetEvent vkCmdSetEvent{}; PFN_vkCmdSetEvent2 vkCmdSetEvent2{};
PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{}; PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{};
PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT{}; PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT{};
PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{}; PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{};
@@ -283,7 +282,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT{}; PFN_vkCmdSetColorWriteEnableEXT vkCmdSetColorWriteEnableEXT{};
PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{}; PFN_vkCmdSetColorBlendEnableEXT vkCmdSetColorBlendEnableEXT{};
PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{}; PFN_vkCmdSetColorBlendEquationEXT vkCmdSetColorBlendEquationEXT{};
PFN_vkCmdWaitEvents vkCmdWaitEvents{}; PFN_vkCmdWaitEvents2 vkCmdWaitEvents2{};
PFN_vkCreateBuffer vkCreateBuffer{}; PFN_vkCreateBuffer vkCreateBuffer{};
PFN_vkCreateBufferView vkCreateBufferView{}; PFN_vkCreateBufferView vkCreateBufferView{};
PFN_vkCreateCommandPool vkCreateCommandPool{}; PFN_vkCreateCommandPool vkCreateCommandPool{};
@@ -348,7 +347,6 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{}; PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{};
PFN_vkMapMemory vkMapMemory{}; PFN_vkMapMemory vkMapMemory{};
PFN_vkQueueBindSparse vkQueueBindSparse{}; PFN_vkQueueBindSparse vkQueueBindSparse{};
PFN_vkQueueSubmit vkQueueSubmit{};
PFN_vkQueueSubmit2 vkQueueSubmit2{}; PFN_vkQueueSubmit2 vkQueueSubmit2{};
PFN_vkResetFences vkResetFences{}; PFN_vkResetFences vkResetFences{};
PFN_vkResetQueryPool vkResetQueryPool{}; PFN_vkResetQueryPool vkResetQueryPool{};
@@ -848,13 +846,7 @@ public:
constexpr Queue(VkQueue queue_, const DeviceDispatch& dld_) noexcept constexpr Queue(VkQueue queue_, const DeviceDispatch& dld_) noexcept
: queue{queue_}, dld{&dld_} {} : queue{queue_}, dld{&dld_} {}
VkResult Submit(Span<VkSubmitInfo> submit_infos, VkResult Submit(Span<VkSubmitInfo2> submit_infos,
VkFence fence = VK_NULL_HANDLE) const noexcept {
return dld->vkQueueSubmit(queue, submit_infos.size(), submit_infos.data(), fence);
}
/// Submits using VK_KHR_synchronization2 / Vulkan 1.3 vkQueueSubmit2.
VkResult Submit2(Span<VkSubmitInfo2> submit_infos,
VkFence fence = VK_NULL_HANDLE) const noexcept { VkFence fence = VK_NULL_HANDLE) const noexcept {
return dld->vkQueueSubmit2(queue, submit_infos.size(), submit_infos.data(), fence); return dld->vkQueueSubmit2(queue, submit_infos.size(), submit_infos.data(), fence);
} }
@@ -1371,103 +1363,50 @@ public:
dld->vkCmdDispatchIndirect(handle, indirect_buffer, offset); dld->vkCmdDispatchIndirect(handle, indirect_buffer, offset);
} }
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, void PipelineBarrier(VkDependencyFlags dependency_flags,
VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers, Span<VkMemoryBarrier2> memory_barriers,
Span<VkBufferMemoryBarrier> buffer_barriers, Span<VkBufferMemoryBarrier2> buffer_barriers,
Span<VkImageMemoryBarrier> image_barriers) const noexcept { Span<VkImageMemoryBarrier2> image_barriers) const noexcept {
static constexpr u32 MaxBarriers = 16; const VkDependencyInfo dependency_info{
if (dld->vkCmdPipelineBarrier2 && memory_barriers.size() <= MaxBarriers && .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
buffer_barriers.size() <= MaxBarriers && image_barriers.size() <= MaxBarriers) { .pNext = nullptr,
const auto src_stage_mask2 = static_cast<VkPipelineStageFlags2>(src_stage_mask); .dependencyFlags = dependency_flags,
const auto dst_stage_mask2 = static_cast<VkPipelineStageFlags2>(dst_stage_mask); .memoryBarrierCount = memory_barriers.size(),
.pMemoryBarriers = memory_barriers.data(),
std::array<VkMemoryBarrier2, MaxBarriers> memory_barriers2; .bufferMemoryBarrierCount = buffer_barriers.size(),
for (u32 i = 0; i < memory_barriers.size(); ++i) { .pBufferMemoryBarriers = buffer_barriers.data(),
memory_barriers2[i] = VkMemoryBarrier2{ .imageMemoryBarrierCount = image_barriers.size(),
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2, .pImageMemoryBarriers = image_barriers.data(),
.pNext = nullptr, };
.srcStageMask = src_stage_mask2, dld->vkCmdPipelineBarrier2(handle, &dependency_info);
.srcAccessMask = static_cast<VkAccessFlags2>(memory_barriers[i].srcAccessMask),
.dstStageMask = dst_stage_mask2,
.dstAccessMask = static_cast<VkAccessFlags2>(memory_barriers[i].dstAccessMask),
};
}
std::array<VkBufferMemoryBarrier2, MaxBarriers> buffer_barriers2;
for (u32 i = 0; i < buffer_barriers.size(); ++i) {
const auto& barrier = buffer_barriers[i];
buffer_barriers2[i] = VkBufferMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
.pNext = nullptr,
.srcStageMask = src_stage_mask2,
.srcAccessMask = static_cast<VkAccessFlags2>(barrier.srcAccessMask),
.dstStageMask = dst_stage_mask2,
.dstAccessMask = static_cast<VkAccessFlags2>(barrier.dstAccessMask),
.srcQueueFamilyIndex = barrier.srcQueueFamilyIndex,
.dstQueueFamilyIndex = barrier.dstQueueFamilyIndex,
.buffer = barrier.buffer,
.offset = barrier.offset,
.size = barrier.size,
};
}
std::array<VkImageMemoryBarrier2, MaxBarriers> image_barriers2;
for (u32 i = 0; i < image_barriers.size(); ++i) {
const auto& barrier = image_barriers[i];
image_barriers2[i] = VkImageMemoryBarrier2{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
.pNext = nullptr,
.srcStageMask = src_stage_mask2,
.srcAccessMask = static_cast<VkAccessFlags2>(barrier.srcAccessMask),
.dstStageMask = dst_stage_mask2,
.dstAccessMask = static_cast<VkAccessFlags2>(barrier.dstAccessMask),
.oldLayout = barrier.oldLayout,
.newLayout = barrier.newLayout,
.srcQueueFamilyIndex = barrier.srcQueueFamilyIndex,
.dstQueueFamilyIndex = barrier.dstQueueFamilyIndex,
.image = barrier.image,
.subresourceRange = barrier.subresourceRange,
};
}
const VkDependencyInfo dependency_info{
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pNext = nullptr,
.dependencyFlags = dependency_flags,
.memoryBarrierCount = memory_barriers.size(),
.pMemoryBarriers = memory_barriers2.data(),
.bufferMemoryBarrierCount = buffer_barriers.size(),
.pBufferMemoryBarriers = buffer_barriers2.data(),
.imageMemoryBarrierCount = image_barriers.size(),
.pImageMemoryBarriers = image_barriers2.data(),
};
dld->vkCmdPipelineBarrier2(handle, &dependency_info);
return;
}
dld->vkCmdPipelineBarrier(handle, src_stage_mask, dst_stage_mask, dependency_flags,
memory_barriers.size(), memory_barriers.data(),
buffer_barriers.size(), buffer_barriers.data(),
image_barriers.size(), image_barriers.data());
} }
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, void PipelineBarrier(VkPipelineStageFlags2 src_stage_mask, VkPipelineStageFlags2 dst_stage_mask,
VkDependencyFlags dependency_flags = 0) const noexcept { VkDependencyFlags dependency_flags = 0) const noexcept {
PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, {}); const VkMemoryBarrier2 barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.pNext = nullptr,
.srcStageMask = src_stage_mask,
.srcAccessMask = VK_ACCESS_2_NONE,
.dstStageMask = dst_stage_mask,
.dstAccessMask = VK_ACCESS_2_NONE,
};
PipelineBarrier(dependency_flags, barrier, {}, {});
} }
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, void PipelineBarrier(const VkMemoryBarrier2& memory_barrier,
VkDependencyFlags dependency_flags, VkDependencyFlags dependency_flags = 0) const noexcept {
const VkMemoryBarrier& memory_barrier) const noexcept { PipelineBarrier(dependency_flags, memory_barrier, {}, {});
PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, memory_barrier, {}, {});
} }
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, void PipelineBarrier(const VkBufferMemoryBarrier2& buffer_barrier,
VkDependencyFlags dependency_flags, VkDependencyFlags dependency_flags = 0) const noexcept {
const VkBufferMemoryBarrier& buffer_barrier) const noexcept { PipelineBarrier(dependency_flags, {}, buffer_barrier, {});
PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, buffer_barrier, {});
} }
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, void PipelineBarrier(const VkImageMemoryBarrier2& image_barrier,
VkDependencyFlags dependency_flags, VkDependencyFlags dependency_flags = 0) const noexcept {
const VkImageMemoryBarrier& image_barrier) const noexcept { PipelineBarrier(dependency_flags, {}, {}, image_barrier);
PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, image_barrier);
} }
void BindDescriptorBuffersEXT(Span<VkDescriptorBufferBindingInfoEXT> bindings) const noexcept { void BindDescriptorBuffersEXT(Span<VkDescriptorBufferBindingInfoEXT> bindings) const noexcept {
@@ -1572,17 +1511,12 @@ public:
dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds); dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds);
} }
void SetEvent(VkEvent event, VkPipelineStageFlags stage_flags) const noexcept { void SetEvent(VkEvent event, const VkDependencyInfo& dependency_info) const noexcept {
dld->vkCmdSetEvent(handle, event, stage_flags); dld->vkCmdSetEvent2(handle, event, &dependency_info);
} }
void WaitEvents(Span<VkEvent> events, VkPipelineStageFlags src_stage_mask, void WaitEvents(Span<VkEvent> events, const VkDependencyInfo& dependency_info) const noexcept {
VkPipelineStageFlags dst_stage_mask, Span<VkMemoryBarrier> memory_barriers, dld->vkCmdWaitEvents2(handle, events.size(), events.data(), &dependency_info);
Span<VkBufferMemoryBarrier> buffer_barriers,
Span<VkImageMemoryBarrier> image_barriers) const noexcept {
dld->vkCmdWaitEvents(handle, events.size(), events.data(), src_stage_mask, dst_stage_mask,
memory_barriers.size(), memory_barriers.data(), buffer_barriers.size(),
buffer_barriers.data(), image_barriers.size(), image_barriers.data());
} }
void BindVertexBuffers2EXT(u32 first_binding, u32 binding_count, const VkBuffer* buffers, void BindVertexBuffers2EXT(u32 first_binding, u32 binding_count, const VkBuffer* buffers,