mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 22:10:49 +00:00
Another try to make barriers more explicit
This commit is contained in:
@@ -36,6 +36,24 @@ struct VertexBindings {
|
||||
u32 count;
|
||||
};
|
||||
|
||||
constexpr VkMemoryBarrier2 READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.dstAccessMask = vk::ACCESS_TRANSFER,
|
||||
};
|
||||
|
||||
constexpr VkMemoryBarrier2 WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||
.dstStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS,
|
||||
.dstAccessMask = vk::ACCESS_BUFFER_INPUTS,
|
||||
};
|
||||
|
||||
VkBufferCopy MakeBufferCopy(const VideoCommon::BufferCopy& copy) {
|
||||
return VkBufferCopy{
|
||||
.srcOffset = copy.src_offset,
|
||||
@@ -482,22 +500,6 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
||||
if (dst_buffer == VK_NULL_HANDLE || src_buffer == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
static constexpr VkMemoryBarrier2 READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||
.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 VkMemoryBarrier2 WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_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
|
||||
boost::container::small_vector<VkBufferCopy, 8> vk_copies(copies.size());
|
||||
@@ -523,14 +525,6 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
|
||||
}
|
||||
|
||||
void BufferCacheRuntime::PreCopyBarrier() {
|
||||
static constexpr VkMemoryBarrier2 READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||
.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.Record([](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.PipelineBarrier(READ_BARRIER);
|
||||
@@ -538,14 +532,6 @@ void BufferCacheRuntime::PreCopyBarrier() {
|
||||
}
|
||||
|
||||
void BufferCacheRuntime::PostCopyBarrier() {
|
||||
static constexpr VkMemoryBarrier2 WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_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.Record([](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.PipelineBarrier(WRITE_BARRIER);
|
||||
@@ -556,22 +542,6 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
|
||||
if (dest_buffer == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
static constexpr VkMemoryBarrier2 READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||
.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 VkMemoryBarrier2 WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_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.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
|
||||
|
||||
@@ -631,19 +631,19 @@ void RasterizerVulkan::DispatchCompute() {
|
||||
static constexpr VkMemoryBarrier2 READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||
.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
|
||||
.dstStageMask =
|
||||
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = vk::ACCESS_SHADER_RESOURCES,
|
||||
};
|
||||
static constexpr VkMemoryBarrier2 WRITE_BARRIER{
|
||||
static constexpr VkMemoryBarrier2 INDIRECT_READ_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
|
||||
.dstStageMask =
|
||||
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT | vk::ACCESS_SHADER_RESOURCES,
|
||||
};
|
||||
const auto& qmd{kepler_compute->launch_description};
|
||||
auto indirect_address = kepler_compute->GetIndirectComputeAddress();
|
||||
@@ -653,15 +653,14 @@ void RasterizerVulkan::DispatchCompute() {
|
||||
const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
|
||||
const auto [buffer, offset] =
|
||||
buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.RequestComputeDispatchContext();
|
||||
scheduler.Record([pipeline, indirect_buffer = buffer->Handle(),
|
||||
indirect_offset = offset](vk::CommandBuffer cmdbuf) {
|
||||
if (!pipeline->IsBound()) {
|
||||
return;
|
||||
}
|
||||
cmdbuf.PipelineBarrier(READ_BARRIER);
|
||||
cmdbuf.PipelineBarrier(INDIRECT_READ_BARRIER);
|
||||
cmdbuf.DispatchIndirect(indirect_buffer, indirect_offset);
|
||||
cmdbuf.PipelineBarrier(WRITE_BARRIER);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -670,14 +669,13 @@ void RasterizerVulkan::DispatchCompute() {
|
||||
if (dim[0] > max_dim[0] || dim[1] > max_dim[1] || dim[2] > max_dim[2]) {
|
||||
return;
|
||||
}
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.RequestComputeDispatchContext();
|
||||
scheduler.Record([pipeline, dim](vk::CommandBuffer cmdbuf) {
|
||||
if (!pipeline->IsBound()) {
|
||||
return;
|
||||
}
|
||||
cmdbuf.PipelineBarrier(READ_BARRIER);
|
||||
cmdbuf.Dispatch(dim[0], dim[1], dim[2]);
|
||||
cmdbuf.PipelineBarrier(WRITE_BARRIER);
|
||||
});
|
||||
|
||||
// Log compute dispatch
|
||||
|
||||
@@ -47,6 +47,12 @@ Scheduler::Scheduler(const Device& device_, StateTracker& state_tracker_)
|
||||
: device{device_}, state_tracker{state_tracker_},
|
||||
master_semaphore{std::make_unique<MasterSemaphore>(device)},
|
||||
command_pool{std::make_unique<CommandPool>(*master_semaphore, device)} {
|
||||
if (device.IsExtTransformFeedbackSupported()) {
|
||||
renderpass_write_barrier.srcStageMask |= VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||
renderpass_write_barrier.srcAccessMask |= VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
|
||||
renderpass_write_barrier.dstStageMask |= VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||
renderpass_write_barrier.dstAccessMask |= VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
|
||||
}
|
||||
|
||||
AcquireNewChunk();
|
||||
AllocateWorkerCommandBuffer();
|
||||
@@ -95,6 +101,7 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass
|
||||
const VkClearValue* clear_values, u32 clear_value_count) {
|
||||
const VkFramebuffer framebuffer_handle = framebuffer->Handle();
|
||||
const VkExtent2D render_area = framebuffer->RenderArea();
|
||||
PublishComputeWrites();
|
||||
state.renderpass = renderpass;
|
||||
state.framebuffer = framebuffer_handle;
|
||||
state.render_area = render_area;
|
||||
@@ -222,6 +229,31 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
|
||||
|
||||
void Scheduler::RequestOutsideRenderPassOperationContext() {
|
||||
EndRenderPass();
|
||||
PublishComputeWrites();
|
||||
}
|
||||
|
||||
void Scheduler::RequestComputeDispatchContext() {
|
||||
EndRenderPass();
|
||||
compute_writes = true;
|
||||
}
|
||||
|
||||
void Scheduler::PublishComputeWrites() {
|
||||
if (!std::exchange(compute_writes, false)) {
|
||||
return;
|
||||
}
|
||||
Record([](vk::CommandBuffer cmdbuf) {
|
||||
static constexpr VkMemoryBarrier2 COMPUTE_WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS | vk::PIPELINE_STAGE_ATTACHMENTS |
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.dstAccessMask =
|
||||
vk::ACCESS_BUFFER_INPUTS | vk::ACCESS_ATTACHMENTS | vk::ACCESS_TRANSFER,
|
||||
};
|
||||
cmdbuf.PipelineBarrier(COMPUTE_WRITE_BARRIER);
|
||||
});
|
||||
}
|
||||
|
||||
bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
|
||||
@@ -420,17 +452,10 @@ void Scheduler::EndRenderPass()
|
||||
Record([num_images = num_renderpass_images,
|
||||
images = renderpass_images,
|
||||
ranges = renderpass_image_ranges,
|
||||
write_barrier = &renderpass_write_barrier,
|
||||
num_memory_barriers =
|
||||
static_cast<size_t>(std::exchange(renderpass_writes, false))](
|
||||
vk::CommandBuffer cmdbuf) {
|
||||
static constexpr VkMemoryBarrier2 WRITE_BARRIER{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT,
|
||||
.srcAccessMask = VK_ACCESS_2_MEMORY_WRITE_BIT,
|
||||
.dstStageMask = vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
|
||||
.dstAccessMask = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT,
|
||||
};
|
||||
std::array<VkImageMemoryBarrier2, 9> barriers;
|
||||
for (size_t i = 0; i < num_images; ++i) {
|
||||
const VkImageSubresourceRange& range = ranges[i];
|
||||
@@ -471,7 +496,7 @@ void Scheduler::EndRenderPass()
|
||||
};
|
||||
}
|
||||
cmdbuf.EndRenderPass();
|
||||
cmdbuf.PipelineBarrier(0, vk::Span(&WRITE_BARRIER, num_memory_barriers), {},
|
||||
cmdbuf.PipelineBarrier(0, vk::Span(write_barrier, num_memory_barriers), {},
|
||||
vk::Span(barriers.data(), num_images));
|
||||
});
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ public:
|
||||
/// of a renderpass.
|
||||
void RequestOutsideRenderPassOperationContext();
|
||||
|
||||
void RequestComputeDispatchContext();
|
||||
|
||||
/// Returns true when a render pass is currently active in the scheduler state.
|
||||
bool IsRenderPassActive() const {
|
||||
return state.renderpass != VK_NULL_HANDLE;
|
||||
@@ -319,6 +321,8 @@ private:
|
||||
|
||||
void EndRenderPass();
|
||||
|
||||
void PublishComputeWrites();
|
||||
|
||||
void AcquireNewChunk();
|
||||
|
||||
const Device& device;
|
||||
@@ -343,6 +347,16 @@ private:
|
||||
u64 wfi_serial = 0;
|
||||
bool renderpass_writes = false;
|
||||
bool renderpass_depth_writes = false;
|
||||
bool compute_writes = false;
|
||||
VkMemoryBarrier2 renderpass_write_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
|
||||
.pNext = nullptr,
|
||||
.srcStageMask = vk::PIPELINE_STAGE_GRAPHICS_SHADERS,
|
||||
.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
|
||||
.dstStageMask = vk::PIPELINE_STAGE_BUFFER_INPUTS | vk::PIPELINE_STAGE_ATTACHMENTS |
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT,
|
||||
.dstAccessMask = vk::ACCESS_BUFFER_INPUTS | vk::ACCESS_ATTACHMENTS | vk::ACCESS_TRANSFER,
|
||||
};
|
||||
u32 num_renderpass_images = 0;
|
||||
std::array<VkImage, 9> renderpass_images{};
|
||||
std::array<VkImageSubresourceRange, 9> renderpass_image_ranges{};
|
||||
|
||||
@@ -158,6 +158,31 @@ inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER_
|
||||
|
||||
inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_HOST = VK_PIPELINE_STAGE_2_HOST_BIT;
|
||||
|
||||
inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_GRAPHICS_SHADERS =
|
||||
VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
|
||||
|
||||
inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_BUFFER_INPUTS =
|
||||
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT |
|
||||
PIPELINE_STAGE_GRAPHICS_SHADERS | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT;
|
||||
|
||||
inline constexpr VkPipelineStageFlags2 PIPELINE_STAGE_ATTACHMENTS =
|
||||
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
|
||||
inline constexpr VkAccessFlags2 ACCESS_SHADER_RESOURCES =
|
||||
VK_ACCESS_2_UNIFORM_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT | VK_ACCESS_2_SHADER_WRITE_BIT;
|
||||
|
||||
inline constexpr VkAccessFlags2 ACCESS_BUFFER_INPUTS =
|
||||
VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_2_INDEX_READ_BIT |
|
||||
VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT | ACCESS_SHADER_RESOURCES;
|
||||
|
||||
inline constexpr VkAccessFlags2 ACCESS_ATTACHMENTS =
|
||||
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;
|
||||
|
||||
inline constexpr VkAccessFlags2 ACCESS_TRANSFER =
|
||||
VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
||||
|
||||
|
||||
/// Table holding Vulkan instance function pointers.
|
||||
struct InstanceDispatch {
|
||||
|
||||
Reference in New Issue
Block a user