Use copy commands 2

This commit is contained in:
CamilleLaVey
2026-09-30 03:00:07 -04:00
parent efba499fd3
commit 4f5fc58b6e
11 changed files with 193 additions and 106 deletions
@@ -140,8 +140,10 @@ VkImageMemoryBarrier2 MakeTransitionBarrier(VkImage image, VkPipelineStageFlags2
}; };
} }
VkImageCopy MakeCopyRegion(VkExtent2D extent) { VkImageCopy2 MakeCopyRegion(VkExtent2D extent) {
return VkImageCopy{ return VkImageCopy2{
.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2,
.pNext = nullptr,
.srcSubresource{ .srcSubresource{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0, .mipLevel = 0,
@@ -343,7 +343,9 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i
buffer.Flush(); // Ensure host writes are visible before the GPU copy. buffer.Flush(); // Ensure host writes are visible before the GPU copy.
} }
const VkBufferImageCopy copy{ const VkBufferImageCopy2 copy{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = nullptr,
.bufferOffset = image_offset, .bufferOffset = image_offset,
.bufferRowLength = 0, .bufferRowLength = 0,
.bufferImageHeight = 0, .bufferImageHeight = 0,
@@ -89,7 +89,9 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
std::ranges::copy(initial_contents, upload_buffer.Mapped().begin()); std::ranges::copy(initial_contents, upload_buffer.Mapped().begin());
upload_buffer.Flush(); upload_buffer.Flush();
const std::array<VkBufferImageCopy, 1> regions{{{ const VkBufferImageCopy2 region{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = nullptr,
.bufferOffset = 0, .bufferOffset = 0,
.bufferRowLength = dimensions.width, .bufferRowLength = dimensions.width,
.bufferImageHeight = dimensions.height, .bufferImageHeight = dimensions.height,
@@ -99,14 +101,14 @@ void UploadImage(const Device& device, MemoryAllocator& allocator, Scheduler& sc
.layerCount = 1}, .layerCount = 1},
.imageOffset{}, .imageOffset{},
.imageExtent{.width = dimensions.width, .height = dimensions.height, .depth = 1}, .imageExtent{.width = dimensions.width, .height = dimensions.height, .depth = 1},
}}}; };
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([&](vk::CommandBuffer cmdbuf) { scheduler.Record([&](vk::CommandBuffer cmdbuf) {
TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_UNDEFINED); VK_IMAGE_LAYOUT_UNDEFINED);
cmdbuf.CopyBufferToImage(*upload_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cmdbuf.CopyBufferToImage(*upload_buffer, *image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
regions); region);
TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_GENERAL, TransitionImageLayout(cmdbuf, *image, VK_IMAGE_LAYOUT_GENERAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
}); });
@@ -163,7 +165,9 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
.dstStageMask = vk::PIPELINE_STAGE_HOST, .dstStageMask = vk::PIPELINE_STAGE_HOST,
.dstAccessMask = VK_ACCESS_2_HOST_READ_BIT, .dstAccessMask = VK_ACCESS_2_HOST_READ_BIT,
}; };
const VkBufferImageCopy copy{ const VkBufferImageCopy2 copy{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = nullptr,
.bufferOffset = 0, .bufferOffset = 0,
.bufferRowLength = 0, .bufferRowLength = 0,
.bufferImageHeight = 0, .bufferImageHeight = 0,
@@ -36,8 +36,10 @@ struct VertexBindings {
u32 count; u32 count;
}; };
VkBufferCopy MakeBufferCopy(const VideoCommon::BufferCopy& copy) { VkBufferCopy2 MakeBufferCopy(const VideoCommon::BufferCopy& copy) {
return VkBufferCopy{ return VkBufferCopy2{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.srcOffset = copy.src_offset, .srcOffset = copy.src_offset,
.dstOffset = copy.dst_offset, .dstOffset = copy.dst_offset,
.size = copy.size, .size = copy.size,
@@ -234,7 +236,9 @@ public:
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset, scheduler.Record([src_buffer = staging.buffer, src_offset = staging.offset,
dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) { dst_buffer = *buffer, size_bytes](vk::CommandBuffer cmdbuf) {
const VkBufferCopy copy{ const VkBufferCopy2 copy{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.srcOffset = src_offset, .srcOffset = src_offset,
.dstOffset = 0, .dstOffset = 0,
.size = size_bytes, .size = size_bytes,
@@ -500,7 +504,7 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
} }
// 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
boost::container::small_vector<VkBufferCopy, 8> vk_copies(copies.size()); boost::container::small_vector<VkBufferCopy2, 8> vk_copies(copies.size());
std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy); std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy);
if (src_buffer == staging_pool.StreamBuf() && can_reorder_upload) { if (src_buffer == staging_pool.StreamBuf() && can_reorder_upload) {
scheduler.RecordWithUploadBuffer([src_buffer, dst_buffer, vk_copies]( scheduler.RecordWithUploadBuffer([src_buffer, dst_buffer, vk_copies](
@@ -51,9 +51,11 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
}; };
} }
[[nodiscard]] VkImageBlit MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width, [[nodiscard]] VkImageBlit2 MakeImageBlit(s32 frame_width, s32 frame_height, s32 swapchain_width,
s32 swapchain_height) { s32 swapchain_height) {
return VkImageBlit{ return VkImageBlit2{
.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
.pNext = nullptr,
.srcSubresource = MakeImageSubresourceLayers(), .srcSubresource = MakeImageSubresourceLayers(),
.srcOffsets = .srcOffsets =
{ {
@@ -85,9 +87,11 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
}; };
} }
[[nodiscard]] VkImageCopy MakeImageCopy(u32 frame_width, u32 frame_height, u32 swapchain_width, [[nodiscard]] VkImageCopy2 MakeImageCopy(u32 frame_width, u32 frame_height, u32 swapchain_width,
u32 swapchain_height) { u32 swapchain_height) {
return VkImageCopy{ return VkImageCopy2{
.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2,
.pNext = nullptr,
.srcSubresource = MakeImageSubresourceLayers(), .srcSubresource = MakeImageSubresourceLayers(),
.srcOffset = .srcOffset =
{ {
@@ -653,11 +653,13 @@ public:
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start, scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start,
size](vk::CommandBuffer cmdbuf) { size](vk::CommandBuffer cmdbuf) {
std::array<VkBufferCopy, 1> copy{VkBufferCopy{ const VkBufferCopy2 copy{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.srcOffset = start * QUERY_SIZE, .srcOffset = start * QUERY_SIZE,
.dstOffset = extra_offset, .dstOffset = extra_offset,
.size = size * QUERY_SIZE, .size = size * QUERY_SIZE,
}}; };
cmdbuf.CopyBuffer(*buffer, dst_buffer, copy); cmdbuf.CopyBuffer(*buffer, dst_buffer, copy);
}); });
} }
@@ -1040,11 +1042,13 @@ private:
src_offset = offsets[slot_index], src_offset = offsets[slot_index],
slot](vk::CommandBuffer cmdbuf) { slot](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(READ_BARRIER); cmdbuf.PipelineBarrier(READ_BARRIER);
std::array<VkBufferCopy, 1> copy{VkBufferCopy{ const VkBufferCopy2 copy{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.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(WRITE_BARRIER); cmdbuf.PipelineBarrier(WRITE_BARRIER);
}); });
@@ -1339,7 +1343,7 @@ struct QueryCacheRuntimeImpl {
std::vector<std::pair<DAddr, DAddr>> little_cache; std::vector<std::pair<DAddr, DAddr>> little_cache;
std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to; std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to;
std::vector<size_t> redirect_cache; std::vector<size_t> redirect_cache;
std::vector<std::vector<VkBufferCopy>> copies_setup; std::vector<std::vector<VkBufferCopy2>> copies_setup;
// Host conditional rendering data // Host conditional rendering data
std::optional<ConditionalRenderingResolvePass> conditional_resolve_pass; std::optional<ConditionalRenderingResolvePass> conditional_resolve_pass;
@@ -1657,7 +1661,9 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
size_t accumulated_size = 0; size_t accumulated_size = 0;
for (size_t i = 0; i < values.size(); i++) { for (size_t i = 0; i < values.size(); i++) {
size_t which_copy = impl->redirect_cache[i]; size_t which_copy = impl->redirect_cache[i];
impl->copies_setup[which_copy].emplace_back(VkBufferCopy{ impl->copies_setup[which_copy].emplace_back(VkBufferCopy2{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.srcOffset = current_offset + accumulated_size, .srcOffset = current_offset + accumulated_size,
.dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address - .dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address -
impl->little_cache[which_copy].first, impl->little_cache[which_copy].first,
@@ -1671,7 +1677,9 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
} else { } else {
for (size_t i = 0; i < values.size(); i++) { for (size_t i = 0; i < values.size(); i++) {
size_t which_copy = impl->redirect_cache[i]; size_t which_copy = impl->redirect_cache[i];
impl->copies_setup[which_copy].emplace_back(VkBufferCopy{ impl->copies_setup[which_copy].emplace_back(VkBufferCopy2{
.sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2,
.pNext = nullptr,
.srcOffset = values[i].offset, .srcOffset = values[i].offset,
.dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address - .dstOffset = impl->buffers_to_upload_to[which_copy].second + values[i].address -
impl->little_cache[which_copy].first, impl->little_cache[which_copy].first,
@@ -503,9 +503,11 @@ void SanitizeDepthStencilSwizzle(std::array<SwizzleSource, 4>& swizzle,
}; };
} }
[[nodiscard]] VkImageCopy MakeImageCopy(const VideoCommon::ImageCopy& copy, [[nodiscard]] VkImageCopy2 MakeImageCopy(const VideoCommon::ImageCopy& copy,
VkImageAspectFlags aspect_mask) noexcept { VkImageAspectFlags aspect_mask) noexcept {
return VkImageCopy{ return VkImageCopy2{
.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2,
.pNext = nullptr,
.srcSubresource = MakeImageSubresourceLayers(copy.src_subresource, aspect_mask), .srcSubresource = MakeImageSubresourceLayers(copy.src_subresource, aspect_mask),
.srcOffset = MakeOffset3D(copy.src_offset), .srcOffset = MakeOffset3D(copy.src_offset),
.dstSubresource = MakeImageSubresourceLayers(copy.dst_subresource, aspect_mask), .dstSubresource = MakeImageSubresourceLayers(copy.dst_subresource, aspect_mask),
@@ -514,9 +516,12 @@ void SanitizeDepthStencilSwizzle(std::array<SwizzleSource, 4>& swizzle,
}; };
} }
[[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src, [[nodiscard]] VkBufferImageCopy2 MakeBufferImageCopy(const VideoCommon::ImageCopy& copy,
VkImageAspectFlags aspect_mask) noexcept { bool is_src,
return VkBufferImageCopy{ VkImageAspectFlags aspect_mask) noexcept {
return VkBufferImageCopy2{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = nullptr,
.bufferOffset = 0, .bufferOffset = 0,
.bufferRowLength = 0, .bufferRowLength = 0,
.bufferImageHeight = 0, .bufferImageHeight = 0,
@@ -527,25 +532,13 @@ void SanitizeDepthStencilSwizzle(std::array<SwizzleSource, 4>& swizzle,
}; };
} }
[[maybe_unused]] [[nodiscard]] boost::container::small_vector<VkBufferCopy, 16> [[nodiscard]] boost::container::small_vector<VkBufferImageCopy2, 16> TransformBufferImageCopies(
TransformBufferCopies(std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) {
boost::container::small_vector<VkBufferCopy, 16> result(copies.size());
std::ranges::transform(
copies, result.begin(), [buffer_offset](const VideoCommon::BufferCopy& copy) {
return VkBufferCopy{
.srcOffset = static_cast<VkDeviceSize>(copy.src_offset + buffer_offset),
.dstOffset = static_cast<VkDeviceSize>(copy.dst_offset),
.size = static_cast<VkDeviceSize>(copy.size),
};
});
return result;
}
[[nodiscard]] boost::container::small_vector<VkBufferImageCopy, 16> TransformBufferImageCopies(
std::span<const BufferImageCopy> copies, size_t buffer_offset, VkImageAspectFlags aspect_mask) { std::span<const BufferImageCopy> copies, size_t buffer_offset, VkImageAspectFlags aspect_mask) {
struct Maker { struct Maker {
VkBufferImageCopy operator()(const BufferImageCopy& copy) const { VkBufferImageCopy2 operator()(const BufferImageCopy& copy) const {
return VkBufferImageCopy{ return VkBufferImageCopy2{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.pNext = nullptr,
.bufferOffset = copy.buffer_offset + buffer_offset, .bufferOffset = copy.buffer_offset + buffer_offset,
.bufferRowLength = copy.buffer_row_length, .bufferRowLength = copy.buffer_row_length,
.bufferImageHeight = copy.buffer_image_height, .bufferImageHeight = copy.buffer_image_height,
@@ -574,14 +567,14 @@ TransformBufferCopies(std::span<const VideoCommon::BufferCopy> copies, size_t bu
VkImageAspectFlags aspect_mask; VkImageAspectFlags aspect_mask;
}; };
if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
boost::container::small_vector<VkBufferImageCopy, 16> result(copies.size() * 2); boost::container::small_vector<VkBufferImageCopy2, 16> result(copies.size() * 2);
std::ranges::transform(copies, result.begin(), std::ranges::transform(copies, result.begin(),
Maker{buffer_offset, VK_IMAGE_ASPECT_DEPTH_BIT}); Maker{buffer_offset, VK_IMAGE_ASPECT_DEPTH_BIT});
std::ranges::transform(copies, result.begin() + copies.size(), std::ranges::transform(copies, result.begin() + copies.size(),
Maker{buffer_offset, VK_IMAGE_ASPECT_STENCIL_BIT}); Maker{buffer_offset, VK_IMAGE_ASPECT_STENCIL_BIT});
return result; return result;
} else { } else {
boost::container::small_vector<VkBufferImageCopy, 16> result(copies.size()); boost::container::small_vector<VkBufferImageCopy2, 16> result(copies.size());
std::ranges::transform(copies, result.begin(), Maker{buffer_offset, aspect_mask}); std::ranges::transform(copies, result.begin(), Maker{buffer_offset, aspect_mask});
return result; return result;
} }
@@ -688,7 +681,7 @@ 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 VkBufferImageCopy2> copies) {
// Compute exact mip/layer range being written to // Compute exact mip/layer range being written to
RangedBarrierRange range; RangedBarrierRange range;
for (const auto& region : copies) { for (const auto& region : copies) {
@@ -732,10 +725,12 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
cmdbuf.PipelineBarrier(0, {}, {}, write_barrier); cmdbuf.PipelineBarrier(0, {}, {}, write_barrier);
} }
[[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, [[nodiscard]] VkImageBlit2 MakeImageBlit(const Region2D& dst_region, const Region2D& src_region,
const VkImageSubresourceLayers& dst_layers, const VkImageSubresourceLayers& dst_layers,
const VkImageSubresourceLayers& src_layers) { const VkImageSubresourceLayers& src_layers) {
return VkImageBlit{ return VkImageBlit2{
.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
.pNext = nullptr,
.srcSubresource = src_layers, .srcSubresource = src_layers,
.srcOffsets = .srcOffsets =
{ {
@@ -772,11 +767,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
dst_region.end.y - dst_region.start.y == src_region.end.y - src_region.start.y; dst_region.end.y - dst_region.start.y == src_region.end.y - src_region.start.y;
} }
[[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, [[nodiscard]] VkImageResolve2 MakeImageResolve(const Region2D& dst_region,
const Region2D& src_region, const Region2D& src_region,
const VkImageSubresourceLayers& dst_layers, const VkImageSubresourceLayers& dst_layers,
const VkImageSubresourceLayers& src_layers) { const VkImageSubresourceLayers& src_layers) {
return VkImageResolve{ return VkImageResolve2{
.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2,
.pNext = nullptr,
.srcSubresource = src_layers, .srcSubresource = src_layers,
.srcOffset = .srcOffset =
{ {
@@ -879,10 +876,12 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
.x = static_cast<s32>(up_scaling ? scaled_width : extent.width), .x = static_cast<s32>(up_scaling ? scaled_width : extent.width),
.y = static_cast<s32>(up_scaling ? scaled_height : extent.height), .y = static_cast<s32>(up_scaling ? scaled_height : extent.height),
}; };
boost::container::small_vector<VkImageBlit, 4> regions; boost::container::small_vector<VkImageBlit2, 4> regions;
regions.reserve(resources.levels); regions.reserve(resources.levels);
for (s32 level = 0; level < resources.levels; level++) { for (s32 level = 0; level < resources.levels; level++) {
regions.push_back({ regions.push_back({
.sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2,
.pNext = nullptr,
.srcSubresource{ .srcSubresource{
.aspectMask = aspect_mask, .aspectMask = aspect_mask,
.mipLevel = static_cast<u32>(level), .mipLevel = static_cast<u32>(level),
@@ -1237,8 +1236,8 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
if (ENABLE_MSAA_RESOLVE_CONSUME) { if (ENABLE_MSAA_RESOLVE_CONSUME) {
InvalidateResolveShadow(dst.Handle()); InvalidateResolveShadow(dst.Handle());
} }
boost::container::small_vector<VkBufferImageCopy, 16> vk_in_copies(copies.size()); boost::container::small_vector<VkBufferImageCopy2, 16> vk_in_copies(copies.size());
boost::container::small_vector<VkBufferImageCopy, 16> vk_out_copies(copies.size()); boost::container::small_vector<VkBufferImageCopy2, 16> vk_out_copies(copies.size());
const VkImageAspectFlags src_aspect_mask = src.AspectMask(); const VkImageAspectFlags src_aspect_mask = src.AspectMask();
const VkImageAspectFlags dst_aspect_mask = dst.AspectMask(); const VkImageAspectFlags dst_aspect_mask = dst.AspectMask();
@@ -1267,10 +1266,10 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) { vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) {
RangedBarrierRange dst_range; RangedBarrierRange dst_range;
RangedBarrierRange src_range; RangedBarrierRange src_range;
for (const VkBufferImageCopy& copy : vk_in_copies) { for (const VkBufferImageCopy2& copy : vk_in_copies) {
src_range.AddLayers(copy.imageSubresource); src_range.AddLayers(copy.imageSubresource);
} }
for (const VkBufferImageCopy& copy : vk_out_copies) { for (const VkBufferImageCopy2& copy : vk_out_copies) {
dst_range.AddLayers(copy.imageSubresource); dst_range.AddLayers(copy.imageSubresource);
} }
static constexpr VkMemoryBarrier2 READ_BARRIER{ static constexpr VkMemoryBarrier2 READ_BARRIER{
@@ -1397,7 +1396,6 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
} }
}(); }();
// Use shader-based depth/stencil blits if hardware doesn't support the format // Use shader-based depth/stencil blits if hardware doesn't support the format
// Note: MSAA resolves (MSAA->single) use vkCmdResolveImage which works fine
if (!can_blit_depth_stencil) { if (!can_blit_depth_stencil) {
UNIMPLEMENTED_IF(is_src_msaa || is_dst_msaa); UNIMPLEMENTED_IF(is_src_msaa || is_dst_msaa);
blit_image_helper.BlitDepthStencil(dst_framebuffer, src, dst_region, src_region, blit_image_helper.BlitDepthStencil(dst_framebuffer, src, dst_region, src_region,
@@ -1647,7 +1645,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
}; };
return ReinterpretImage(dst, src, std::span{&oneCopy, 1}); return ReinterpretImage(dst, src, std::span{&oneCopy, 1});
} }
boost::container::small_vector<VkImageCopy, 16> vk_copies(copies.size()); boost::container::small_vector<VkImageCopy2, 16> vk_copies(copies.size());
const VkImageAspectFlags aspect_mask = dst.AspectMask(); const VkImageAspectFlags aspect_mask = dst.AspectMask();
ASSERT(aspect_mask == src.AspectMask()); ASSERT(aspect_mask == src.AspectMask());
@@ -1660,7 +1658,7 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
scheduler.Record([dst_image, src_image, aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { scheduler.Record([dst_image, src_image, aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
RangedBarrierRange dst_range; RangedBarrierRange dst_range;
RangedBarrierRange src_range; RangedBarrierRange src_range;
for (const VkImageCopy& copy : vk_copies) { for (const VkImageCopy2& copy : vk_copies) {
dst_range.AddLayers(copy.dstSubresource); dst_range.AddLayers(copy.dstSubresource);
src_range.AddLayers(copy.srcSubresource); src_range.AddLayers(copy.srcSubresource);
} }
@@ -1749,7 +1747,9 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
const VkImageAspectFlags aspect_mask = shadow->aspect_mask; const VkImageAspectFlags aspect_mask = shadow->aspect_mask;
const VkImage shadow_image = *shadow->image; const VkImage shadow_image = *shadow->image;
const VkImage dst_image = dst.Handle(); const VkImage dst_image = dst.Handle();
const VkImageCopy region{ const VkImageCopy2 region{
.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2,
.pNext = nullptr,
.srcSubresource{ .srcSubresource{
.aspectMask = aspect_mask, .aspectMask = aspect_mask,
.mipLevel = 0, .mipLevel = 0,
@@ -2199,7 +2199,8 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
} }
boost::container::small_vector<VkBuffer, 8> buffers_vector{}; boost::container::small_vector<VkBuffer, 8> buffers_vector{};
boost::container::small_vector<boost::container::small_vector<VkBufferImageCopy, 16>, 8> boost::container::small_vector<
boost::container::small_vector<VkBufferImageCopy2, 16>, 8>
vk_copies; vk_copies;
for (size_t index = 0; index < buffers_span.size(); index++) { for (size_t index = 0; index < buffers_span.size(); index++) {
buffers_vector.emplace_back(buffers_span[index]); buffers_vector.emplace_back(buffers_span[index]);
@@ -2278,7 +2279,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
return; return;
} else { } else {
boost::container::small_vector<VkBuffer, 8> buffers_vector{}; boost::container::small_vector<VkBuffer, 8> buffers_vector{};
boost::container::small_vector<boost::container::small_vector<VkBufferImageCopy, 16>, 8> boost::container::small_vector<boost::container::small_vector<VkBufferImageCopy2, 16>, 8>
vk_copies; vk_copies;
for (size_t index = 0; index < buffers_span.size(); index++) { for (size_t index = 0; index < buffers_span.size(); index++) {
buffers_vector.emplace_back(buffers_span[index]); buffers_vector.emplace_back(buffers_span[index]);
@@ -1423,7 +1423,9 @@ void Device::RemoveUnsuitableExtensions() {
extensions.synchronization2 = features.synchronization2.synchronization2; extensions.synchronization2 = features.synchronization2.synchronization2;
extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering; extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering;
if (!extensions.synchronization2 || !extensions.dynamic_rendering) { const bool copy_commands2 =
extensions.copy_commands2 || instance_version >= VK_API_VERSION_1_3;
if (!extensions.synchronization2 || !extensions.dynamic_rendering || !copy_commands2) {
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
} }
} }
@@ -97,6 +97,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \ EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
EXTENSION(EXT, TOOLING_INFO, tooling_info) \ EXTENSION(EXT, TOOLING_INFO, tooling_info) \
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \ EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
EXTENSION(KHR, COPY_COMMANDS_2, copy_commands2) \
EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \ EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \
EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \ EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \ EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
+19 -12
View File
@@ -96,13 +96,13 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdBindPipeline); X(vkCmdBindPipeline);
X(vkCmdBindTransformFeedbackBuffersEXT); X(vkCmdBindTransformFeedbackBuffersEXT);
X(vkCmdBindVertexBuffers); X(vkCmdBindVertexBuffers);
X(vkCmdBlitImage); X(vkCmdBlitImage2);
X(vkCmdClearAttachments); X(vkCmdClearAttachments);
X(vkCmdClearColorImage); X(vkCmdClearColorImage);
X(vkCmdCopyBuffer); X(vkCmdCopyBuffer2);
X(vkCmdCopyBufferToImage); X(vkCmdCopyBufferToImage2);
X(vkCmdCopyImage); X(vkCmdCopyImage2);
X(vkCmdCopyImageToBuffer); X(vkCmdCopyImageToBuffer2);
X(vkCmdCopyQueryPoolResults); X(vkCmdCopyQueryPoolResults);
X(vkCmdDispatch); X(vkCmdDispatch);
X(vkCmdDispatchIndirect); X(vkCmdDispatchIndirect);
@@ -158,7 +158,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetColorBlendEnableEXT); X(vkCmdSetColorBlendEnableEXT);
X(vkCmdSetColorBlendEquationEXT); X(vkCmdSetColorBlendEquationEXT);
X(vkCmdResetQueryPool); X(vkCmdResetQueryPool);
X(vkCmdResolveImage); X(vkCmdResolveImage2);
X(vkCreateBuffer); X(vkCreateBuffer);
X(vkCreateBufferView); X(vkCreateBufferView);
X(vkCreateCommandPool); X(vkCreateCommandPool);
@@ -253,12 +253,19 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device); Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device);
} }
if (!dld.vkCmdBeginRendering) { const auto load_khr = [&](auto& function, const char* name) {
Proc(dld.vkCmdBeginRendering, dld, "vkCmdBeginRenderingKHR", device); if (!function) {
} Proc(function, dld, name, device);
if (!dld.vkCmdEndRendering) { }
Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device); };
} load_khr(dld.vkCmdBeginRendering, "vkCmdBeginRenderingKHR");
load_khr(dld.vkCmdEndRendering, "vkCmdEndRenderingKHR");
load_khr(dld.vkCmdBlitImage2, "vkCmdBlitImage2KHR");
load_khr(dld.vkCmdCopyBuffer2, "vkCmdCopyBuffer2KHR");
load_khr(dld.vkCmdCopyBufferToImage2, "vkCmdCopyBufferToImage2KHR");
load_khr(dld.vkCmdCopyImage2, "vkCmdCopyImage2KHR");
load_khr(dld.vkCmdCopyImageToBuffer2, "vkCmdCopyImageToBuffer2KHR");
load_khr(dld.vkCmdResolveImage2, "vkCmdResolveImage2KHR");
#undef X #undef X
} }
+75 -23
View File
@@ -246,13 +246,13 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT{}; PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT{};
PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers{}; PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers{};
PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{}; PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT{};
PFN_vkCmdBlitImage vkCmdBlitImage{}; PFN_vkCmdBlitImage2 vkCmdBlitImage2{};
PFN_vkCmdClearAttachments vkCmdClearAttachments{}; PFN_vkCmdClearAttachments vkCmdClearAttachments{};
PFN_vkCmdClearColorImage vkCmdClearColorImage{}; PFN_vkCmdClearColorImage vkCmdClearColorImage{};
PFN_vkCmdCopyBuffer vkCmdCopyBuffer{}; PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2{};
PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage{}; PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2{};
PFN_vkCmdCopyImage vkCmdCopyImage{}; PFN_vkCmdCopyImage2 vkCmdCopyImage2{};
PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{}; PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2{};
PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults{}; PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults{};
PFN_vkCmdDispatch vkCmdDispatch{}; PFN_vkCmdDispatch vkCmdDispatch{};
PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect{}; PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect{};
@@ -272,7 +272,7 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdPushConstants vkCmdPushConstants{}; PFN_vkCmdPushConstants vkCmdPushConstants{};
PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{}; PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{};
PFN_vkCmdResetQueryPool vkCmdResetQueryPool{}; PFN_vkCmdResetQueryPool vkCmdResetQueryPool{};
PFN_vkCmdResolveImage vkCmdResolveImage{}; PFN_vkCmdResolveImage2 vkCmdResolveImage2{};
PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{};
PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{};
PFN_vkCmdSetDepthBias vkCmdSetDepthBias{}; PFN_vkCmdSetDepthBias vkCmdSetDepthBias{};
@@ -1274,16 +1274,35 @@ public:
} }
void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, void BlitImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
VkImageLayout dst_layout, Span<VkImageBlit> regions, VkImageLayout dst_layout, Span<VkImageBlit2> regions,
VkFilter filter) const noexcept { VkFilter filter) const noexcept {
dld->vkCmdBlitImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), const VkBlitImageInfo2 info{
regions.data(), filter); .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2,
.pNext = nullptr,
.srcImage = src_image,
.srcImageLayout = src_layout,
.dstImage = dst_image,
.dstImageLayout = dst_layout,
.regionCount = regions.size(),
.pRegions = regions.data(),
.filter = filter,
};
dld->vkCmdBlitImage2(handle, &info);
} }
void ResolveImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, void ResolveImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
VkImageLayout dst_layout, Span<VkImageResolve> regions) { VkImageLayout dst_layout, Span<VkImageResolve2> regions) const noexcept {
dld->vkCmdResolveImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), const VkResolveImageInfo2 info{
regions.data()); .sType = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2,
.pNext = nullptr,
.srcImage = src_image,
.srcImageLayout = src_layout,
.dstImage = dst_image,
.dstImageLayout = dst_layout,
.regionCount = regions.size(),
.pRegions = regions.data(),
};
dld->vkCmdResolveImage2(handle, &info);
} }
void Dispatch(u32 x, u32 y, u32 z) const noexcept { void Dispatch(u32 x, u32 y, u32 z) const noexcept {
@@ -1353,26 +1372,59 @@ public:
} }
void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout, void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout,
Span<VkBufferImageCopy> regions) const noexcept { Span<VkBufferImageCopy2> regions) const noexcept {
dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(), const VkCopyBufferToImageInfo2 info{
regions.data()); .sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2,
.pNext = nullptr,
.srcBuffer = src_buffer,
.dstImage = dst_image,
.dstImageLayout = dst_image_layout,
.regionCount = regions.size(),
.pRegions = regions.data(),
};
dld->vkCmdCopyBufferToImage2(handle, &info);
} }
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer, void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
Span<VkBufferCopy> regions) const noexcept { Span<VkBufferCopy2> regions) const noexcept {
dld->vkCmdCopyBuffer(handle, src_buffer, dst_buffer, regions.size(), regions.data()); const VkCopyBufferInfo2 info{
.sType = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2,
.pNext = nullptr,
.srcBuffer = src_buffer,
.dstBuffer = dst_buffer,
.regionCount = regions.size(),
.pRegions = regions.data(),
};
dld->vkCmdCopyBuffer2(handle, &info);
} }
void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image, void CopyImage(VkImage src_image, VkImageLayout src_layout, VkImage dst_image,
VkImageLayout dst_layout, Span<VkImageCopy> regions) const noexcept { VkImageLayout dst_layout, Span<VkImageCopy2> regions) const noexcept {
dld->vkCmdCopyImage(handle, src_image, src_layout, dst_image, dst_layout, regions.size(), const VkCopyImageInfo2 info{
regions.data()); .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2,
.pNext = nullptr,
.srcImage = src_image,
.srcImageLayout = src_layout,
.dstImage = dst_image,
.dstImageLayout = dst_layout,
.regionCount = regions.size(),
.pRegions = regions.data(),
};
dld->vkCmdCopyImage2(handle, &info);
} }
void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer, void CopyImageToBuffer(VkImage src_image, VkImageLayout src_layout, VkBuffer dst_buffer,
Span<VkBufferImageCopy> regions) const noexcept { Span<VkBufferImageCopy2> regions) const noexcept {
dld->vkCmdCopyImageToBuffer(handle, src_image, src_layout, dst_buffer, regions.size(), const VkCopyImageToBufferInfo2 info{
regions.data()); .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2,
.pNext = nullptr,
.srcImage = src_image,
.srcImageLayout = src_layout,
.dstBuffer = dst_buffer,
.regionCount = regions.size(),
.pRegions = regions.data(),
};
dld->vkCmdCopyImageToBuffer2(handle, &info);
} }
void CopyQueryPoolResults(VkQueryPool query_pool, u32 first_query, u32 query_count, void CopyQueryPoolResults(VkQueryPool query_pool, u32 first_query, u32 query_count,