Vulkan: Fix incorrect reordering when copying attachment

Solved by not supporting complex reordering at this moment. It
is currently better to focus on quality and add back performance
later. During tests I didn't detect any user noticeable performance
degradation. Could also be because we support rendering
suspending/resuming.

Fixes artifacts in EEVEE volumes and raytracing.

Pull Request: https://projects.blender.org/blender/blender/pulls/126974
This commit is contained in:
Jeroen Bakker
2024-08-30 13:24:57 +02:00
parent 05f2e6f5c2
commit e8e89b751d
2 changed files with 225 additions and 88 deletions

View File

@@ -437,18 +437,8 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
}
render_graph.submit_for_present(image);
EXPECT_EQ(8, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_TRANSFER_BIT" +
endl() +
" - buffer_barrier(src_access_mask=, dst_access_mask=VK_ACCESS_TRANSFER_READ_BIT, "
"buffer=0x3, offset=0, size=18446744073709551615)" +
endl() + ")",
log[0]);
EXPECT_EQ("copy_buffer(src_buffer=0x3, dst_buffer=0x4" + endl() +
" - region(src_offset=0, dst_offset=0, size=0)" + endl() + ")",
log[1]);
EXPECT_EQ(10, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT" +
@@ -461,33 +451,60 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=0, layer_count=4294967295 )" +
endl() + ")",
log[0]);
EXPECT_EQ(
"begin_rendering(p_rendering_info=flags=VK_RENDERING_SUSPENDING_BIT, "
"VK_RENDERING_SUSPENDING_BIT_KHR, render_area=" +
endl() + " offset=" + endl() + " x=0, y=0 , extent=" + endl() +
" width=0, height=0 , layer_count=1, view_mask=0, color_attachment_count=1, "
"p_color_attachments=" +
endl() +
" image_view=0x2, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"resolve_mode=VK_RESOLVE_MODE_NONE, resolve_image_view=0, "
"resolve_image_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"load_op=VK_ATTACHMENT_LOAD_OP_DONT_CARE, store_op=VK_ATTACHMENT_STORE_OP_STORE" +
endl() + ")",
log[1]);
EXPECT_EQ(
"clear_attachments( - attachment(aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, "
"color_attachment=0)" +
endl() + " - rect(rect=" + endl() + " offset=" + endl() +
" x=0, y=0 , extent=" + endl() +
" width=1920, height=1080 , base_array_layer=0, layer_count=1)" + endl() + ")",
log[2]);
EXPECT_EQ("begin_rendering(p_rendering_info=flags=, render_area=" + endl() +
" offset=" + endl() + " x=0, y=0 , extent=" + endl() +
" width=0, height=0 , layer_count=1, view_mask=0, color_attachment_count=1, "
"p_color_attachments=" +
endl() +
" image_view=0x2, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"resolve_mode=VK_RESOLVE_MODE_NONE, resolve_image_view=0, "
"resolve_image_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"load_op=VK_ATTACHMENT_LOAD_OP_DONT_CARE, store_op=VK_ATTACHMENT_STORE_OP_STORE" +
endl() + ")",
log[3]);
EXPECT_EQ("end_rendering()", log[3]);
EXPECT_EQ(
"clear_attachments( - attachment(aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, "
"color_attachment=0)" +
endl() + " - rect(rect=" + endl() + " offset=" + endl() +
" x=0, y=0 , extent=" + endl() +
" width=1920, height=1080 , base_array_layer=0, layer_count=1)" + endl() + ")",
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_TRANSFER_BIT" +
endl() +
" - buffer_barrier(src_access_mask=, dst_access_mask=VK_ACCESS_TRANSFER_READ_BIT, "
"buffer=0x3, offset=0, size=18446744073709551615)" +
endl() + ")",
log[4]);
EXPECT_EQ("copy_buffer(src_buffer=0x3, dst_buffer=0x4" + endl() +
" - region(src_offset=0, dst_offset=0, size=0)" + endl() + ")",
log[5]);
EXPECT_EQ(
"begin_rendering(p_rendering_info=flags=VK_RENDERING_RESUMING_BIT, "
"VK_RENDERING_RESUMING_BIT_KHR, render_area=" +
endl() + " offset=" + endl() + " x=0, y=0 , extent=" + endl() +
" width=0, height=0 , layer_count=1, view_mask=0, color_attachment_count=1, "
"p_color_attachments=" +
endl() +
" image_view=0x2, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"resolve_mode=VK_RESOLVE_MODE_NONE, resolve_image_view=0, "
"resolve_image_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"load_op=VK_ATTACHMENT_LOAD_OP_DONT_CARE, store_op=VK_ATTACHMENT_STORE_OP_STORE" +
endl() + ")",
log[6]);
EXPECT_EQ(
"clear_attachments( - attachment(aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, "
"color_attachment=0)" +
endl() + " - rect(rect=" + endl() + " offset=" + endl() +
" x=0, y=0 , extent=" + endl() +
" width=1920, height=1080 , base_array_layer=0, layer_count=1)" + endl() + ")",
log[5]);
EXPECT_EQ("end_rendering()", log[6]);
log[7]);
EXPECT_EQ("end_rendering()", log[8]);
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT" +
@@ -500,7 +517,185 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=0, layer_count=4294967295 )" +
endl() + ")",
log[9]);
}
/**
* When copying the frame buffer content between two draw calls we should not move the command.
*
* This happens in EEVEE where the feedback radiance is copied before the world background is added
* to the combined texture.
*/
TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
{
VkHandle<VkImage> image_attachment(1u);
VkHandle<VkImage> image_feedback(2u);
VkHandle<VkImageView> image_view_attachment(3u);
VkHandle<VkPipelineLayout> pipeline_layout_combine(4u);
VkHandle<VkPipeline> pipeline_combine(5u);
VkHandle<VkPipelineLayout> pipeline_layout_background(6u);
VkHandle<VkPipeline> pipeline_background(7u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(
image_attachment, 1, VK_IMAGE_LAYOUT_UNDEFINED, render_graph::ResourceOwner::APPLICATION);
resources.add_image(
image_feedback, 1, VK_IMAGE_LAYOUT_UNDEFINED, render_graph::ResourceOwner::APPLICATION);
{
VKResourceAccessInfo access_info = {};
access_info.images.append(
{image_attachment, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0});
VKBeginRenderingNode::CreateInfo begin_rendering(access_info);
begin_rendering.node_data.color_attachments[0].sType =
VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
begin_rendering.node_data.color_attachments[0].imageLayout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
begin_rendering.node_data.color_attachments[0].imageView = image_view_attachment;
begin_rendering.node_data.color_attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
begin_rendering.node_data.color_attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
begin_rendering.node_data.vk_rendering_info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
begin_rendering.node_data.vk_rendering_info.colorAttachmentCount = 1;
begin_rendering.node_data.vk_rendering_info.layerCount = 1;
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
}
{
VKResourceAccessInfo access_info = {};
VKDrawNode::CreateInfo draw(access_info);
draw.node_data.first_instance = 0;
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline_combine;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout_combine;
render_graph.add_node(draw);
}
{
VKCopyImageNode::CreateInfo copy_image = {};
copy_image.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
copy_image.node_data.src_image = image_attachment;
copy_image.node_data.dst_image = image_feedback;
copy_image.node_data.region.extent.width = 1920;
copy_image.node_data.region.extent.height = 1080;
copy_image.node_data.region.extent.depth = 1;
copy_image.node_data.region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_image.node_data.region.srcSubresource.baseArrayLayer = 0;
copy_image.node_data.region.srcSubresource.layerCount = 1;
copy_image.node_data.region.srcSubresource.mipLevel = 0;
render_graph.add_node(copy_image);
}
{
VKResourceAccessInfo access_info = {};
VKDrawNode::CreateInfo draw(access_info);
draw.node_data.first_instance = 0;
draw.node_data.first_vertex = 0;
draw.node_data.instance_count = 1;
draw.node_data.vertex_count = 4;
draw.node_data.pipeline_data.push_constants_data = nullptr;
draw.node_data.pipeline_data.push_constants_size = 0;
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline_background;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout_background;
render_graph.add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
}
render_graph.submit();
ASSERT_EQ(11, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT" +
endl() +
" - image_barrier(src_access_mask=, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=0, layer_count=4294967295 )" +
endl() + ")",
log[0]);
EXPECT_EQ(
"begin_rendering(p_rendering_info=flags=VK_RENDERING_SUSPENDING_BIT, "
"VK_RENDERING_SUSPENDING_BIT_KHR, render_area=" +
endl() + " offset=" + endl() + " x=0, y=0 , extent=" + endl() +
" width=0, height=0 , layer_count=1, view_mask=0, color_attachment_count=1, "
"p_color_attachments=" +
endl() +
" image_view=0x3, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"resolve_mode=VK_RESOLVE_MODE_NONE, resolve_image_view=0, "
"resolve_image_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"load_op=VK_ATTACHMENT_LOAD_OP_DONT_CARE, store_op=VK_ATTACHMENT_STORE_OP_STORE" +
endl() + ")",
log[1]);
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline=0x5)",
log[2]);
EXPECT_EQ("draw(vertex_count=4, instance_count=1, first_vertex=0, first_instance=0)", log[3]);
EXPECT_EQ("end_rendering()", log[4]);
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_TRANSFER_BIT" +
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=VK_ACCESS_TRANSFER_READ_BIT, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"new_layout=VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=0, layer_count=4294967295 )" +
endl() +
" - image_barrier(src_access_mask=, dst_access_mask=VK_ACCESS_TRANSFER_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_UNDEFINED, new_layout=VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "
"image=0x2, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=0, layer_count=4294967295 )" +
endl() + ")",
log[5]);
EXPECT_EQ(
"copy_image(src_image=0x1, src_image_layout=VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "
"dst_image=0x2, dst_image_layout=VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL" +
endl() + " - region(src_subresource=" + endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, mip_level=0, base_array_layer=0, "
"layer_count=1 , src_offset=" +
endl() + " x=0, y=0, z=0 , dst_subresource=" + endl() +
" aspect_mask=, mip_level=0, base_array_layer=0, layer_count=0 , dst_offset=" +
endl() + " x=0, y=0, z=0 , extent=" + endl() +
" width=1920, height=1080, depth=1 )" + endl() + ")",
log[6]);
EXPECT_EQ(
"begin_rendering(p_rendering_info=flags=VK_RENDERING_RESUMING_BIT, "
"VK_RENDERING_RESUMING_BIT_KHR, render_area=" +
endl() + " offset=" + endl() + " x=0, y=0 , extent=" + endl() +
" width=0, height=0 , layer_count=1, view_mask=0, color_attachment_count=1, "
"p_color_attachments=" +
endl() +
" image_view=0x3, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"resolve_mode=VK_RESOLVE_MODE_NONE, resolve_image_view=0, "
"resolve_image_layout=VK_IMAGE_LAYOUT_UNDEFINED, "
"load_op=VK_ATTACHMENT_LOAD_OP_DONT_CARE, store_op=VK_ATTACHMENT_STORE_OP_STORE" +
endl() + ")",
log[7]);
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline=0x7)",
log[8]);
EXPECT_EQ("draw(vertex_count=4, instance_count=1, first_vertex=0, first_instance=0)", log[9]);
EXPECT_EQ("end_rendering()", log[10]);
}
} // namespace blender::gpu::render_graph

