[vk] Simplified layouts per driver configuration (#3271)
Replaces VK_PIPELINE_STAGE_ALL_COMMANDS_BIT with more specific pipeline stage flags in Vulkan pipeline barriers across renderer modules. Co-authored-by: DraVee <dravee@eden-emu.dev> Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3271 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: crueter <crueter@eden-emu.dev> Reviewed-by: DraVee <dravee@eden-emu.dev> Co-authored-by: Nekle <224100951+ne-kle@users.noreply.github.com> Co-committed-by: Nekle <224100951+ne-kle@users.noreply.github.com>
This commit is contained in:
parent
b9e052b3a7
commit
75fda70db2
|
|
@ -436,7 +436,23 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
// Blit image barrier - transition can happen at any stage
|
||||||
|
// Using specific stages for better parallelism, but keeping broad since this is a general utility
|
||||||
|
const VkPipelineStageFlags src_stages_blit =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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 |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
const VkPipelineStageFlags dst_stages_blit =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_blit, dst_stages_blit,
|
||||||
0, barrier);
|
0, barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
|
@ -68,7 +68,16 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
// Present path - use specific stages for better parallelism on tile-based GPUs
|
||||||
|
const VkPipelineStageFlags src_stages =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
const VkPipelineStageFlags dst_stages =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages, dst_stages,
|
||||||
0, barrier);
|
0, barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,11 +160,12 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
// Host will read the downloaded data
|
||||||
static constexpr VkMemoryBarrier memory_write_barrier{
|
static constexpr VkMemoryBarrier memory_write_barrier{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_HOST_READ_BIT,
|
||||||
};
|
};
|
||||||
const VkBufferImageCopy copy{
|
const VkBufferImageCopy copy{
|
||||||
.bufferOffset = 0,
|
.bufferOffset = 0,
|
||||||
|
|
@ -170,10 +180,20 @@ 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_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
const VkPipelineStageFlags src_stages_copy =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_copy, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||||
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_ALL_COMMANDS_BIT, 0,
|
const VkPipelineStageFlags dst_stages_copy =
|
||||||
|
VK_PIPELINE_STAGE_HOST_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_copy, 0,
|
||||||
memory_write_barrier, nullptr, image_write_barrier);
|
memory_write_barrier, nullptr, image_write_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -436,13 +436,27 @@ 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_ALL_COMMANDS_BIT,
|
// Buffer writes can come from vertex input, shaders, or compute
|
||||||
|
const VkPipelineStageFlags src_stages =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 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) {
|
||||||
|
// Buffer reads can go to vertex input, shaders, or compute
|
||||||
|
const VkPipelineStageFlags dst_stages =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
dst_stages, 0, WRITE_BARRIER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -456,21 +470,36 @@ void BufferCacheRuntime::PreCopyBarrier() {
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
const VkPipelineStageFlags src_stages =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, READ_BARRIER);
|
0, READ_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::PostCopyBarrier() {
|
void BufferCacheRuntime::PostCopyBarrier() {
|
||||||
|
// Specific access flags for buffer destinations: vertex input, uniforms, storage, index
|
||||||
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
|
||||||
|
VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
|
||||||
|
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_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_ALL_COMMANDS_BIT,
|
const VkPipelineStageFlags dst_stages =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages,
|
||||||
0, WRITE_BARRIER);
|
0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -494,10 +523,24 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
|
||||||
|
|
||||||
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_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
// Buffer writes can come from vertex input, shaders, or compute
|
||||||
|
const VkPipelineStageFlags src_stages_clear =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_clear, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, 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_ALL_COMMANDS_BIT,
|
// Buffer reads can go to vertex input, shaders, or compute
|
||||||
|
const VkPipelineStageFlags dst_stages_clear =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_clear,
|
||||||
0, WRITE_BARRIER);
|
0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -446,13 +446,26 @@ 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_ALL_COMMANDS_BIT,
|
// Memory writes can come from graphics or compute stages
|
||||||
|
const VkPipelineStageFlags src_stages_compute =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_compute,
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 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.Dispatch(1, 1, 1);
|
cmdbuf.Dispatch(1, 1, 1);
|
||||||
|
// Conditional rendering result used by draw indirect or conditional rendering
|
||||||
|
const VkPipelineStageFlags dst_stages_cond =
|
||||||
|
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);
|
dst_stages_cond, 0, write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,14 +533,29 @@ 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_ALL_COMMANDS_BIT,
|
// Memory writes can come from graphics or compute stages
|
||||||
|
const VkPipelineStageFlags src_stages_scan =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_scan,
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 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);
|
||||||
|
// Query prefix scan results used by draw indirect, conditional rendering, or shaders
|
||||||
|
const VkPipelineStageFlags dst_stages_scan =
|
||||||
|
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);
|
dst_stages_scan, 0, write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -579,8 +607,15 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
// If initialized, memory writes can come from graphics or compute stages
|
||||||
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
const VkPipelineStageFlags src_stages_astc = is_initialized ?
|
||||||
|
(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT) :
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_astc,
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
|
||||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
|
@ -441,7 +441,13 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, {},
|
// Previous operations that might have written to the frame image
|
||||||
|
const VkPipelineStageFlags src_stages_present =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_present, VK_PIPELINE_STAGE_TRANSFER_BIT, {},
|
||||||
{}, {}, pre_barriers);
|
{}, {}, pre_barriers);
|
||||||
|
|
||||||
if (blit_supported) {
|
if (blit_supported) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
|
@ -809,12 +809,19 @@ public:
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_SHADER_READ_BIT,
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
|
// After transfer, results may be read by host or used in subsequent operations
|
||||||
|
const VkPipelineStageFlags dst_stages_query =
|
||||||
|
VK_PIPELINE_STAGE_HOST_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
dst_stages_query, 0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::scoped_lock lk(flush_guard);
|
std::scoped_lock lk(flush_guard);
|
||||||
|
|
@ -942,7 +949,7 @@ private:
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([dst_buffer = current_bank->GetBuffer(),
|
scheduler.Record([dst_buffer = current_bank->GetBuffer(),
|
||||||
|
|
@ -1475,22 +1482,40 @@ void QueryCacheRuntime::Barriers(bool is_prebarrier) {
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
};
|
};
|
||||||
|
// Query results may be read by host or used in shaders/indirect commands
|
||||||
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
|
||||||
|
VK_ACCESS_INDIRECT_COMMAND_READ_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_ALL_COMMANDS_BIT,
|
// Query data can be written by graphics or compute stages
|
||||||
|
const VkPipelineStageFlags src_stages_query =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_query,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
impl->scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
|
// Query results may be read by host or used in shaders/indirect commands
|
||||||
|
const VkPipelineStageFlags dst_stages_query =
|
||||||
|
VK_PIPELINE_STAGE_HOST_BIT |
|
||||||
|
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
dst_stages_query, 0, WRITE_BARRIER);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -586,14 +586,23 @@ void RasterizerVulkan::DispatchCompute() {
|
||||||
}
|
}
|
||||||
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
|
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
// Compute shader reads from storage buffers, uniforms, and images
|
||||||
static constexpr VkMemoryBarrier READ_BARRIER{
|
static constexpr VkMemoryBarrier READ_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT,
|
||||||
};
|
};
|
||||||
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
scheduler.Record([](vk::CommandBuffer cmdbuf) {
|
||||||
0, READ_BARRIER); });
|
// Memory writes can come from graphics or compute stages
|
||||||
|
const VkPipelineStageFlags src_stages =
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
|
0, READ_BARRIER);
|
||||||
|
});
|
||||||
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
||||||
|
|
||||||
// Log compute dispatch
|
// Log compute dispatch
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
|
@ -44,13 +44,19 @@ using VideoCore::Surface::SurfaceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format,
|
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format,
|
||||||
VkSampleCountFlagBits samples) {
|
VkSampleCountFlagBits samples,
|
||||||
|
bool is_depth_stencil) {
|
||||||
using MaxwellToVK::SurfaceFormat;
|
using MaxwellToVK::SurfaceFormat;
|
||||||
|
|
||||||
const SurfaceType surface_type = GetSurfaceType(format);
|
const SurfaceType surface_type = GetSurfaceType(format);
|
||||||
const bool has_stencil = surface_type == SurfaceType::DepthStencil ||
|
const bool has_stencil = surface_type == SurfaceType::DepthStencil ||
|
||||||
surface_type == SurfaceType::Stencil;
|
surface_type == SurfaceType::Stencil;
|
||||||
|
|
||||||
|
// Use optimal layouts for attachments - this allows drivers to optimize tiling and access patterns
|
||||||
|
const VkImageLayout attachment_layout = is_depth_stencil
|
||||||
|
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||||
|
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.flags = {},
|
.flags = {},
|
||||||
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
|
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
|
||||||
|
|
@ -61,8 +67,8 @@ using VideoCore::Surface::SurfaceType;
|
||||||
: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
.stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE
|
.stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE
|
||||||
: VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
: VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
.initialLayout = VK_IMAGE_LAYOUT_GENERAL,
|
.initialLayout = attachment_layout,
|
||||||
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
|
.finalLayout = attachment_layout,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
@ -84,10 +90,10 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
||||||
const bool is_valid{format != PixelFormat::Invalid};
|
const bool is_valid{format != PixelFormat::Invalid};
|
||||||
references[index] = VkAttachmentReference{
|
references[index] = VkAttachmentReference{
|
||||||
.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_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
};
|
};
|
||||||
if (is_valid) {
|
if (is_valid) {
|
||||||
descriptions.push_back(AttachmentDescription(*device, format, key.samples));
|
descriptions.push_back(AttachmentDescription(*device, format, key.samples, false));
|
||||||
num_attachments = static_cast<u32>(index + 1);
|
num_attachments = static_cast<u32>(index + 1);
|
||||||
++num_colors;
|
++num_colors;
|
||||||
}
|
}
|
||||||
|
|
@ -97,9 +103,9 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
|
||||||
if (key.depth_format != PixelFormat::Invalid) {
|
if (key.depth_format != PixelFormat::Invalid) {
|
||||||
depth_reference = VkAttachmentReference{
|
depth_reference = VkAttachmentReference{
|
||||||
.attachment = num_colors,
|
.attachment = num_colors,
|
||||||
.layout = VK_IMAGE_LAYOUT_GENERAL,
|
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
};
|
};
|
||||||
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples));
|
descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples, true));
|
||||||
}
|
}
|
||||||
const VkSubpassDescription subpass{
|
const VkSubpassDescription subpass{
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
|
|
|
||||||
|
|
@ -264,14 +264,26 @@ 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) {
|
||||||
|
// Specific access flags for upload destinations: vertex input, uniforms, storage, index, textures
|
||||||
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
|
||||||
|
VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
|
||||||
|
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||||
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||||
};
|
};
|
||||||
|
// Specify exact stages that need the transfer results instead of ALL_COMMANDS_BIT
|
||||||
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
upload_cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
0, WRITE_BARRIER);
|
||||||
upload_cmdbuf.End();
|
upload_cmdbuf.End();
|
||||||
cmdbuf.End();
|
cmdbuf.End();
|
||||||
|
|
||||||
|
|
@ -332,11 +344,11 @@ void Scheduler::EndRenderPass()
|
||||||
|
|
||||||
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
|
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
|
||||||
query_cache->NotifySegment(false);
|
query_cache->NotifySegment(false);
|
||||||
|
|
||||||
Record([num_images = num_renderpass_images,
|
Record([num_images = num_renderpass_images,
|
||||||
images = renderpass_images,
|
images = renderpass_images,
|
||||||
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
|
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
|
||||||
std::array<VkImageMemoryBarrier, 9> barriers;
|
std::array<VkImageMemoryBarrier, 9> barriers;
|
||||||
|
VkPipelineStageFlags src_stages = 0;
|
||||||
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;
|
||||||
|
|
@ -344,38 +356,76 @@ 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;
|
||||||
|
|
||||||
|
// Determine optimal destination layout based on image usage
|
||||||
|
// After render pass, images may be used as shader resources or as attachments again
|
||||||
|
// Use optimal layouts to allow driver optimizations
|
||||||
VkAccessFlags src_access = 0;
|
VkAccessFlags src_access = 0;
|
||||||
|
VkAccessFlags dst_access = 0;
|
||||||
|
VkPipelineStageFlags this_stage = 0;
|
||||||
|
VkImageLayout new_layout;
|
||||||
|
|
||||||
if (is_color)
|
if (is_color) {
|
||||||
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
// Color attachments can be read as textures or used as attachments again
|
||||||
else if (is_depth_stencil)
|
src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
src_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
this_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
else
|
new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
dst_access = VK_ACCESS_SHADER_READ_BIT
|
||||||
|
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||||
|
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
} else if (is_depth_stencil) {
|
||||||
|
// Depth attachments can be read as textures or used as attachments again
|
||||||
|
src_access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
this_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||||
|
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
dst_access = VK_ACCESS_SHADER_READ_BIT
|
||||||
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
||||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
} else {
|
||||||
|
// Fallback to GENERAL for unknown usage
|
||||||
|
src_access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||||
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
this_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
||||||
|
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
||||||
|
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
new_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
dst_access = VK_ACCESS_SHADER_READ_BIT
|
||||||
|
| VK_ACCESS_SHADER_WRITE_BIT
|
||||||
|
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||||
|
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||||
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
||||||
|
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
}
|
||||||
|
src_stages |= this_stage;
|
||||||
barriers[i] = VkImageMemoryBarrier{
|
barriers[i] = VkImageMemoryBarrier{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = src_access,
|
.srcAccessMask = src_access,
|
||||||
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
|
.dstAccessMask = dst_access,
|
||||||
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
.oldLayout = is_color ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||||
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
: (is_depth_stencil ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
|
: VK_IMAGE_LAYOUT_GENERAL),
|
||||||
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
.newLayout = new_layout,
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = images[i],
|
.image = images[i],
|
||||||
.subresourceRange = range,
|
.subresourceRange = range,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdbuf.EndRenderPass();
|
cmdbuf.EndRenderPass();
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
|
||||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
// Use specific pipeline stages instead of ALL_COMMANDS_BIT for better parallelism
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
// The destination stages depend on how the images will be used next
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
const VkPipelineStageFlags dst_stages =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
|
||||||
|
cmdbuf.PipelineBarrier(src_stages,
|
||||||
|
dst_stages,
|
||||||
0,
|
0,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
|
|
||||||
|
|
@ -810,7 +810,8 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = 0,
|
.srcAccessMask = 0,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_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,
|
||||||
|
|
@ -822,7 +823,8 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_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,
|
||||||
|
|
@ -831,11 +833,26 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const
|
||||||
.subresourceRange = subresource_range,
|
.subresourceRange = subresource_range,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
// Use specific pipeline stages for better parallelism
|
||||||
|
const VkPipelineStageFlags src_stages =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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 |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, nullptr, nullptr, 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_ALL_COMMANDS_BIT,
|
// After transfer, images may be used in graphics, compute, or as attachments
|
||||||
|
const VkPipelineStageFlags dst_stages =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages,
|
||||||
0, nullptr, nullptr, write_barriers);
|
0, nullptr, nullptr, write_barriers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1021,11 +1038,12 @@ void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
};
|
};
|
||||||
|
// After reinterpret, buffers used as transfer source, uniforms, or storage
|
||||||
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
static constexpr VkMemoryBarrier WRITE_BARRIER{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT,
|
||||||
};
|
};
|
||||||
const std::array pre_barriers{
|
const std::array pre_barriers{
|
||||||
VkImageMemoryBarrier{
|
VkImageMemoryBarrier{
|
||||||
|
|
@ -1092,18 +1110,39 @@ 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_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
const VkPipelineStageFlags src_stages_transfer =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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 |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_transfer, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
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_ALL_COMMANDS_BIT,
|
const VkPipelineStageFlags dst_stages_transfer =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_transfer,
|
||||||
0, WRITE_BARRIER, nullptr, middle_in_barrier);
|
0, WRITE_BARRIER, nullptr, middle_in_barrier);
|
||||||
|
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
cmdbuf.PipelineBarrier(src_stages_transfer, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
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_ALL_COMMANDS_BIT,
|
// After reinterpret copy, image may be used in shaders or as attachment
|
||||||
|
const VkPipelineStageFlags dst_stages_post =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_post,
|
||||||
0, {}, {}, post_barriers);
|
0, {}, {}, post_barriers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1230,7 +1269,12 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
const VkPipelineStageFlags src_stages_resolve =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_resolve, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, nullptr, nullptr, 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,
|
||||||
|
|
@ -1243,7 +1287,14 @@ 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_ALL_COMMANDS_BIT,
|
// After blit/resolve, image may be used in shaders or as attachment
|
||||||
|
const VkPipelineStageFlags dst_stages_blit =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_blit,
|
||||||
0, write_barrier);
|
0, write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1821,7 +1872,14 @@ 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_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
const VkPipelineStageFlags src_stages_download =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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 |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_download, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, read_barrier);
|
0, read_barrier);
|
||||||
|
|
||||||
for (size_t index = 0; index < buffers.size(); index++) {
|
for (size_t index = 0; index < buffers.size(); index++) {
|
||||||
|
|
@ -1829,17 +1887,20 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<size_t> o
|
||||||
vk_copies[index]);
|
vk_copies[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Host will read the downloaded data
|
||||||
const VkMemoryBarrier memory_write_barrier{
|
const VkMemoryBarrier memory_write_barrier{
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_HOST_READ_BIT,
|
||||||
};
|
};
|
||||||
|
// Image will be used for shaders or as attachment
|
||||||
const VkImageMemoryBarrier image_write_barrier{
|
const VkImageMemoryBarrier image_write_barrier{
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = 0,
|
.srcAccessMask = 0,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_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,
|
||||||
|
|
@ -1853,7 +1914,13 @@ 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_ALL_COMMANDS_BIT,
|
const VkPipelineStageFlags dst_stages_download =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_download,
|
||||||
0, memory_write_barrier, nullptr, image_write_barrier);
|
0, memory_write_barrier, nullptr, image_write_barrier);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
@ -1888,7 +1955,15 @@ 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_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
// Image writes can come from graphics or compute stages
|
||||||
|
const VkPipelineStageFlags src_stages_img =
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_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 |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(src_stages_img, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, read_barrier);
|
0, read_barrier);
|
||||||
|
|
||||||
for (size_t index = 0; index < buffers.size(); index++) {
|
for (size_t index = 0; index < buffers.size(); index++) {
|
||||||
|
|
@ -1920,7 +1995,14 @@ 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_ALL_COMMANDS_BIT,
|
// After download, image may be used in shaders or as attachment
|
||||||
|
const VkPipelineStageFlags dst_stages_img =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stages_img,
|
||||||
0, memory_write_barrier, nullptr, image_write_barrier);
|
0, memory_write_barrier, nullptr, image_write_barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -2474,7 +2556,9 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) {
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_NONE,
|
.srcAccessMask = VK_ACCESS_NONE,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
||||||
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_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,
|
||||||
|
|
@ -2490,8 +2574,16 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) {
|
||||||
};
|
};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([barrier](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([barrier](vk::CommandBuffer cmdbuf) {
|
||||||
|
// After layout transition, image may be used in shaders or as attachment
|
||||||
|
const VkPipelineStageFlags dst_stages_layout =
|
||||||
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier);
|
dst_stages_layout, 0, barrier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue