Vulkan: Add support for dynamic rendering local read

This will add support for `VK_KHR_dynamic_rendering_local_read` when supported.
The extension allows reading from an attachment that has been written to by a
previous command.

Per platform optimizations still need to happen in future changes. Change will
 be limited to Qualcomm devices (in a future commit).

On Qualcomm devices this provides an uplift of 16% when using shader_balls.blend

Pull Request: https://projects.blender.org/blender/blender/pulls/131053
This commit is contained in:
Jeff Moguillansky 2025-01-13 08:10:31 +01:00 committed by Jeroen Bakker
parent 5ceaff9aa6
commit 75dc76bceb
24 changed files with 573 additions and 359 deletions

View file

@ -820,5 +820,7 @@ AMD <*@amd.com>
Blender Foundation <*@blender.org>
Intel <*@intel.com>
NVIDIA <*@nvidia.com>
Qualcomm <*@qualcomm.com>
Qualcomm <*@quicinc.com>
# Please DO NOT APPEND here. See comments at the top of the file.
# END organizations section.

View file

@ -284,6 +284,15 @@ class GHOST_DeviceVK {
device_create_info_p_next = &dynamic_rendering_unused_attachments;
}
VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR dynamic_rendering_local_read = {};
dynamic_rendering_local_read.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR;
dynamic_rendering_local_read.dynamicRenderingLocalRead = VK_TRUE;
if (has_extensions({VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME})) {
dynamic_rendering_local_read.pNext = device_create_info_p_next;
device_create_info_p_next = &dynamic_rendering_local_read;
}
/* Query for Mainenance4 (core in Vulkan 1.3). */
VkPhysicalDeviceMaintenance4FeaturesKHR maintenance_4 = {};
maintenance_4.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR;
@ -1022,6 +1031,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
required_device_extensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
#endif
optional_device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
optional_device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME);
optional_device_extensions.push_back(VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME);
optional_device_extensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
optional_device_extensions.push_back(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);

View file

