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
This commit is contained in:
Jeroen Bakker
2024-04-19 14:55:39 +02:00
parent c3e1f63635
commit be75f1ac2b
19 changed files with 291 additions and 114 deletions

View File

@@ -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

View File

@@ -56,10 +56,14 @@ class VKBlitImageNode : public VKNodeInfo<VKNodeType::BLIT_IMAGE,
{
ResourceWithStamp src_resource = resources.get_image(create_info.src_image);
ResourceWithStamp dst_resource = resources.get_image_and_increase_stamp(create_info.dst_image);
node_links.inputs.append(
{src_resource, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL});
node_links.outputs.append(
{dst_resource, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL});
node_links.inputs.append({src_resource,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_IMAGE_ASPECT_COLOR_BIT});
node_links.outputs.append({dst_resource,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_ASPECT_COLOR_BIT});
}
/**

View File

@@ -47,8 +47,10 @@ class VKClearColorImageNode : public VKNodeInfo<VKNodeType::CLEAR_COLOR_IMAGE,
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});
node_links.outputs.append({resource,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_ASPECT_COLOR_BIT});
}
/**

View File

@@ -0,0 +1,70 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#pragma once
#include "vk_node_info.hh"
namespace blender::gpu::render_graph {
/**
* Information stored inside the render graph node. See `VKRenderGraphNode`.
*/
struct VKClearDepthStencilImageData {
VkImage vk_image;
VkClearDepthStencilValue vk_clear_depth_stencil_value;
VkImageSubresourceRange vk_image_subresource_range;
};
class VKClearDepthStencilImageNode : public VKNodeInfo<VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE,
VKClearDepthStencilImageData,
VKClearDepthStencilImageData,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VKResourceType::IMAGE> {
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<typename Node> 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

View File

@@ -49,8 +49,10 @@ class VKCopyBufferToImageNode : public VKNodeInfo<VKNodeType::COPY_BUFFER_TO_IMA
ResourceWithStamp dst_resource = resources.get_image_and_increase_stamp(create_info.dst_image);
node_links.inputs.append(
{src_resource, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED});
node_links.outputs.append(
{dst_resource, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL});
node_links.outputs.append({dst_resource,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
create_info.region.imageSubresource.aspectMask});
}
/**

View File

@@ -51,10 +51,14 @@ class VKCopyImageNode : public VKNodeInfo<VKNodeType::COPY_IMAGE,
{
ResourceWithStamp src_resource = resources.get_image(create_info.src_image);
ResourceWithStamp dst_resource = resources.get_image_and_increase_stamp(create_info.dst_image);
node_links.inputs.append(
{src_resource, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL});
node_links.outputs.append(
{dst_resource, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL});
node_links.inputs.append({src_resource,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
create_info.region.srcSubresource.aspectMask});
node_links.outputs.append({dst_resource,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
create_info.region.dstSubresource.aspectMask});
}
/**

View File

@@ -52,8 +52,10 @@ class VKCopyImageToBufferNode : public VKNodeInfo<VKNodeType::COPY_IMAGE_TO_BUFF
ResourceWithStamp src_resource = resources.get_image(create_info.src_image);
ResourceWithStamp dst_resource = resources.get_buffer_and_increase_version(
create_info.dst_buffer);
node_links.inputs.append(
{src_resource, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL});
node_links.inputs.append({src_resource,
VK_ACCESS_TRANSFER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
create_info.region.imageSubresource.aspectMask});
node_links.outputs.append(
{dst_resource, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED});
}

View File

@@ -22,6 +22,7 @@ namespace blender::gpu::render_graph {
enum class VKNodeType {
UNUSED,
CLEAR_COLOR_IMAGE,
CLEAR_DEPTH_STENCIL_IMAGE,
FILL_BUFFER,
COPY_BUFFER,
COPY_IMAGE,

View File

@@ -23,6 +23,7 @@ struct VKSynchronizationData {};
struct VKSynchronizationCreateInfo {
VkImage vk_image;
VkImageLayout vk_image_layout;
VkImageAspectFlags vk_image_aspect;
};
class VKSynchronizationNode : public VKNodeInfo<VKNodeType::SYNCHRONIZATION,
@@ -52,8 +53,10 @@ class VKSynchronizationNode : public VKNodeInfo<VKNodeType::SYNCHRONIZATION,
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, create_info.vk_image_layout});
node_links.outputs.append({resource,
VK_ACCESS_TRANSFER_WRITE_BIT,
create_info.vk_image_layout,
create_info.vk_image_aspect});
}
/**

View File

@@ -142,9 +142,12 @@ TEST(vk_render_graph, clear_clear_copy_and_read_back)
VKCopyImageNode::CreateInfo copy_image = {};
copy_image.src_image = src_image;
copy_image.dst_image = dst_image;
copy_image.region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_image.region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VKCopyImageToBufferNode::CreateInfo copy_dst_image_to_buffer = {};
copy_dst_image_to_buffer.src_image = dst_image;
copy_dst_image_to_buffer.dst_buffer = staging_buffer;
copy_dst_image_to_buffer.region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
render_graph.add_node(clear_color_image_src);
render_graph.add_node(clear_color_image_dst);
@@ -208,9 +211,11 @@ TEST(vk_render_graph, clear_clear_copy_and_read_back)
"copy_image(src_image=0x1, src_image_layout=VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "
"dst_image=0x2, dst_image_layout=VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL" +
endl() + " - region(src_subresource=" + endl() +
" aspect_mask=, mip_level=0, base_array_layer=0, layer_count=0 , src_offset=" +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, mip_level=0, base_array_layer=0, "
"layer_count=0 , src_offset=" +
endl() + " x=0, y=0, z=0 , dst_subresource=" + endl() +
" aspect_mask=, mip_level=0, base_array_layer=0, layer_count=0 , dst_offset=" +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, mip_level=0, base_array_layer=0, "
"layer_count=0 , dst_offset=" +
endl() + " x=0, y=0, z=0 , extent=" + endl() + " width=0, height=0, depth=0 )" +
endl() + ")",
log[5]);
@@ -235,7 +240,8 @@ TEST(vk_render_graph, clear_clear_copy_and_read_back)
" - region(buffer_offset=0, buffer_row_length=0, buffer_image_height=0, "
"image_subresource=" +
endl() +
" aspect_mask=, mip_level=0, base_array_layer=0, layer_count=0 , image_offset=" +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, mip_level=0, base_array_layer=0, "
"layer_count=0 , image_offset=" +
endl() + " x=0, y=0, z=0 , image_extent=\n width=0, height=0, depth=0 )" +
endl() + ")",
log[7]);
@@ -269,6 +275,7 @@ TEST(vk_render_graph, clear_blit_copy_and_read_back)
VKCopyImageToBufferNode::CreateInfo copy_dst_image_to_buffer = {};
copy_dst_image_to_buffer.src_image = dst_image;
copy_dst_image_to_buffer.dst_buffer = staging_buffer;
copy_dst_image_to_buffer.region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
render_graph.add_node(clear_color_image_src);
VKBlitImageNode::CreateInfo blit_image = {src_image, dst_image, vk_image_blit, VK_FILTER_LINEAR};
@@ -340,7 +347,8 @@ TEST(vk_render_graph, clear_blit_copy_and_read_back)
" - region(buffer_offset=0, buffer_row_length=0, buffer_image_height=0, "
"image_subresource=" +
endl() +
" aspect_mask=, mip_level=0, base_array_layer=0, layer_count=0 , image_offset=" +
" aspect_mask=VK_IMAGE_ASPECT_COLOR_BIT, mip_level=0, base_array_layer=0, "
"layer_count=0 , image_offset=" +
endl() + " x=0, y=0, z=0 , image_extent=" + endl() +
" width=0, height=0, depth=0 )" + endl() + ")",
log[5]);

View File

@@ -263,7 +263,8 @@ void VKCommandBuilder::add_image_read_barriers(VKRenderGraph &render_graph,
wait_access,
read_access,
resource_state.image_layout,
link.vk_image_layout);
link.vk_image_layout,
link.vk_image_aspect);
resource_state.image_layout = link.vk_image_layout;
}
}
@@ -305,7 +306,8 @@ void VKCommandBuilder::add_image_write_barriers(VKRenderGraph &render_graph,
wait_access,
link.vk_access_flags,
resource_state.image_layout,
link.vk_image_layout);
link.vk_image_layout,
link.vk_image_aspect);
resource_state.image_layout = link.vk_image_layout;
}
}
@@ -315,15 +317,16 @@ void VKCommandBuilder::add_image_barrier(VkImage vk_image,
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
VkImageLayout old_layout,
VkImageLayout new_layout)
VkImageLayout new_layout,
VkImageAspectFlags aspect_mask)
{
BLI_assert(aspect_mask != VK_IMAGE_ASPECT_NONE);
vk_image_memory_barrier_.srcAccessMask = src_access_mask;
vk_image_memory_barrier_.dstAccessMask = dst_access_mask;
vk_image_memory_barrier_.image = vk_image;
vk_image_memory_barrier_.oldLayout = old_layout;
vk_image_memory_barrier_.newLayout = new_layout;
/* TODO: determine the correct aspect bits. */
vk_image_memory_barrier_.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vk_image_memory_barrier_.subresourceRange.aspectMask = aspect_mask;
vk_image_memory_barriers_.append(vk_image_memory_barrier_);
vk_image_memory_barrier_.srcAccessMask = VK_ACCESS_NONE;
vk_image_memory_barrier_.dstAccessMask = VK_ACCESS_NONE;