View File

@@ -89,10 +89,6 @@ std::optional<std::pair<int64_t, int64_t>> VKScheduler::find_rendering_scope(
void VKScheduler::move_transfer_and_dispatch_outside_rendering_scope(
const VKRenderGraph &render_graph)
{
Vector<NodeHandle> pre_rendering_handles;
Vector<NodeHandle> rendering_handles;
Set<ResourceHandle> accessed_resources;
foreach_rendering_scope(render_graph, [&](int64_t start_index, int64_t end_index) {
/* Move end_rendering right after the last graphics node. */
for (int index = end_index - 1; index >= start_index; index--) {
@@ -115,60 +111,6 @@ void VKScheduler::move_transfer_and_dispatch_outside_rendering_scope(
std::swap(result_[start_index], result_[index]);
start_index += 1;
}
/* Move all other none graphics commands to before the begin_rendering unless the resource they
* are modifying is already being used by a draw command. Uses temporary allocated vectors to
* reduce the amount and size of copying data. */
pre_rendering_handles.clear();
rendering_handles.clear();
accessed_resources.clear();
for (int index = start_index + 1; index < end_index; index++) {
NodeHandle node_handle = result_[index];
const VKRenderGraphNode &node = render_graph.nodes_[node_handle];
if (pre_rendering_handles.is_empty()) {
if (!node_type_is_rendering(node.type)) {
rendering_handles.extend(&result_[start_index], index - start_index);
pre_rendering_handles.append(node_handle);
}
}
else {
const VKRenderGraphNodeLinks &node_links = render_graph.links_[node_handle];
if (node_type_is_rendering(node.type)) {
rendering_handles.append(node_handle);
for (const VKRenderGraphLink &input : node_links.inputs) {
accessed_resources.add(input.resource.handle);
}
}
else {
bool prepend = true;
for (const VKRenderGraphLink &output : node_links.outputs) {
if (accessed_resources.contains(output.resource.handle)) {
accessed_resources.remove(output.resource.handle);
prepend = false;
}
}
if (prepend) {
pre_rendering_handles.append(node_handle);
}
else {
// This adds a none rendering node into a rendering scope.
// later on the rendering will be suspended when the commands
// for these nodes are build.
rendering_handles.append(node_handle);
}
}
}
}
if (!pre_rendering_handles.is_empty()) {
MutableSpan<NodeHandle> store_none_rendering = result_.as_mutable_span().slice(
start_index, pre_rendering_handles.size());
MutableSpan<NodeHandle> store_rendering = result_.as_mutable_span().slice(
start_index + pre_rendering_handles.size(), rendering_handles.size());
store_none_rendering.copy_from(pre_rendering_handles);
store_rendering.copy_from(rendering_handles);
start_index += pre_rendering_handles.size();
}
});
}