@ -8,16 +8,15 @@
namespace blender::gpu::render_graph {
TEST(vk_render_graph, dispatch_read_back)
class VKRenderGraphTestCompute : public VKRenderGraphTest {};
TEST_F(VKRenderGraphTestCompute, dispatch_read_back)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkPipeline> pipeline(2u);
VkHandle<VkPipelineLayout> pipeline_layout(3u);
VkHandle<VkDescriptorSet> descriptor_set(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
VKResourceAccessInfo access_info = {};
access_info.buffers.append({buffer, VK_ACCESS_SHADER_WRITE_BIT});
@ -28,8 +27,8 @@ TEST(vk_render_graph, dispatch_read_back)
dispatch_info.dispatch_node.group_count_x = 1;
dispatch_info.dispatch_node.group_count_y = 1;
dispatch_info.dispatch_node.group_count_z = 1;
render_graph.add_node(dispatch_info);
render_graph.submit_buffer_for_read(buffer);
render_graph->add_node(dispatch_info);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(3, log.size());
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_COMPUTE, pipeline=0x2)",
log[0]);
@ -43,16 +42,13 @@ TEST(vk_render_graph, dispatch_read_back)
/**
* Test that the descriptor sets are updated once when chaining dispatching.
*/
TEST(vk_render_graph, dispatch_dispatch_read_back)
TEST_F(VKRenderGraphTestCompute, dispatch_dispatch_read_back)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkPipeline> pipeline(2u);
VkHandle<VkPipelineLayout> pipeline_layout(3u);
VkHandle<VkDescriptorSet> descriptor_set(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
{
@ -65,7 +61,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back)
dispatch_info.dispatch_node.group_count_x = 1;
dispatch_info.dispatch_node.group_count_y = 1;
dispatch_info.dispatch_node.group_count_z = 1;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
{
VKResourceAccessInfo access_info = {};
@ -77,9 +73,9 @@ TEST(vk_render_graph, dispatch_dispatch_read_back)
dispatch_info.dispatch_node.group_count_x = 2;
dispatch_info.dispatch_node.group_count_y = 2;
dispatch_info.dispatch_node.group_count_z = 2;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(5, log.size());
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_COMPUTE, pipeline=0x2)",
log[0]);
@ -104,7 +100,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back)
* Test that the descriptor sets are updated when chaining dispatching with different descriptor
* sets.
*/
TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_descriptor_sets)
TEST_F(VKRenderGraphTestCompute, dispatch_dispatch_read_back_with_changing_descriptor_sets)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkPipeline> pipeline(2u);
@ -112,9 +108,6 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_descriptor_sets)
VkHandle<VkDescriptorSet> descriptor_set_a(4u);
VkHandle<VkDescriptorSet> descriptor_set_b(5u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
{
@ -127,7 +120,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_descriptor_sets)
dispatch_info.dispatch_node.group_count_x = 1;
dispatch_info.dispatch_node.group_count_y = 1;
dispatch_info.dispatch_node.group_count_z = 1;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
{
VKResourceAccessInfo access_info = {};
@ -139,9 +132,9 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_descriptor_sets)
dispatch_info.dispatch_node.group_count_x = 2;
dispatch_info.dispatch_node.group_count_y = 2;
dispatch_info.dispatch_node.group_count_z = 2;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(6, log.size());
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_COMPUTE, pipeline=0x2)",
log[0]);
@ -169,7 +162,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_descriptor_sets)
/**
* Test that the descriptor sets are updated when chaining dispatching with different pipelines.
*/
TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines)
TEST_F(VKRenderGraphTestCompute, dispatch_dispatch_read_back_with_changing_pipelines)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkPipeline> pipeline_a(2u);
@ -177,9 +170,6 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines)
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkDescriptorSet> descriptor_set(5u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
{
@ -192,7 +182,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines)
dispatch_info.dispatch_node.group_count_x = 1;
dispatch_info.dispatch_node.group_count_y = 1;
dispatch_info.dispatch_node.group_count_z = 1;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
{
VKResourceAccessInfo access_info = {};
@ -204,9 +194,9 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines)
dispatch_info.dispatch_node.group_count_x = 2;
dispatch_info.dispatch_node.group_count_y = 2;
dispatch_info.dispatch_node.group_count_z = 2;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(6, log.size());
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_COMPUTE, pipeline=0x2)",
log[0]);
@ -233,7 +223,8 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines)
* Test that the descriptor sets are updated when chaining dispatching with different pipelines and
* descriptor sets.
*/
TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines_descriptor_sets)
TEST_F(VKRenderGraphTestCompute,
dispatch_dispatch_read_back_with_changing_pipelines_descriptor_sets)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkPipeline> pipeline_a(2u);
@ -242,9 +233,6 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines_descri
VkHandle<VkDescriptorSet> descriptor_set_a(5u);
VkHandle<VkDescriptorSet> descriptor_set_b(6u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
{
@ -257,7 +245,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines_descri
dispatch_info.dispatch_node.group_count_x = 1;
dispatch_info.dispatch_node.group_count_y = 1;
dispatch_info.dispatch_node.group_count_z = 1;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
{
VKResourceAccessInfo access_info = {};
@ -269,9 +257,9 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines_descri
dispatch_info.dispatch_node.group_count_x = 2;
dispatch_info.dispatch_node.group_count_y = 2;
dispatch_info.dispatch_node.group_count_z = 2;
render_graph.add_node(dispatch_info);
render_graph->add_node(dispatch_info);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(7, log.size());
EXPECT_EQ("bind_pipeline(pipeline_bind_point=VK_PIPELINE_BIND_POINT_COMPUTE, pipeline=0x2)",
log[0]);
@ -301,7 +289,7 @@ TEST(vk_render_graph, dispatch_dispatch_read_back_with_changing_pipelines_descri
/**
* Test dispatch indirect
*/
TEST(vk_render_graph, dispatch_indirect_read_back)
TEST_F(VKRenderGraphTestCompute, dispatch_indirect_read_back)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkBuffer> command_buffer(2u);
@ -309,9 +297,6 @@ TEST(vk_render_graph, dispatch_indirect_read_back)
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkDescriptorSet> descriptor_set(5u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
resources.add_buffer(command_buffer);
@ -323,8 +308,8 @@ TEST(vk_render_graph, dispatch_indirect_read_back)
dispatch_indirect_info.dispatch_indirect_node.pipeline_data.vk_descriptor_set = descriptor_set;
dispatch_indirect_info.dispatch_indirect_node.buffer = command_buffer;
dispatch_indirect_info.dispatch_indirect_node.offset = 0;
render_graph.add_node(dispatch_indirect_info);
render_graph.submit_buffer_for_read(buffer);
render_graph->add_node(dispatch_indirect_info);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(4, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -344,7 +329,7 @@ TEST(vk_render_graph, dispatch_indirect_read_back)
EXPECT_EQ("dispatch_indirect(buffer=0x2, offset=0)", log[3]);
}
TEST(vk_render_graph, dispatch_indirect_dispatch_indirect_read_back)
TEST_F(VKRenderGraphTestCompute, dispatch_indirect_dispatch_indirect_read_back)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkBuffer> command_buffer(2u);
@ -352,9 +337,6 @@ TEST(vk_render_graph, dispatch_indirect_dispatch_indirect_read_back)
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkDescriptorSet> descriptor_set(5u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
resources.add_buffer(command_buffer);
@ -368,7 +350,7 @@ TEST(vk_render_graph, dispatch_indirect_dispatch_indirect_read_back)
dispatch_indirect_info.dispatch_indirect_node.pipeline_data.vk_descriptor_set = descriptor_set;
dispatch_indirect_info.dispatch_indirect_node.buffer = command_buffer;
dispatch_indirect_info.dispatch_indirect_node.offset = 0;
render_graph.add_node(dispatch_indirect_info);
render_graph->add_node(dispatch_indirect_info);
}
{
VKResourceAccessInfo access_info = {};
@ -380,9 +362,9 @@ TEST(vk_render_graph, dispatch_indirect_dispatch_indirect_read_back)
dispatch_indirect_info.dispatch_indirect_node.pipeline_data.vk_descriptor_set = descriptor_set;
dispatch_indirect_info.dispatch_indirect_node.buffer = command_buffer;
dispatch_indirect_info.dispatch_indirect_node.offset = 12;
render_graph.add_node(dispatch_indirect_info);
render_graph->add_node(dispatch_indirect_info);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(6, log.size());
EXPECT_EQ(
@ -413,4 +395,5 @@ TEST(vk_render_graph, dispatch_indirect_dispatch_indirect_read_back)
log[4]);
EXPECT_EQ("dispatch_indirect(buffer=0x2, offset=12)", log[5]);
}
} // namespace blender::gpu::render_graph

View file

@ -8,17 +8,16 @@
namespace blender::gpu::render_graph {
TEST(vk_render_graph, transfer_and_present)
class VKRenderGraphTestPresent : public VKRenderGraphTest {};
TEST_F(VKRenderGraphTestPresent, transfer_and_present)
{
VkHandle<VkImage> back_buffer(1u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(
back_buffer, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ResourceOwner::SWAP_CHAIN);
render_graph.submit_for_present(back_buffer);
render_graph->submit_for_present(back_buffer);
EXPECT_EQ(1, log.size());
EXPECT_EQ(
@ -35,20 +34,17 @@ TEST(vk_render_graph, transfer_and_present)
log[0]);
}
TEST(vk_render_graph, clear_and_present)
TEST_F(VKRenderGraphTestPresent, clear_and_present)
{
VkHandle<VkImage> back_buffer(1u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(back_buffer, 1, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, ResourceOwner::SWAP_CHAIN);
VKClearColorImageNode::CreateInfo clear_color_image = {};
clear_color_image.vk_image = back_buffer;
render_graph.add_node(clear_color_image);
render_graph->add_node(clear_color_image);
render_graph.submit_for_present(back_buffer);
render_graph->submit_for_present(back_buffer);
EXPECT_EQ(3, log.size());

View file

@ -8,15 +8,14 @@
namespace blender::gpu::render_graph {
TEST(vk_render_graph, begin_clear_attachments_end_read_back)
class VKRenderGraphTestRender : public VKRenderGraphTest_P {};
TEST_P(VKRenderGraphTestRender, begin_clear_attachments_end_read_back)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkBuffer> buffer(3u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_buffer(buffer);
@ -27,8 +26,7 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -38,7 +36,7 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -54,12 +52,12 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
clear_attachments.vk_clear_rect.layerCount = 1;
clear_attachments.vk_clear_rect.rect.extent.width = 1920;
clear_attachments.vk_clear_rect.rect.extent.height = 1080;
render_graph.add_node(clear_attachments);
render_graph->add_node(clear_attachments);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
{
@ -68,10 +66,11 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
copy_image_to_buffer.node_data.dst_buffer = buffer;
copy_image_to_buffer.node_data.region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_image_to_buffer.vk_image_aspects = VK_IMAGE_ASPECT_COLOR_BIT;
render_graph.add_node(copy_image_to_buffer);
render_graph->add_node(copy_image_to_buffer);
}
render_graph.submit_buffer_for_read(buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(6, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -80,7 +79,9 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
" - 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, "
"new_layout=" +
color_attachment_layout_str() +
", image=0x1, "
"subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -91,8 +92,8 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -112,7 +113,9 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
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, "
"old_layout=" +
color_attachment_layout_str() +
", "
"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, "
@ -133,16 +136,13 @@ TEST(vk_render_graph, begin_clear_attachments_end_read_back)
log[5]);
}
TEST(vk_render_graph, begin_draw_end)
TEST_P(VKRenderGraphTestRender, begin_draw_end)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkPipeline> pipeline(3u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
{
@ -152,8 +152,7 @@ TEST(vk_render_graph, begin_draw_end)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -163,7 +162,7 @@ TEST(vk_render_graph, begin_draw_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -178,15 +177,15 @@ TEST(vk_render_graph, begin_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit();
render_graph->submit();
EXPECT_EQ(5, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -195,8 +194,8 @@ TEST(vk_render_graph, begin_draw_end)
" - 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() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -205,8 +204,8 @@ TEST(vk_render_graph, begin_draw_end)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -218,16 +217,13 @@ TEST(vk_render_graph, begin_draw_end)
EXPECT_EQ("end_rendering()", log[4]);
}
TEST(vk_render_graph, begin_draw_end__layered)
TEST_P(VKRenderGraphTestRender, begin_draw_end__layered)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkPipeline> pipeline(3u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 2, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
{
@ -237,8 +233,7 @@ TEST(vk_render_graph, begin_draw_end__layered)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -248,7 +243,7 @@ TEST(vk_render_graph, begin_draw_end__layered)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -264,15 +259,15 @@ TEST(vk_render_graph, begin_draw_end__layered)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit();
render_graph->submit();
EXPECT_EQ(7, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -281,8 +276,8 @@ TEST(vk_render_graph, begin_draw_end__layered)
" - 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() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -295,7 +290,9 @@ TEST(vk_render_graph, begin_draw_end__layered)
"dst_access_mask=VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, "
"VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_GENERAL, "
"image=0x1, subresource_range=" +
endl() +
@ -307,8 +304,8 @@ TEST(vk_render_graph, begin_draw_end__layered)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -329,12 +326,17 @@ TEST(vk_render_graph, begin_draw_end__layered)
"VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, "
"VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, "
"VK_ACCESS_TRANSFER_WRITE_BIT, old_layout=VK_IMAGE_LAYOUT_GENERAL, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", image=0x1, subresource_range=" + endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
"base_array_layer=1, layer_count=0 )" +
endl() + ")",
log[6]);
}
INSTANTIATE_TEST_SUITE_P(,
VKRenderGraphTestRender,
::testing::Values(std::make_tuple(true, true),
std::make_tuple(true, false)));
} // namespace blender::gpu::render_graph

View file

@ -8,17 +8,16 @@
namespace blender::gpu::render_graph {
class VKRenderGraphTestScheduler : public VKRenderGraphTest_P {};
/** Copy buffer should be done after the end rendering. */
TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
TEST_P(VKRenderGraphTestScheduler, begin_rendering_copy_buffer_end_rendering)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkBuffer> buffer_src(3u);
VkHandle<VkBuffer> buffer_dst(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, ResourceOwner::SWAP_CHAIN);
resources.add_buffer(buffer_src);
resources.add_buffer(buffer_dst);
@ -30,8 +29,7 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -41,22 +39,22 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
VKCopyBufferNode::CreateInfo copy_buffer = {};
copy_buffer.src_buffer = buffer_src;
copy_buffer.dst_buffer = buffer_dst;
render_graph.add_node(copy_buffer);
render_graph->add_node(copy_buffer);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit_for_present(image);
render_graph->submit_for_present(image);
EXPECT_EQ(6, log.size());
EXPECT_EQ(
@ -70,7 +68,6 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
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(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
"dst_stage_mask=VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT" +
@ -78,8 +75,8 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
" - image_barrier(src_access_mask=, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -88,8 +85,8 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -102,7 +99,9 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -111,16 +110,13 @@ TEST(vk_render_graph, begin_rendering_copy_buffer_end_rendering)
log[5]);
}
TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
TEST_P(VKRenderGraphTestScheduler, begin_clear_attachments_copy_buffer_end)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkBuffer> buffer_src(3u);
VkHandle<VkBuffer> buffer_dst(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, ResourceOwner::SWAP_CHAIN);
resources.add_buffer(buffer_src);
resources.add_buffer(buffer_dst);
@ -132,8 +128,7 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -143,7 +138,7 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -159,22 +154,22 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
clear_attachments.vk_clear_rect.layerCount = 1;
clear_attachments.vk_clear_rect.rect.extent.width = 1920;
clear_attachments.vk_clear_rect.rect.extent.height = 1080;
render_graph.add_node(clear_attachments);
render_graph->add_node(clear_attachments);
}
{
VKCopyBufferNode::CreateInfo copy_buffer = {};
copy_buffer.src_buffer = buffer_src;
copy_buffer.dst_buffer = buffer_dst;
render_graph.add_node(copy_buffer);
render_graph->add_node(copy_buffer);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit_for_present(image);
render_graph->submit_for_present(image);
EXPECT_EQ(7, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -194,8 +189,8 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
" - image_barrier(src_access_mask=, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -204,8 +199,8 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -225,7 +220,9 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -234,16 +231,13 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_end)
log[6]);
}
TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
TEST_P(VKRenderGraphTestScheduler, begin_copy_buffer_clear_attachments_end)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkBuffer> buffer_src(3u);
VkHandle<VkBuffer> buffer_dst(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, ResourceOwner::SWAP_CHAIN);
resources.add_buffer(buffer_src);
resources.add_buffer(buffer_dst);
@ -255,8 +249,7 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -266,14 +259,14 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
VKCopyBufferNode::CreateInfo copy_buffer = {};
copy_buffer.src_buffer = buffer_src;
copy_buffer.dst_buffer = buffer_dst;
render_graph.add_node(copy_buffer);
render_graph->add_node(copy_buffer);
}
{
@ -289,15 +282,15 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
clear_attachments.vk_clear_rect.layerCount = 1;
clear_attachments.vk_clear_rect.rect.extent.width = 1920;
clear_attachments.vk_clear_rect.rect.extent.height = 1080;
render_graph.add_node(clear_attachments);
render_graph->add_node(clear_attachments);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit_for_present(image);
render_graph->submit_for_present(image);
EXPECT_EQ(7, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -317,8 +310,8 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
" - image_barrier(src_access_mask=, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -327,8 +320,8 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -348,7 +341,9 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -357,16 +352,13 @@ TEST(vk_render_graph, begin_copy_buffer_clear_attachments_end)
log[6]);
}
TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
TEST_P(VKRenderGraphTestScheduler, begin_clear_attachments_copy_buffer_clear_attachments_end)
{
VkHandle<VkImage> image(1u);
VkHandle<VkImageView> image_view(2u);
VkHandle<VkBuffer> buffer_src(3u);
VkHandle<VkBuffer> buffer_dst(4u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, ResourceOwner::SWAP_CHAIN);
resources.add_buffer(buffer_src);
resources.add_buffer(buffer_dst);
@ -378,8 +370,7 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -389,7 +380,7 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -405,14 +396,14 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
clear_attachments.vk_clear_rect.layerCount = 1;
clear_attachments.vk_clear_rect.rect.extent.width = 1920;
clear_attachments.vk_clear_rect.rect.extent.height = 1080;
render_graph.add_node(clear_attachments);
render_graph->add_node(clear_attachments);
}
{
VKCopyBufferNode::CreateInfo copy_buffer = {};
copy_buffer.src_buffer = buffer_src;
copy_buffer.dst_buffer = buffer_dst;
render_graph.add_node(copy_buffer);
render_graph->add_node(copy_buffer);
}
{
@ -428,15 +419,15 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
clear_attachments.vk_clear_rect.layerCount = 1;
clear_attachments.vk_clear_rect.rect.extent.width = 1920;
clear_attachments.vk_clear_rect.rect.extent.height = 1080;
render_graph.add_node(clear_attachments);
render_graph->add_node(clear_attachments);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit_for_present(image);
render_graph->submit_for_present(image);
ASSERT_EQ(8, log.size());
EXPECT_EQ(
@ -457,8 +448,8 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
" - image_barrier(src_access_mask=, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -467,8 +458,8 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
" 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, "
endl() + " image_view=0x2, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -494,7 +485,9 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
"dst_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT" +
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=, old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"dst_access_mask=, old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -509,7 +502,7 @@ TEST(vk_render_graph, begin_clear_attachments_copy_buffer_clear_attachments_end)
* 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)
TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_framebuffer_draw_end)
{
VkHandle<VkImage> image_attachment(1u);
VkHandle<VkImage> image_feedback(2u);
@ -519,9 +512,6 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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(
@ -534,8 +524,7 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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].imageLayout = color_attachment_layout();
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;
@ -545,7 +534,7 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -560,7 +549,7 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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);
render_graph->add_node(draw);
}
{
@ -575,7 +564,7 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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);
render_graph->add_node(copy_image);
}
{
@ -590,15 +579,15 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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);
render_graph->add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit();
render_graph->submit();
ASSERT_EQ(12, log.size());
EXPECT_EQ(
@ -608,8 +597,8 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
" - 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() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -620,8 +609,8 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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, "
endl() + " image_view=0x3, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -637,7 +626,9 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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, "
"old_layout=" +
color_attachment_layout_str() +
", "
"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, "
@ -669,8 +660,8 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
" - image_barrier(src_access_mask=VK_ACCESS_TRANSFER_READ_BIT, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -681,8 +672,8 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
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, "
endl() + " image_view=0x3, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -698,7 +689,7 @@ TEST(vk_render_graph, begin_draw_copy_framebuffer_draw_end)
* Update buffers can be moved to before the rendering scope as when the destination buffer isn't
* used.
*/
TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
TEST_P(VKRenderGraphTestScheduler, begin_update_draw_update_draw_update_draw_end)
{
VkHandle<VkBuffer> buffer_a(1u);
VkHandle<VkBuffer> buffer_b(2u);
@ -707,10 +698,6 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
VkHandle<VkPipelineLayout> pipeline_layout(5u);
VkHandle<VkPipeline> pipeline(6u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_buffer(buffer_a);
resources.add_buffer(buffer_b);
@ -722,8 +709,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
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].imageLayout = color_attachment_layout();
begin_rendering.node_data.color_attachments[0].imageView = image_view;
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;
@ -733,7 +719,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -742,7 +728,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
update_buffer.data_size = 16;
update_buffer.data = MEM_callocN(16, __func__);
render_graph.add_node(update_buffer);
render_graph->add_node(update_buffer);
}
{
@ -758,7 +744,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
@ -767,7 +753,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
update_buffer.data_size = 24;
update_buffer.data = MEM_callocN(24, __func__);
render_graph.add_node(update_buffer);
render_graph->add_node(update_buffer);
}
{
@ -783,7 +769,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
@ -792,7 +778,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
update_buffer.data_size = 16;
update_buffer.data = MEM_callocN(16, __func__);
render_graph.add_node(update_buffer);
render_graph->add_node(update_buffer);
}
{
@ -808,15 +794,15 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit();
render_graph->submit();
ASSERT_EQ(17, log.size());
EXPECT_EQ("update_buffer(dst_buffer=0x1, dst_offset=0, data_size=16)", log[0]);
EXPECT_EQ("update_buffer(dst_buffer=0x2, dst_offset=0, data_size=24)", log[1]);
@ -827,7 +813,9 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
" - 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, "
"new_layout=" +
color_attachment_layout_str() +
", "
"image=0x3, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, "
@ -861,8 +849,8 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
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=0x4, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
endl() + " image_view=0x4, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -898,9 +886,11 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x3, subresource_range=" +
endl() +
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=" +
color_attachment_layout_str() + ", image=0x3, 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() + ")",
@ -911,8 +901,8 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
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=0x4, image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
endl() + " image_view=0x4, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -928,7 +918,7 @@ TEST(vk_render_graph, begin_update_draw_update_draw_update_draw_end)
*
* This case happens when updating the swap-chain image with the result of editors.
*/
TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
TEST_P(VKRenderGraphTestScheduler, begin_draw_copy_to_attachment_draw_end)
{
VkHandle<VkImage> image_attachment(1u);
VkHandle<VkImage> image_editor(2u);
@ -936,9 +926,6 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
VkHandle<VkPipelineLayout> pipeline_layout(4u);
VkHandle<VkPipeline> pipeline(5u);
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(
@ -951,8 +938,7 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
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].imageLayout = color_attachment_layout();
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;
@ -962,7 +948,7 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
begin_rendering.node_data.vk_rendering_info.pColorAttachments =
begin_rendering.node_data.color_attachments;
render_graph.add_node(begin_rendering);
render_graph->add_node(begin_rendering);
}
{
@ -977,7 +963,7 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
@ -992,7 +978,7 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
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);
render_graph->add_node(copy_image);
}
{
@ -1007,15 +993,15 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
draw.node_data.pipeline_data.vk_descriptor_set = VK_NULL_HANDLE;
draw.node_data.pipeline_data.vk_pipeline = pipeline;
draw.node_data.pipeline_data.vk_pipeline_layout = pipeline_layout;
render_graph.add_node(draw);
render_graph->add_node(draw);
}
{
VKEndRenderingNode::CreateInfo end_rendering = {};
render_graph.add_node(end_rendering);
render_graph->add_node(end_rendering);
}
render_graph.submit();
render_graph->submit();
ASSERT_EQ(11, log.size());
EXPECT_EQ(
"pipeline_barrier(src_stage_mask=VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "
@ -1024,8 +1010,8 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
" - 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() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -1036,8 +1022,8 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
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, "
endl() + " image_view=0x3, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -1060,7 +1046,9 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
endl() +
" - image_barrier(src_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"dst_access_mask=VK_ACCESS_TRANSFER_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "
"old_layout=" +
color_attachment_layout_str() +
", "
"new_layout=VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image=0x1, subresource_range=" +
endl() +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, base_mip_level=0, level_count=4294967295, "
@ -1085,8 +1073,8 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
" - image_barrier(src_access_mask=VK_ACCESS_TRANSFER_WRITE_BIT, "
"dst_access_mask=VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, "
"old_layout=VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "
"new_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image=0x1, subresource_range=" +
endl() +
"new_layout=" +
color_attachment_layout_str() + ", 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() + ")",
@ -1097,8 +1085,8 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
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, "
endl() + " image_view=0x3, image_layout=" + color_attachment_layout_str() +
", "
"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" +
@ -1108,4 +1096,9 @@ TEST(vk_render_graph, begin_draw_copy_to_attachment_draw_end)
EXPECT_EQ("end_rendering()", log[10]);
}
INSTANTIATE_TEST_SUITE_P(,
VKRenderGraphTestScheduler,
::testing::Values(std::make_tuple(true, true),
std::make_tuple(true, false)));
} // namespace blender::gpu::render_graph

View file

@ -8,20 +8,19 @@
namespace blender::gpu::render_graph {
class VKRenderGraphTestTransfer : public VKRenderGraphTest {};
/**
* Fill a single buffer and read it back.
*/
TEST(vk_render_graph, fill_and_read_back)
TEST_F(VKRenderGraphTestTransfer, fill_and_read_back)
{
VkHandle<VkBuffer> buffer(1u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
VKFillBufferNode::CreateInfo fill_buffer = {buffer, 1024, 42};
render_graph.add_node(fill_buffer);
render_graph.submit_buffer_for_read(buffer);
render_graph->add_node(fill_buffer);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(1, log.size());
EXPECT_EQ("fill_buffer(dst_buffer=0x1, dst_offset=0, size=1024, data=42)", log[0]);
@ -30,17 +29,14 @@ TEST(vk_render_graph, fill_and_read_back)
/**
* Fill a single buffer, copy it to a staging buffer and read the staging buffer back.
*/
TEST(vk_render_graph, fill_transfer_and_read_back)
TEST_F(VKRenderGraphTestTransfer, fill_transfer_and_read_back)
{
VkHandle<VkBuffer> buffer(1u);
VkHandle<VkBuffer> staging_buffer(2u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
VKFillBufferNode::CreateInfo fill_buffer = {buffer, 1024, 42};
render_graph.add_node(fill_buffer);
render_graph->add_node(fill_buffer);
resources.add_buffer(staging_buffer);
VKCopyBufferNode::CreateInfo copy_buffer = {};
@ -49,9 +45,9 @@ TEST(vk_render_graph, fill_transfer_and_read_back)
copy_buffer.region.srcOffset = 0;
copy_buffer.region.dstOffset = 0;
copy_buffer.region.size = 1024;
render_graph.add_node(copy_buffer);
render_graph->add_node(copy_buffer);
render_graph.submit_buffer_for_read(staging_buffer);
render_graph->submit_buffer_for_read(staging_buffer);
EXPECT_EQ(3, log.size());
EXPECT_EQ("fill_buffer(dst_buffer=0x1, dst_offset=0, size=1024, data=42)", log[0]);
@ -74,19 +70,16 @@ TEST(vk_render_graph, fill_transfer_and_read_back)
*
* Between the two fills a write->write barrier should be created.
*/
TEST(vk_render_graph, fill_fill_read_back)
TEST_F(VKRenderGraphTestTransfer, fill_fill_read_back)
{
VkHandle<VkBuffer> buffer(1u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_buffer(buffer);
VKFillBufferNode::CreateInfo fill_buffer_1 = {buffer, 1024, 0};
render_graph.add_node(fill_buffer_1);
render_graph->add_node(fill_buffer_1);
VKFillBufferNode::CreateInfo fill_buffer_2 = {buffer, 1024, 42};
render_graph.add_node(fill_buffer_2);
render_graph.submit_buffer_for_read(buffer);
render_graph->add_node(fill_buffer_2);
render_graph->submit_buffer_for_read(buffer);
EXPECT_EQ(3, log.size());
EXPECT_EQ("fill_buffer(dst_buffer=0x1, dst_offset=0, size=1024, data=0)", log[0]);
@ -105,15 +98,12 @@ TEST(vk_render_graph, fill_fill_read_back)
/**
* Fill a single buffer, copy it to a staging buffer and read the staging buffer back.
*/
TEST(vk_render_graph, clear_clear_copy_and_read_back)
TEST_F(VKRenderGraphTestTransfer, clear_clear_copy_and_read_back)
{
VkHandle<VkImage> src_image(1u);
VkHandle<VkImage> dst_image(2u);
VkHandle<VkBuffer> staging_buffer(3u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(src_image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_image(dst_image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_buffer(staging_buffer);
@ -148,11 +138,11 @@ TEST(vk_render_graph, clear_clear_copy_and_read_back)
VK_IMAGE_ASPECT_COLOR_BIT;
copy_dst_image_to_buffer.vk_image_aspects = VK_IMAGE_ASPECT_COLOR_BIT;
render_graph.add_node(clear_color_image_src);
render_graph.add_node(clear_color_image_dst);
render_graph.add_node(copy_image);
render_graph.add_node(copy_dst_image_to_buffer);
render_graph.submit_buffer_for_read(staging_buffer);
render_graph->add_node(clear_color_image_src);
render_graph->add_node(clear_color_image_dst);
render_graph->add_node(copy_image);
render_graph->add_node(copy_dst_image_to_buffer);
render_graph->submit_buffer_for_read(staging_buffer);
EXPECT_EQ(8, log.size());
EXPECT_EQ(
@ -249,15 +239,12 @@ TEST(vk_render_graph, clear_clear_copy_and_read_back)
/**
* Clear an image, blit it to another image, copy to a staging buffer and read back.
*/
TEST(vk_render_graph, clear_blit_copy_and_read_back)
TEST_F(VKRenderGraphTestTransfer, clear_blit_copy_and_read_back)
{
VkHandle<VkImage> src_image(1u);
VkHandle<VkImage> dst_image(2u);
VkHandle<VkBuffer> staging_buffer(3u);
Vector<std::string> log;
VKResourceStateTracker resources;
VKRenderGraph render_graph(std::make_unique<CommandBufferLog>(log), resources);
resources.add_image(src_image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_image(dst_image, 1, VK_IMAGE_LAYOUT_UNDEFINED, ResourceOwner::APPLICATION);
resources.add_buffer(staging_buffer);
@ -277,11 +264,11 @@ TEST(vk_render_graph, clear_blit_copy_and_read_back)
VK_IMAGE_ASPECT_COLOR_BIT;
copy_dst_image_to_buffer.vk_image_aspects = VK_IMAGE_ASPECT_COLOR_BIT;
render_graph.add_node(clear_color_image_src);
render_graph->add_node(clear_color_image_src);
VKBlitImageNode::CreateInfo blit_image = {src_image, dst_image, vk_image_blit, VK_FILTER_LINEAR};
render_graph.add_node(blit_image);
render_graph.add_node(copy_dst_image_to_buffer);
render_graph.submit_buffer_for_read(staging_buffer);
render_graph->add_node(blit_image);
render_graph->add_node(copy_dst_image_to_buffer);
render_graph->submit_buffer_for_read(staging_buffer);
EXPECT_EQ(6, log.size());
EXPECT_EQ(
@ -353,4 +340,5 @@ TEST(vk_render_graph, clear_blit_copy_and_read_back)
" width=0, height=0, depth=0 )" + endl() + ")",
log[5]);
}
} // namespace blender::gpu::render_graph

View file

@ -30,7 +30,14 @@ class CommandBufferLog : public VKCommandBufferInterface {
bool is_cpu_synchronizing_ = false;
public:
CommandBufferLog(Vector<std::string> &log) : log_(log) {}
CommandBufferLog(Vector<std::string> &log,
bool use_dynamic_rendering_ = true,
bool use_dynamic_rendering_local_read_ = true)
: log_(log)
{
use_dynamic_rendering = use_dynamic_rendering_;
use_dynamic_rendering_local_read = use_dynamic_rendering_local_read_;
}
virtual ~CommandBufferLog() {}
void begin_recording() override
@ -468,6 +475,59 @@ class CommandBufferLog : public VKCommandBufferInterface {
void end_debug_utils_label() override {}
};
class VKRenderGraphTest : public ::testing::Test {
public:
VKRenderGraphTest()
{
resources.use_dynamic_rendering = use_dynamic_rendering;
resources.use_dynamic_rendering_local_read = use_dynamic_rendering_local_read;
render_graph = std::make_unique<VKRenderGraph>(
std::make_unique<CommandBufferLog>(
log, use_dynamic_rendering, use_dynamic_rendering_local_read),
resources);
}
protected:
Vector<std::string> log;
VKResourceStateTracker resources;
std::unique_ptr<VKRenderGraph> render_graph;
bool use_dynamic_rendering = true;
bool use_dynamic_rendering_local_read = true;
};
class VKRenderGraphTest_P : public ::testing::TestWithParam<std::tuple<bool, bool>> {
public:
VKRenderGraphTest_P()
{
use_dynamic_rendering = std::get<0>(GetParam());
use_dynamic_rendering_local_read = std::get<1>(GetParam());
resources.use_dynamic_rendering = use_dynamic_rendering;
resources.use_dynamic_rendering_local_read = use_dynamic_rendering_local_read;
render_graph = std::make_unique<VKRenderGraph>(
std::make_unique<CommandBufferLog>(
log, use_dynamic_rendering, use_dynamic_rendering_local_read),
resources);
}
protected:
VkImageLayout color_attachment_layout() const
{
return use_dynamic_rendering_local_read ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
std::string color_attachment_layout_str() const
{
return use_dynamic_rendering_local_read ? "VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR" :
"VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL";
}
Vector<std::string> log;
VKResourceStateTracker resources;
std::unique_ptr<VKRenderGraph> render_graph;
bool use_dynamic_rendering = true;
bool use_dynamic_rendering_local_read = true;
};
/**
* Union to create a dummy vulkan handler.
*

View file

@ -42,6 +42,7 @@ VKCommandBufferWrapper::VKCommandBufferWrapper(const VKWorkarounds &workarounds)
vk_submit_info_.pSignalSemaphores = nullptr;
use_dynamic_rendering = !workarounds.dynamic_rendering;
use_dynamic_rendering_local_read = !workarounds.dynamic_rendering_local_read;
}
VKCommandBufferWrapper::~VKCommandBufferWrapper()

View file

@ -18,6 +18,7 @@ namespace blender::gpu::render_graph {
class VKCommandBufferInterface {
public:
bool use_dynamic_rendering = true;
bool use_dynamic_rendering_local_read = true;
VKCommandBufferInterface() {}
virtual ~VKCommandBufferInterface() = default;

View file

@ -7,6 +7,7 @@
*/
#include "vk_command_builder.hh"
#include "vk_backend.hh"
#include "vk_render_graph.hh"
#include "vk_to_string.hh"
@ -83,12 +84,23 @@ void VKCommandBuilder::build_nodes(VKRenderGraph &render_graph,
command_buffer.end_recording();
}
bool VKCommandBuilder::node_has_input_attachments(const VKRenderGraph &render_graph,
NodeHandle node)
{
const VKRenderGraphNodeLinks &links = render_graph.links_[node];
const Vector<VKRenderGraphLink> &inputs = links.inputs;
return std::any_of(inputs.begin(), inputs.end(), [](const VKRenderGraphLink &input) {
return input.vk_access_flags & VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
});
}
void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
VKCommandBufferInterface &command_buffer,
Span<NodeHandle> node_group,
std::optional<NodeHandle> &r_rendering_scope)
{
bool is_rendering = false;
const bool supports_local_read = command_buffer.use_dynamic_rendering_local_read;
for (NodeHandle node_handle : node_group) {
VKRenderGraphNode &node = render_graph.nodes_[node_handle];
@ -100,7 +112,8 @@ void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
#if 0
render_graph.debug_print(node_handle);
#endif
build_pipeline_barriers(render_graph, command_buffer, node_handle, node.pipeline_stage_get());
build_pipeline_barriers(
render_graph, command_buffer, node_handle, node.pipeline_stage_get(), false);
if (node.type == VKNodeType::BEGIN_RENDERING) {
layer_tracking_begin(render_graph, node_handle);
}
@ -142,6 +155,10 @@ void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
rendering_node.build_commands(command_buffer, state_.active_pipelines);
is_rendering = true;
}
else if (supports_local_read && node_has_input_attachments(render_graph, node_handle)) {
build_pipeline_barriers(
render_graph, command_buffer, node_handle, node.pipeline_stage_get(), true);
}
}
if (G.debug & G_DEBUG_GPU) {
activate_debug_group(render_graph, command_buffer, node_handle);
@ -246,12 +263,13 @@ void VKCommandBuilder::finish_debug_groups(VKCommandBufferInterface &command_buf
void VKCommandBuilder::build_pipeline_barriers(VKRenderGraph &render_graph,
VKCommandBufferInterface &command_buffer,
NodeHandle node_handle,
VkPipelineStageFlags pipeline_stage)
VkPipelineStageFlags pipeline_stage,
bool within_rendering)
{
reset_barriers();
add_image_barriers(render_graph, node_handle, pipeline_stage);
add_image_barriers(render_graph, node_handle, pipeline_stage, within_rendering);
add_buffer_barriers(render_graph, node_handle, pipeline_stage);
send_pipeline_barriers(command_buffer);
send_pipeline_barriers(command_buffer, within_rendering);
}
/** \} */
@ -268,7 +286,8 @@ void VKCommandBuilder::reset_barriers()
state_.dst_stage_mask = VK_PIPELINE_STAGE_NONE;
}
void VKCommandBuilder::send_pipeline_barriers(VKCommandBufferInterface &command_buffer)
void VKCommandBuilder::send_pipeline_barriers(VKCommandBufferInterface &command_buffer,
bool within_rendering)
{
if (vk_image_memory_barriers_.is_empty() && vk_buffer_memory_barriers_.is_empty()) {
reset_barriers();
@ -282,8 +301,24 @@ void VKCommandBuilder::send_pipeline_barriers(VKCommandBufferInterface &command_
state_.src_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
command_buffer.pipeline_barrier(state_.src_stage_mask,
state_.dst_stage_mask,
VkPipelineStageFlags src_stage_mask;
VkPipelineStageFlags dst_stage_mask;
if (within_rendering) {
/* See: VUID - vkCmdPipelineBarrier - srcStageMask - 09556
* If vkCmdPipelineBarrier is called within a render pass instance started with
* vkCmdBeginRendering, this command must only specify framebuffer-space stages in srcStageMask
* and dstStageMask */
src_stage_mask = dst_stage_mask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
}
else {
src_stage_mask = state_.src_stage_mask;
dst_stage_mask = state_.dst_stage_mask;
}
command_buffer.pipeline_barrier(src_stage_mask,
dst_stage_mask,
VK_DEPENDENCY_BY_REGION_BIT,
0,
nullptr,
@ -401,15 +436,17 @@ void VKCommandBuilder::add_buffer_barrier(VkBuffer vk_buffer,
void VKCommandBuilder::add_image_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages)
VkPipelineStageFlags node_stages,
bool within_rendering)
{
add_image_read_barriers(render_graph, node_handle, node_stages);
add_image_write_barriers(render_graph, node_handle, node_stages);
add_image_read_barriers(render_graph, node_handle, node_stages, within_rendering);
add_image_write_barriers(render_graph, node_handle, node_stages, within_rendering);
}
void VKCommandBuilder::add_image_read_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages)
VkPipelineStageFlags node_stages,
bool within_rendering)
{
for (const VKRenderGraphLink &link : render_graph.links_[node_handle].inputs) {
const ResourceWithStamp &versioned_resource = link.resource;
@ -429,6 +466,10 @@ void VKCommandBuilder::add_image_read_barriers(VKRenderGraph &render_graph,
/* Has already been covered in previous barrier no need to add this one. */
continue;
}
if (within_rendering && link.vk_image_layout != VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) {
/* Allow only local read barriers inside rendering scope */
continue;
}
if (state_.layered_attachments.contains(resource.image.vk_image) &&
resource_state.image_layout != link.vk_image_layout)
@ -467,7 +508,8 @@ void VKCommandBuilder::add_image_read_barriers(VKRenderGraph &render_graph,
void VKCommandBuilder::add_image_write_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages)
VkPipelineStageFlags node_stages,
bool within_rendering)
{
for (const VKRenderGraphLink link : render_graph.links_[node_handle].outputs) {
const ResourceWithStamp &versioned_resource = link.resource;
@ -479,7 +521,10 @@ void VKCommandBuilder::add_image_write_barriers(VKRenderGraph &render_graph,
}
VKResourceBarrierState &resource_state = resource.barrier_state;
const VkAccessFlags wait_access = resource_state.vk_access;
if (within_rendering && link.vk_image_layout != VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) {
/* Allow only local read barriers inside rendering scope */
continue;
}
if (state_.layered_attachments.contains(resource.image.vk_image) &&
resource_state.image_layout != link.vk_image_layout)
{
@ -626,6 +671,8 @@ void VKCommandBuilder::layer_tracking_end(VKCommandBufferInterface &command_buff
void VKCommandBuilder::layer_tracking_suspend(VKCommandBufferInterface &command_buffer)
{
const bool supports_local_read = command_buffer.use_dynamic_rendering_local_read;
if (state_.layered_bindings.is_empty()) {
return;
}
@ -644,6 +691,7 @@ void VKCommandBuilder::layer_tracking_suspend(VKCommandBufferInterface &command_
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
binding.vk_image_layout,
supports_local_read ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_ASPECT_COLOR_BIT,
binding.layer,
@ -655,7 +703,7 @@ void VKCommandBuilder::layer_tracking_suspend(VKCommandBufferInterface &command_
<< ", to_layout=" << to_string(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) << "\n";
#endif
}
send_pipeline_barriers(command_buffer);
send_pipeline_barriers(command_buffer, false);
}
void VKCommandBuilder::layer_tracking_resume(VKCommandBufferInterface &command_buffer)
@ -668,6 +716,7 @@ void VKCommandBuilder::layer_tracking_resume(VKCommandBufferInterface &command_b
/* We should be able to do better. BOTTOM/TOP is really a worst case barrier. */
state_.src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
state_.dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
const bool supports_local_read = command_buffer.use_dynamic_rendering_local_read;
for (const LayeredImageBinding &binding : state_.layered_bindings) {
add_image_barrier(
binding.vk_image,
@ -677,6 +726,7 @@ void VKCommandBuilder::layer_tracking_resume(VKCommandBufferInterface &command_b
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
supports_local_read ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
binding.vk_image_layout,
VK_IMAGE_ASPECT_COLOR_BIT,
@ -689,7 +739,7 @@ void VKCommandBuilder::layer_tracking_resume(VKCommandBufferInterface &command_b
<< ", to_layout=" << to_string(binding.vk_image_layout) << "\n";
#endif
}
send_pipeline_barriers(command_buffer);
send_pipeline_barriers(command_buffer, false);
}
/** \} */

View file

@ -122,9 +122,10 @@ class VKCommandBuilder {
void build_pipeline_barriers(VKRenderGraph &render_graph,
VKCommandBufferInterface &command_buffer,
NodeHandle node_handle,
VkPipelineStageFlags pipeline_stage);
VkPipelineStageFlags pipeline_stage,
bool within_rendering = false);
void reset_barriers();
void send_pipeline_barriers(VKCommandBufferInterface &command_buffer);
void send_pipeline_barriers(VKCommandBufferInterface &command_buffer, bool within_rendering);
void add_buffer_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
@ -141,7 +142,8 @@ class VKCommandBuilder {
void add_image_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages);
VkPipelineStageFlags node_stages,
bool within_rendering);
void add_image_barrier(VkImage vk_image,
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
@ -152,10 +154,12 @@ class VKCommandBuilder {
uint32_t layer_count = VK_REMAINING_ARRAY_LAYERS);
void add_image_read_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages);
VkPipelineStageFlags node_stages,
bool within_rendering);
void add_image_write_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages);
VkPipelineStageFlags node_stages,
bool within_rendering);
/**
* Ensure that the debug group associated with the given node_handle is activated.
@ -218,6 +222,8 @@ class VKCommandBuilder {
* state.
*/
void layer_tracking_resume(VKCommandBufferInterface &command_buffer);
bool node_has_input_attachments(const VKRenderGraph &render_graph, NodeHandle node);
};
} // namespace blender::gpu::render_graph

View file

@ -7,19 +7,26 @@
*/
#include "vk_resource_access_info.hh"
#include "vk_backend.hh"
#include "vk_render_graph_links.hh"
#include "vk_resource_state_tracker.hh"
namespace blender::gpu::render_graph {
VkImageLayout VKImageAccess::to_vk_image_layout() const
VkImageLayout VKImageAccess::to_vk_image_layout(bool supports_local_read) const
{
if (vk_access_flags & (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT)) {
/* TODO: when read only use VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL */
return VK_IMAGE_LAYOUT_GENERAL;
}
if (vk_access_flags &
if (supports_local_read && vk_access_flags & (VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT))
{
return VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
}
else if (vk_access_flags &
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT))
{
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@ -67,8 +74,10 @@ void VKResourceAccessInfo::build_links(VKResourceStateTracker &resources,
}
}
const bool supports_local_read = resources.use_dynamic_rendering_local_read;
for (const VKImageAccess &image_access : images) {
VkImageLayout image_layout = image_access.to_vk_image_layout();
VkImageLayout image_layout = image_access.to_vk_image_layout(supports_local_read);
const bool writes_to_resource = bool(image_access.vk_access_flags & VK_ACCESS_WRITE_MASK);
ResourceWithStamp versioned_resource = writes_to_resource ?
resources.get_image_and_increase_stamp(

View file

@ -41,7 +41,7 @@ struct VKImageAccess {
uint32_t layer_count;
/** Determine the image layout for the vk_access_flags. */
VkImageLayout to_vk_image_layout() const;
VkImageLayout to_vk_image_layout(bool supports_local_read) const;
};
/** Struct describing the access to a buffer. */

View file

@ -319,6 +319,9 @@ class VKResourceStateTracker {
return resources_.lookup(resource_handle).type;
}
bool use_dynamic_rendering = true;
bool use_dynamic_rendering_local_read = true;
private:
/**
* Get the current stamp of the resource.

View file

@ -356,6 +356,7 @@ void VKBackend::detect_workarounds(VKDevice &device)
workarounds.vertex_formats.r8g8b8 = true;
workarounds.fragment_shader_barycentric = true;
workarounds.dynamic_rendering = true;
workarounds.dynamic_rendering_local_read = true;
workarounds.dynamic_rendering_unused_attachments = true;
GCaps.render_pass_workaround = true;
@ -372,6 +373,8 @@ void VKBackend::detect_workarounds(VKDevice &device)
VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
workarounds.dynamic_rendering = !device.supports_extension(
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
workarounds.dynamic_rendering_local_read = !device.supports_extension(
VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME);
workarounds.dynamic_rendering_unused_attachments = !device.supports_extension(
VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME);
workarounds.logic_ops = !device.physical_device_features_get().logicOp;

View file

@ -150,11 +150,29 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
const VKResourceBinding &resource_binding,
render_graph::VKResourceAccessInfo &access_info)
{
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
if (supports_local_read) {
VKTexture *texture = static_cast<VKTexture *>(
state_manager.images_.get(resource_binding.binding));
BLI_assert(texture);
bind_image(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
VK_NULL_HANDLE,
texture->image_view_get(resource_binding.arrayed).vk_handle(),
VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR,
resource_binding.location);
access_info.images.append({texture->vk_image_handle(),
resource_binding.access_mask,
to_vk_image_aspect_flag_bits(texture->device_format_get()),
0,
VK_REMAINING_ARRAY_LAYERS});
}
else {
bool supports_dynamic_rendering = !device.workarounds_get().dynamic_rendering;
const BindSpaceTextures::Elem &elem = state_manager.textures_.get(resource_binding.binding);
VKTexture *texture = static_cast<VKTexture *>(elem.resource);
BLI_assert(texture);
BLI_assert(elem.resource_type == BindSpaceTextures::Type::Texture);
if (!device.workarounds_get().dynamic_rendering) {
if (supports_dynamic_rendering) {
const VKSampler &sampler = device.samplers().get(elem.sampler);
bind_image(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
sampler.vk_handle(),
@ -168,6 +186,7 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
VK_REMAINING_ARRAY_LAYERS});
}
else {
/* Fallback to renderpasses / subpasses. */
bind_image(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
VK_NULL_HANDLE,
texture->image_view_get(resource_binding.arrayed).vk_handle(),
@ -180,6 +199,7 @@ void VKDescriptorSetTracker::bind_input_attachment_resource(
VK_REMAINING_ARRAY_LAYERS});
}
}
}
void VKDescriptorSetTracker::bind_storage_buffer_resource(
const VKStateManager &state_manager,

View file

@ -102,6 +102,9 @@ void VKDevice::init(void *ghost_context)
debug::object_label(vk_handle(), "LogicalDevice");
debug::object_label(queue_get(), "GenericQueue");
init_glsl_patch();
resources.use_dynamic_rendering = !workarounds_.dynamic_rendering;
resources.use_dynamic_rendering_local_read = !workarounds_.dynamic_rendering_local_read;
}
void VKDevice::init_functions()

View file

@ -68,6 +68,11 @@ struct VKWorkarounds {
*/
bool dynamic_rendering = false;
/**
* Is the workarounds for devices that don't support VK_KHR_dynamic_rendering_local_read enabled.
*/
bool dynamic_rendering_local_read = false;
/**
* Is the workarounds for devices that don't support VK_EXT_dynamic_rendering_unused_attachments
* enabled.

View file

@ -331,9 +331,22 @@ static void set_load_store(VkRenderingAttachmentInfo &r_rendering_attachment,
void VKFrameBuffer::subpass_transition_impl(const GPUAttachmentState depth_attachment_state,
Span<GPUAttachmentState> color_attachment_states)
{
/* TODO: this is a fallback implementation. We should also provide support for
* `VK_EXT_dynamic_rendering_local_read`. This extension is only supported on Windows
* platforms (2024Q2), but would reduce the rendering synchronization overhead. */
const VKDevice &device = VKBackend::get().device;
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
if (supports_local_read) {
VKContext &context = *VKContext::get();
for (int index : IndexRange(color_attachment_states.size())) {
if (color_attachment_states[index] == GPU_ATTACHMENT_READ) {
VKTexture *texture = unwrap(unwrap(color_tex(index)));
if (texture) {
context.state_manager_get().image_bind(texture, index);
}
}
}
load_stores.fill(default_load_store());
}
else {
VKContext &context = *VKContext::get();
if (is_rendering_) {
rendering_end(context);
@ -359,6 +372,7 @@ void VKFrameBuffer::subpass_transition_impl(const GPUAttachmentState depth_attac
}
}
}
}
/** \} */
@ -802,6 +816,9 @@ void VKFrameBuffer::rendering_ensure_render_pass(VKContext &context)
void VKFrameBuffer::rendering_ensure_dynamic_rendering(VKContext &context,
const VKWorkarounds &workarounds)
{
const VKDevice &device = VKBackend::get().device;
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
depth_attachment_format_ = VK_FORMAT_UNDEFINED;
stencil_attachment_format_ = VK_FORMAT_UNDEFINED;
@ -857,7 +874,8 @@ void VKFrameBuffer::rendering_ensure_dynamic_rendering(VKContext &context,
vk_format = image_view.vk_format();
}
attachment_info.imageView = vk_image_view;
attachment_info.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_info.imageLayout = supports_local_read ? VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
set_load_store(attachment_info, load_stores[color_attachment_index]);
access_info.images.append(

View file

@ -973,8 +973,46 @@ std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo
ss << "\n/* Sub-pass Inputs. */\n";
const VKShaderInterface &interface = interface_get();
const bool use_local_read = !workarounds.dynamic_rendering_local_read;
const bool use_dynamic_rendering = !workarounds.dynamic_rendering;
if (use_dynamic_rendering) {
if (use_local_read) {
uint32_t subpass_input_binding_index = 0;
for (const ShaderCreateInfo::SubpassIn &input : info.subpass_inputs_) {
std::string input_attachment_name = "gpu_input_attachment_";
input_attachment_name += std::to_string(input.index);
/* Declare global for input. */
ss << to_string(input.type) << " " << input.name << ";\n";
Type component_type = to_component_type(input.type);
char typePrefix;
switch (component_type) {
case Type::INT:
typePrefix = 'i';
break;
case Type::UINT:
typePrefix = 'u';
break;
default:
typePrefix = ' ';
break;
}
ss << "layout(input_attachment_index = " << (input.index)
<< ", binding = " << (subpass_input_binding_index++) << ") uniform " << typePrefix
<< "subpassInput " << input_attachment_name << "; \n";
std::stringstream ss_pre;
static const std::string swizzle = "xyzw";
/* Populate the global before main using subpassLoad. */
ss_pre << " " << input.name << " = " << input.type << "( subpassLoad("
<< input_attachment_name << ")." << swizzle.substr(0, to_component_count(input.type))
<< " ); \n";
pre_main += ss_pre.str();
}
}
else if (use_dynamic_rendering) {
for (const ShaderCreateInfo::SubpassIn &input : info.subpass_inputs_) {
std::string image_name = "gpu_subpass_img_";
image_name += std::to_string(input.index);

View file

@ -63,14 +63,12 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
break;
}
}
/* Sub-pass inputs are read as samplers.
* In future this can change depending on extensions that will be supported. */
const VKDevice &device = VKBackend::get().device;
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
uniform_len_ += info.subpass_inputs_.size();
/* Reserve 1 uniform buffer for push constants fallback. */
size_t names_size = info.interface_names_size_;
const VKDevice &device = VKBackend::get().device;
const VKPushConstants::StorageType push_constants_storage_type =
VKPushConstants::Layout::determine_storage_type(info, device);
if (push_constants_storage_type == VKPushConstants::StorageType::UNIFORM_BUFFER) {
@ -200,10 +198,13 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
uint32_t descriptor_set_location = 0;
for (const ShaderCreateInfo::SubpassIn &subpass_in : info.subpass_inputs_) {
const ShaderInput *input = shader_input_get(
shader::ShaderCreateInfo::Resource::BindType::SAMPLER, subpass_in.index);
BLI_assert(STREQ(input_name_get(input), SUBPASS_FALLBACK_NAME));
const ShaderInput *input = supports_local_read ?
texture_get(subpass_in.index) :
shader_input_get(
shader::ShaderCreateInfo::Resource::BindType::SAMPLER,
subpass_in.index);
BLI_assert(input);
BLI_assert(STREQ(input_name_get(input), SUBPASS_FALLBACK_NAME));
descriptor_set_location_update(input,
descriptor_set_location++,
VKBindType::INPUT_ATTACHMENT,
@ -292,6 +293,9 @@ void VKShaderInterface::descriptor_set_location_update(
BLI_assert_msg(!resource.has_value() || to_bind_type(resource->bind_type) == bind_type,
"Incorrect parameter, bind types do not match.");
const VKDevice &device = VKBackend::get().device;
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
int32_t index = shader_input_index(inputs_, shader_input);
BLI_assert(resource_bindings_[index].binding == -1);
@ -329,7 +333,9 @@ void VKShaderInterface::descriptor_set_location_update(
vk_access_flags |= VK_ACCESS_UNIFORM_READ_BIT;
}
else if (bind_type == VKBindType::INPUT_ATTACHMENT) {
vk_access_flags |= VK_ACCESS_SHADER_READ_BIT;
vk_access_flags |= supports_local_read ? VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT :
VK_ACCESS_SHADER_READ_BIT;
}
VKResourceBinding &resource_binding = resource_bindings_[index];
@ -403,15 +409,26 @@ void VKShaderInterface::init_descriptor_set_layout_info(
{
BLI_assert(descriptor_set_layout_info_.bindings.is_empty());
const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
const bool supports_local_read = !workarounds.dynamic_rendering_local_read;
descriptor_set_layout_info_.bindings.reserve(resources_len);
descriptor_set_layout_info_.vk_shader_stage_flags =
info.compute_source_.is_empty() && info.compute_source_generated.empty() ?
VK_SHADER_STAGE_ALL_GRAPHICS :
VK_SHADER_STAGE_COMPUTE_BIT;
if (!(info.compute_source_.is_empty() && info.compute_source_generated.empty())) {
descriptor_set_layout_info_.vk_shader_stage_flags = VK_SHADER_STAGE_COMPUTE_BIT;
}
else if (supports_local_read && !info.subpass_inputs_.is_empty()) {
descriptor_set_layout_info_.vk_shader_stage_flags = VK_SHADER_STAGE_FRAGMENT_BIT;
}
else {
descriptor_set_layout_info_.vk_shader_stage_flags = VK_SHADER_STAGE_ALL_GRAPHICS;
}
for (int index : IndexRange(info.subpass_inputs_.size())) {
UNUSED_VARS(index);
descriptor_set_layout_info_.bindings.append_n_times(
workarounds.dynamic_rendering ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
workarounds.dynamic_rendering_local_read ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER :
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
info.subpass_inputs_.size());
}
for (const shader::ShaderCreateInfo::Resource &res : all_resources) {
descriptor_set_layout_info_.bindings.append(to_vk_descriptor_type(res));
}

View file

@ -422,6 +422,10 @@ bool VKTexture::is_texture_view() const
static VkImageUsageFlags to_vk_image_usage(const eGPUTextureUsage usage,
const eGPUTextureFormatFlag format_flag)
{
const VKDevice &device = VKBackend::get().device;
const bool supports_local_read = !device.workarounds_get().dynamic_rendering_local_read;
const bool supports_dynamic_rendering = !device.workarounds_get().dynamic_rendering;
VkImageUsageFlags result = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
if (usage & GPU_TEXTURE_USAGE_SHADER_READ) {
@ -441,8 +445,7 @@ static VkImageUsageFlags to_vk_image_usage(const eGPUTextureUsage usage,
}
else {
result |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
const VKWorkarounds &workarounds = VKBackend::get().device.workarounds_get();
if (workarounds.dynamic_rendering) {
if (supports_local_read || (!supports_dynamic_rendering)) {
result |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
}

View file

@ -124,6 +124,9 @@ const char *to_string(const VkImageLayout vk_image_layout)
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
return STRINGIFY(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
case VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR:
return STRINGIFY(VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR);
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
return STRINGIFY(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);