From be75f1ac2bc645ae777b37efb537aebf3d96a10a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 19 Apr 2024 14:55:39 +0200 Subject: [PATCH] Vulkan: Render graph textures This PR implements render graph for VKTexture. During the implementation some tweaks to the render graph was done to support depth and stencil textures. The render graph will record the image aspect being used for each node. This will then be used to generate barriers for the correct aspect. Also fixes an issue that uploading of array textures didn't allocate a large enough staging buffer. Pull Request: https://projects.blender.org/blender/blender/pulls/120821 --- source/blender/gpu/CMakeLists.txt | 1 + .../render_graph/nodes/vk_blit_image_node.hh | 12 +- .../nodes/vk_clear_color_image_node.hh | 6 +- .../vk_clear_depth_stencil_image_node.hh | 70 ++++++ .../nodes/vk_copy_buffer_to_image_node.hh | 6 +- .../render_graph/nodes/vk_copy_image_node.hh | 12 +- .../nodes/vk_copy_image_to_buffer_node.hh | 6 +- .../vulkan/render_graph/nodes/vk_node_info.hh | 1 + .../nodes/vk_synchronization_node.hh | 7 +- .../tests/vk_render_graph_test_transfer.cc | 16 +- .../vulkan/render_graph/vk_command_builder.cc | 13 +- .../vulkan/render_graph/vk_command_builder.hh | 3 +- .../vulkan/render_graph/vk_render_graph.cc | 1 + .../vulkan/render_graph/vk_render_graph.hh | 4 + .../render_graph/vk_render_graph_links.hh | 7 +- .../render_graph/vk_render_graph_node.hh | 11 + .../render_graph/vk_resource_access_info.cc | 12 +- .../render_graph/vk_resource_access_info.hh | 1 + source/blender/gpu/vulkan/vk_texture.cc | 216 +++++++++++------- 19 files changed, 291 insertions(+), 114 deletions(-) create mode 100644 source/blender/gpu/vulkan/render_graph/nodes/vk_clear_depth_stencil_image_node.hh diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 8da94d392a9..5891fece198 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -269,6 +269,7 @@ set(VULKAN_SRC vulkan/vk_query.hh vulkan/render_graph/nodes/vk_blit_image_node.hh vulkan/render_graph/nodes/vk_clear_color_image_node.hh + vulkan/render_graph/nodes/vk_clear_depth_stencil_image_node.hh vulkan/render_graph/nodes/vk_copy_buffer_node.hh vulkan/render_graph/nodes/vk_copy_buffer_to_image_node.hh vulkan/render_graph/nodes/vk_copy_image_node.hh diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_blit_image_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_blit_image_node.hh index 1c88c2c2c6a..f6a44fd59bb 100644 --- a/source/blender/gpu/vulkan/render_graph/nodes/vk_blit_image_node.hh +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_blit_image_node.hh @@ -56,10 +56,14 @@ class VKBlitImageNode : public VKNodeInfo { + public: + /** + * Update the node data with the data inside create_info. + * + * Has been implemented as a template to ensure all node specific data + * (`VK*Data`/`VK*CreateInfo`) types can be included in the same header file as the logic. The + * actual node data (`VKRenderGraphNode` includes all header files.) + */ + template static void set_node_data(Node &node, const CreateInfo &create_info) + { + node.clear_depth_stencil_image = create_info; + } + + /** + * Extract read/write resource dependencies from `create_info` and add them to `node_links`. + */ + void build_links(VKResourceStateTracker &resources, + VKRenderGraphNodeLinks &node_links, + const CreateInfo &create_info) override + { + ResourceWithStamp resource = resources.get_image_and_increase_stamp(create_info.vk_image); + node_links.outputs.append({resource, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + create_info.vk_image_subresource_range.aspectMask}); + } + + /** + * Build the commands and add them to the command_buffer. + */ + void build_commands(VKCommandBufferInterface &command_buffer, + const Data &data, + VKBoundPipelines & /*r_bound_pipelines*/) override + { + command_buffer.clear_depth_stencil_image(data.vk_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &data.vk_clear_depth_stencil_value, + 1, + &data.vk_image_subresource_range); + } +}; +} // namespace blender::gpu::render_graph diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_copy_buffer_to_image_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_copy_buffer_to_image_node.hh index 49441a3b721..1b21a3d0c7f 100644 --- a/source/blender/gpu/vulkan/render_graph/nodes/vk_copy_buffer_to_image_node.hh +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_copy_buffer_to_image_node.hh @@ -49,8 +49,10 @@ class VKCopyBufferToImageNode : public VKNodeInfo(synchronization); std::scoped_lock lock(resources_.mutex); diff --git a/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh b/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh index 5955eaa4856..6c32b845638 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh @@ -132,6 +132,10 @@ class VKRenderGraph : public NonCopyable { { add_node(clear_color_image); } + void add_node(const VKClearDepthStencilImageNode::CreateInfo &clear_depth_stencil_image) + { + add_node(clear_depth_stencil_image); + } void add_node(const VKFillBufferNode::CreateInfo &fill_buffer) { add_node(fill_buffer); diff --git a/source/blender/gpu/vulkan/render_graph/vk_render_graph_links.hh b/source/blender/gpu/vulkan/render_graph/vk_render_graph_links.hh index 6e7b9ec5339..58155efede9 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_render_graph_links.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_render_graph_links.hh @@ -44,7 +44,12 @@ struct VKRenderGraphLink { * When generating the commands this attribute is compared with the actual image layout of the * the image. Additional pipeline barriers will be added to transit to the layout stored here. */ - VkImageLayout vk_image_layout; + VkImageLayout vk_image_layout = VK_IMAGE_LAYOUT_UNDEFINED; + + /** + * Which aspect of the image is being used. + */ + VkImageAspectFlags vk_image_aspect = VK_IMAGE_ASPECT_NONE; }; /** diff --git a/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh b/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh index dd76995a341..6841715be18 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh @@ -10,6 +10,7 @@ #include "nodes/vk_blit_image_node.hh" #include "nodes/vk_clear_color_image_node.hh" +#include "nodes/vk_clear_depth_stencil_image_node.hh" #include "nodes/vk_copy_buffer_node.hh" #include "nodes/vk_copy_buffer_to_image_node.hh" #include "nodes/vk_copy_image_node.hh" @@ -37,6 +38,7 @@ struct VKRenderGraphNode { union { VKBlitImageNode::Data blit_image; VKClearColorImageNode::Data clear_color_image; + VKClearDepthStencilImageNode::Data clear_depth_stencil_image; VKCopyBufferNode::Data copy_buffer; VKCopyBufferToImageNode::Data copy_buffer_to_image; VKCopyImageNode::Data copy_image; @@ -92,6 +94,8 @@ struct VKRenderGraphNode { return VK_PIPELINE_STAGE_NONE; case VKNodeType::CLEAR_COLOR_IMAGE: return VKClearColorImageNode::pipeline_stage; + case VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE: + return VKClearDepthStencilImageNode::pipeline_stage; case VKNodeType::FILL_BUFFER: return VKFillBufferNode::pipeline_stage; case VKNodeType::COPY_BUFFER: @@ -133,6 +137,12 @@ struct VKRenderGraphNode { break; } + case VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE: { + VKClearDepthStencilImageNode node_info; + node_info.build_commands(command_buffer, clear_depth_stencil_image, r_bound_pipelines); + break; + } + case VKNodeType::FILL_BUFFER: { VKFillBufferNode node_info; node_info.build_commands(command_buffer, fill_buffer, r_bound_pipelines); @@ -200,6 +210,7 @@ struct VKRenderGraphNode { case VKNodeType::UNUSED: case VKNodeType::CLEAR_COLOR_IMAGE: + case VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE: case VKNodeType::FILL_BUFFER: case VKNodeType::COPY_BUFFER: case VKNodeType::COPY_IMAGE: diff --git a/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.cc b/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.cc index 2364fd06fd7..3e3a85424fd 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.cc +++ b/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.cc @@ -58,16 +58,20 @@ void VKResourceAccessInfo::build_links(VKResourceStateTracker &resources, VkAccessFlags read_access = image_access.vk_access_flags & VK_ACCESS_READ_MASK; if (read_access != VK_ACCESS_NONE) { ResourceWithStamp versioned_resource = resources.get_image(image_access.vk_image); - node_links.inputs.append( - {versioned_resource, read_access, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}); + node_links.inputs.append({versioned_resource, + read_access, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + image_access.vk_image_aspect}); } VkAccessFlags write_access = image_access.vk_access_flags & VK_ACCESS_WRITE_MASK; if (write_access != VK_ACCESS_NONE) { ResourceWithStamp versioned_resource = resources.get_image_and_increase_stamp( image_access.vk_image); - node_links.outputs.append( - {versioned_resource, write_access, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}); + node_links.outputs.append({versioned_resource, + write_access, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + image_access.vk_image_aspect}); } } } diff --git a/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.hh b/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.hh index 44dea7f48a5..493e10785df 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_resource_access_info.hh @@ -31,6 +31,7 @@ class VKRenderGraphLinks; struct VKImageAccess { VkImage vk_image; VkAccessFlags vk_access_flags; + VkImageAspectFlags vk_image_aspect; }; /** Struct describing the access to a buffer. */ diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc index 755a257b600..d6cc8dc5550 100644 --- a/source/blender/gpu/vulkan/vk_texture.cc +++ b/source/blender/gpu/vulkan/vk_texture.cc @@ -142,22 +142,29 @@ void VKTexture::generate_mipmap() void VKTexture::copy_to(VKTexture &dst_texture, VkImageAspectFlags vk_image_aspect) { + render_graph::VKCopyImageNode::CreateInfo copy_image = {}; + copy_image.src_image = vk_image_handle(); + copy_image.dst_image = dst_texture.vk_image_handle(); + copy_image.region.srcSubresource.aspectMask = vk_image_aspect; + copy_image.region.srcSubresource.mipLevel = 0; + copy_image.region.srcSubresource.layerCount = vk_layer_count(1); + copy_image.region.dstSubresource.aspectMask = vk_image_aspect; + copy_image.region.dstSubresource.mipLevel = 0; + copy_image.region.dstSubresource.layerCount = vk_layer_count(1); + copy_image.region.extent = vk_extent_3d(0); + VKContext &context = *VKContext::get(); - layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - dst_texture.layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + if (use_render_graph) { + context.render_graph.add_node(copy_image); + } + else { + layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + dst_texture.layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VkImageCopy region = {}; - region.srcSubresource.aspectMask = vk_image_aspect; - region.srcSubresource.mipLevel = 0; - region.srcSubresource.layerCount = vk_layer_count(1); - region.dstSubresource.aspectMask = vk_image_aspect; - region.dstSubresource.mipLevel = 0; - region.dstSubresource.layerCount = vk_layer_count(1); - region.extent = vk_extent_3d(0); - - VKCommandBuffers &command_buffers = context.command_buffers_get(); - command_buffers.copy(dst_texture, *this, Span(®ion, 1)); - context.flush(); + VKCommandBuffers &command_buffers = context.command_buffers_get(); + command_buffers.copy(dst_texture, *this, Span(©_image.region, 1)); + context.flush(); + } } void VKTexture::copy_to(Texture *tex) @@ -177,17 +184,28 @@ void VKTexture::clear(eGPUDataFormat format, const void *data) { BLI_assert(!is_texture_view()); - VKContext &context = *VKContext::get(); - VKCommandBuffers &command_buffers = context.command_buffers_get(); - VkClearColorValue clear_color = to_vk_clear_color_value(format, data); - VkImageSubresourceRange range = {0}; - range.aspectMask = to_vk_image_aspect_flag_bits(device_format_); - range.levelCount = VK_REMAINING_MIP_LEVELS; - range.layerCount = VK_REMAINING_ARRAY_LAYERS; - layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL); + render_graph::VKClearColorImageNode::CreateInfo clear_color_image = {}; + clear_color_image.vk_clear_color_value = to_vk_clear_color_value(format, data); + clear_color_image.vk_image = vk_image_handle(); + clear_color_image.vk_image_subresource_range.aspectMask = to_vk_image_aspect_flag_bits( + device_format_); + clear_color_image.vk_image_subresource_range.layerCount = VK_REMAINING_ARRAY_LAYERS; + clear_color_image.vk_image_subresource_range.levelCount = VK_REMAINING_MIP_LEVELS; - command_buffers.clear( - vk_image_, current_layout_get(), clear_color, Span(&range, 1)); + VKContext &context = *VKContext::get(); + + if (use_render_graph) { + context.render_graph.add_node(clear_color_image); + } + else { + layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL); + VKCommandBuffers &command_buffers = context.command_buffers_get(); + command_buffers.clear( + clear_color_image.vk_image, + current_layout_get(), + clear_color_image.vk_clear_color_value, + Span(&clear_color_image.vk_image_subresource_range, 1)); + } } void VKTexture::clear_depth_stencil(const eGPUFrameBufferBits buffers, @@ -196,21 +214,28 @@ void VKTexture::clear_depth_stencil(const eGPUFrameBufferBits buffers, { BLI_assert(buffers & (GPU_DEPTH_BIT | GPU_STENCIL_BIT)); - VKContext &context = *VKContext::get(); - VKCommandBuffers &command_buffers = context.command_buffers_get(); - VkClearDepthStencilValue clear_depth_stencil; - clear_depth_stencil.depth = clear_depth; - clear_depth_stencil.stencil = clear_stencil; - VkImageSubresourceRange range = {0}; - range.aspectMask = to_vk_image_aspect_flag_bits(buffers & (GPU_DEPTH_BIT | GPU_STENCIL_BIT)); - range.levelCount = VK_REMAINING_MIP_LEVELS; - range.layerCount = VK_REMAINING_ARRAY_LAYERS; + render_graph::VKClearDepthStencilImageNode::CreateInfo clear_depth_stencil_image = {}; + clear_depth_stencil_image.vk_image = vk_image_handle(); + clear_depth_stencil_image.vk_clear_depth_stencil_value.depth = clear_depth; + clear_depth_stencil_image.vk_clear_depth_stencil_value.stencil = clear_stencil; + clear_depth_stencil_image.vk_image_subresource_range.aspectMask = to_vk_image_aspect_flag_bits( + buffers & (GPU_DEPTH_BIT | GPU_STENCIL_BIT)); + clear_depth_stencil_image.vk_image_subresource_range.layerCount = VK_REMAINING_ARRAY_LAYERS; + clear_depth_stencil_image.vk_image_subresource_range.levelCount = VK_REMAINING_MIP_LEVELS; - layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL); - command_buffers.clear(vk_image_, - current_layout_get(), - clear_depth_stencil, - Span(&range, 1)); + VKContext &context = *VKContext::get(); + if (use_render_graph) { + context.render_graph.add_node(clear_depth_stencil_image); + } + else { + VKCommandBuffers &command_buffers = context.command_buffers_get(); + layout_ensure(context, VK_IMAGE_LAYOUT_GENERAL); + command_buffers.clear( + clear_depth_stencil_image.vk_image, + current_layout_get(), + clear_depth_stencil_image.vk_clear_depth_stencil_value, + Span(&clear_depth_stencil_image.vk_image_subresource_range, 1)); + } } void VKTexture::swizzle_set(const char swizzle_mask[4]) @@ -234,9 +259,6 @@ void VKTexture::mip_range_set(int min, int max) void VKTexture::read_sub( int mip, eGPUDataFormat format, const int region[6], const IndexRange layers, void *r_data) { - VKContext &context = *VKContext::get(); - layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - /* Vulkan images cannot be directly mapped to host memory and requires a staging buffer. */ VKBuffer staging_buffer; @@ -246,22 +268,33 @@ void VKTexture::read_sub( staging_buffer.create(device_memory_size, GPU_USAGE_DYNAMIC, VK_BUFFER_USAGE_TRANSFER_DST_BIT); - VkBufferImageCopy buffer_image_copy = {}; - buffer_image_copy.imageOffset.x = region[0]; - buffer_image_copy.imageOffset.y = region[1]; - buffer_image_copy.imageOffset.z = region[2]; - buffer_image_copy.imageExtent.width = region[3]; - buffer_image_copy.imageExtent.height = region[4]; - buffer_image_copy.imageExtent.depth = region[5]; - buffer_image_copy.imageSubresource.aspectMask = to_vk_image_aspect_single_bit( + render_graph::VKCopyImageToBufferNode::CreateInfo copy_image_to_buffer = {}; + copy_image_to_buffer.src_image = vk_image_handle(); + copy_image_to_buffer.dst_buffer = staging_buffer.vk_handle(); + copy_image_to_buffer.region.imageOffset.x = region[0]; + copy_image_to_buffer.region.imageOffset.y = region[1]; + copy_image_to_buffer.region.imageOffset.z = region[2]; + copy_image_to_buffer.region.imageExtent.width = region[3]; + copy_image_to_buffer.region.imageExtent.height = region[4]; + copy_image_to_buffer.region.imageExtent.depth = region[5]; + copy_image_to_buffer.region.imageSubresource.aspectMask = to_vk_image_aspect_single_bit( to_vk_image_aspect_flag_bits(device_format_), false); - buffer_image_copy.imageSubresource.mipLevel = mip; - buffer_image_copy.imageSubresource.baseArrayLayer = layers.start(); - buffer_image_copy.imageSubresource.layerCount = layers.size(); + copy_image_to_buffer.region.imageSubresource.mipLevel = mip; + copy_image_to_buffer.region.imageSubresource.baseArrayLayer = layers.start(); + copy_image_to_buffer.region.imageSubresource.layerCount = layers.size(); - VKCommandBuffers &command_buffers = context.command_buffers_get(); - command_buffers.copy(staging_buffer, *this, Span(&buffer_image_copy, 1)); - context.flush(); + VKContext &context = *VKContext::get(); + if (use_render_graph) { + context.render_graph.add_node(copy_image_to_buffer); + context.render_graph.submit_buffer_for_read(staging_buffer.vk_handle()); + } + else { + layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + VKCommandBuffers &command_buffers = context.command_buffers_get(); + command_buffers.copy( + staging_buffer, *this, Span(©_image_to_buffer.region, 1)); + context.flush(); + } convert_device_to_host( r_data, staging_buffer.mapped_memory_get(), sample_len, format, format_, device_format_); @@ -319,7 +352,7 @@ void VKTexture::update_sub( /* Vulkan images cannot be directly mapped to host memory and requires a staging buffer. */ VKContext &context = *VKContext::get(); int layers = vk_layer_count(1); - size_t sample_len = size_t(extent.x) * extent.y * extent.z; + size_t sample_len = size_t(extent.x) * extent.y * extent.z * layers; size_t device_memory_size = sample_len * to_bytesize(device_format_); if (is_compressed) { @@ -338,23 +371,32 @@ void VKTexture::update_sub( convert_host_to_device( staging_buffer.mapped_memory_get(), data, sample_len, format, format_, device_format_); - VkBufferImageCopy region = {}; - region.imageExtent.width = extent.x; - region.imageExtent.height = extent.y; - region.imageExtent.depth = extent.z; - region.bufferRowLength = context.state_manager_get().texture_unpack_row_length_get(); - region.imageOffset.x = offset[0]; - region.imageOffset.y = offset[1]; - region.imageOffset.z = offset[2]; - region.imageSubresource.aspectMask = to_vk_image_aspect_single_bit( + render_graph::VKCopyBufferToImageNode::CreateInfo copy_buffer_to_image = {}; + copy_buffer_to_image.src_buffer = staging_buffer.vk_handle(); + copy_buffer_to_image.dst_image = vk_image_handle(); + copy_buffer_to_image.region.imageExtent.width = extent.x; + copy_buffer_to_image.region.imageExtent.height = extent.y; + copy_buffer_to_image.region.imageExtent.depth = extent.z; + copy_buffer_to_image.region.bufferRowLength = + context.state_manager_get().texture_unpack_row_length_get(); + copy_buffer_to_image.region.imageOffset.x = offset[0]; + copy_buffer_to_image.region.imageOffset.y = offset[1]; + copy_buffer_to_image.region.imageOffset.z = offset[2]; + copy_buffer_to_image.region.imageSubresource.aspectMask = to_vk_image_aspect_single_bit( to_vk_image_aspect_flag_bits(device_format_), false); - region.imageSubresource.mipLevel = mip; - region.imageSubresource.layerCount = layers; + copy_buffer_to_image.region.imageSubresource.mipLevel = mip; + copy_buffer_to_image.region.imageSubresource.layerCount = layers; - layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VKCommandBuffers &command_buffers = context.command_buffers_get(); - command_buffers.copy(*this, staging_buffer, Span(®ion, 1)); - context.flush(); + if (use_render_graph) { + context.render_graph.add_node(copy_buffer_to_image); + } + else { + layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VKCommandBuffers &command_buffers = context.command_buffers_get(); + command_buffers.copy( + *this, staging_buffer, Span(©_buffer_to_image.region, 1)); + context.flush(); + } } void VKTexture::update_sub(int /*offset*/[3], @@ -406,22 +448,30 @@ bool VKTexture::init_internal(VertBuf *vbo) if (!allocate()) { return false; } - VKVertexBuffer *vertex_buffer = unwrap(vbo); - VkBufferImageCopy region = {}; - region.imageExtent.width = w_; - region.imageExtent.height = 1; - region.imageExtent.depth = 1; - region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(device_format_); - region.imageSubresource.mipLevel = 0; - region.imageSubresource.layerCount = 1; + render_graph::VKCopyBufferToImageNode::CreateInfo copy_buffer_to_image = {}; + copy_buffer_to_image.src_buffer = vertex_buffer->vk_handle(); + copy_buffer_to_image.dst_image = vk_image_handle(); + copy_buffer_to_image.region.imageExtent.width = w_; + copy_buffer_to_image.region.imageExtent.height = 1; + copy_buffer_to_image.region.imageExtent.depth = 1; + copy_buffer_to_image.region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits( + device_format_); + copy_buffer_to_image.region.imageSubresource.mipLevel = 0; + copy_buffer_to_image.region.imageSubresource.layerCount = 1; VKContext &context = *VKContext::get(); - layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - VKCommandBuffers &command_buffers = context.command_buffers_get(); - command_buffers.copy(*this, vertex_buffer->buffer_, Span(®ion, 1)); - context.flush(); + if (use_render_graph) { + context.render_graph.add_node(copy_buffer_to_image); + } + else { + layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VKCommandBuffers &command_buffers = context.command_buffers_get(); + command_buffers.copy( + *this, vertex_buffer->buffer_, Span(©_buffer_to_image.region, 1)); + context.flush(); + } return true; }