View File

@@ -113,7 +113,8 @@ class VKCommandBuilder {
VkAccessFlags src_access_mask,
VkAccessFlags dst_access_mask,
VkImageLayout old_image_layout,
VkImageLayout new_image_layout);
VkImageLayout new_image_layout,
VkImageAspectFlags aspect_mask);
void add_image_read_barriers(VKRenderGraph &render_graph,
NodeHandle node_handle,
VkPipelineStageFlags node_stages);

View File

@@ -44,6 +44,7 @@ void VKRenderGraph::submit_for_present(VkImage vk_swapchain_image)
VKSynchronizationNode::CreateInfo synchronization = {};
synchronization.vk_image = vk_swapchain_image;
synchronization.vk_image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
synchronization.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
add_node<VKSynchronizationNode>(synchronization);
std::scoped_lock lock(resources_.mutex);

View File

@@ -132,6 +132,10 @@ class VKRenderGraph : public NonCopyable {
{
add_node<VKClearColorImageNode>(clear_color_image);
}
void add_node(const VKClearDepthStencilImageNode::CreateInfo &clear_depth_stencil_image)
{
add_node<VKClearDepthStencilImageNode>(clear_depth_stencil_image);
}
void add_node(const VKFillBufferNode::CreateInfo &fill_buffer)
{
add_node<VKFillBufferNode>(fill_buffer);

View File

@@ -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;
};
/**

View File

@@ -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:

View File

@@ -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});
}
}
}

View File

@@ -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. */

View File

@@ -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<VkImageCopy>(&region, 1));
context.flush();
VKCommandBuffers &command_buffers = context.command_buffers_get();
command_buffers.copy(dst_texture, *this, Span<VkImageCopy>(&copy_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<VkImageSubresourceRange>(&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<VkImageSubresourceRange>(&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<VkImageSubresourceRange>(&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<VkImageSubresourceRange>(&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<VkBufferImageCopy>(&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<VkBufferImageCopy>(&copy_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<VkBufferImageCopy>(&region, 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<VkBufferImageCopy>(&copy_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<VkBufferImageCopy>(&region, 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<VkBufferImageCopy>(&copy_buffer_to_image.region, 1));
context.flush();
}
return true;
}