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:
@@ -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
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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>(®ion, 1));
|
||||
context.flush();
|
||||
VKCommandBuffers &command_buffers = context.command_buffers_get();
|
||||
command_buffers.copy(dst_texture, *this, Span<VkImageCopy>(©_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>(©_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>(®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<VkBufferImageCopy>(©_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>(®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<VkBufferImageCopy>(©_buffer_to_image.region, 1));
|
||||
context.flush();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user