Vulkan: Fix incorrect layout transition

When many text using BLF the glymp texture could be re-written.
In this case the new upload should be done in a separate render
graph node group. This wasn't the case and resulted in
validation warnings about the glyph texture being in an layout
that wasn't expected.

This PR simplifies the group extraction a bit by looking ahead
when the group ends.

Pull Request: https://projects.blender.org/blender/blender/pulls/123547
This commit is contained in:
Jeroen Bakker 2024-06-21 13:26:52 +02:00
parent bcc42a72aa
commit dbd04310c7
2 changed files with 28 additions and 30 deletions

@ -57,22 +57,25 @@ void VKCommandBuilder::build_nodes(VKRenderGraph &render_graph,
command_buffer.begin_recording();
state_.debug_level = 0;
state_.active_debug_group_id = -1;
int64_t node_group_start = 0;
bool is_rendering = false;
std::optional<NodeHandle> rendering_scope;
for (int64_t node_index : nodes.index_range()) {
NodeHandle node_handle = nodes[node_index];
IndexRange nodes_range = nodes.index_range();
while (!nodes_range.is_empty()) {
IndexRange node_group = nodes_range.slice(0, 1);
NodeHandle node_handle = nodes[nodes_range.first()];
VKRenderGraphNode &node = render_graph.nodes_[node_handle];
int64_t node_group_end = node_index;
if (node.type == VKNodeType::END_RENDERING || !node_type_is_rendering(node.type)) {
build_node_group(render_graph,
command_buffer,
nodes.slice(node_group_start, (node_group_end - node_group_start) + 1),
rendering_scope,
is_rendering);
node_group_start = node_index + 1;
while (node_type_is_rendering(node.type) && node_group.size() < nodes_range.size()) {
NodeHandle node_handle = nodes[nodes_range[node_group.size()]];
VKRenderGraphNode &node = render_graph.nodes_[node_handle];
if (!node_type_is_rendering(node.type) || node.type == VKNodeType::BEGIN_RENDERING) {
break;
}
node_group = nodes_range.slice(0, node_group.size() + 1);
}
build_node_group(render_graph, command_buffer, nodes.slice(node_group), rendering_scope);
nodes_range = nodes_range.drop_front(node_group.size());
}
finish_debug_groups(command_buffer);
state_.debug_level = 0;
@ -82,9 +85,9 @@ void VKCommandBuilder::build_nodes(VKRenderGraph &render_graph,
void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
VKCommandBufferInterface &command_buffer,
Span<NodeHandle> node_group,
std::optional<NodeHandle> &r_rendering_scope,
bool &r_is_rendering)
std::optional<NodeHandle> &r_rendering_scope)
{
bool is_rendering = false;
for (NodeHandle node_handle : node_group) {
VKRenderGraphNode &node = render_graph.nodes_[node_handle];
build_pipeline_barriers(render_graph, command_buffer, node_handle, node.pipeline_stage_get());
@ -94,9 +97,9 @@ void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
VKRenderGraphNode &node = render_graph.nodes_[node_handle];
if (node.type == VKNodeType::BEGIN_RENDERING) {
BLI_assert(!r_rendering_scope.has_value());
BLI_assert(!r_is_rendering);
BLI_assert(!is_rendering);
r_rendering_scope = node_handle;
r_is_rendering = true;
is_rendering = true;
/* Check of the node_group spans a full rendering scope. In that case we don't need to set
* the VK_RENDERING_SUSPENDING_BIT. */
@ -110,25 +113,16 @@ void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
else if (node.type == VKNodeType::END_RENDERING) {
BLI_assert(r_rendering_scope.has_value());
r_rendering_scope.reset();
r_is_rendering = false;
is_rendering = false;
}
else if (node_type_is_within_rendering(node.type)) {
BLI_assert(r_rendering_scope.has_value());
if (!r_is_rendering) {
if (!is_rendering) {
// Resuming paused rendering scope.
VKRenderGraphNode &rendering_node = render_graph.nodes_[*r_rendering_scope];
rendering_node.begin_rendering.vk_rendering_info.flags = VK_RENDERING_RESUMING_BIT;
rendering_node.build_commands(command_buffer, state_.active_pipelines);
r_is_rendering = true;
}
}
else {
// Dispatch or data transfer command that cannot be done before rendering. We have to pause
// rendering
if (r_is_rendering) {
// Pause rendering.
r_is_rendering = false;
command_buffer.end_rendering();
is_rendering = true;
}
}
@ -138,6 +132,11 @@ void VKCommandBuilder::build_node_group(VKRenderGraph &render_graph,
}
node.build_commands(command_buffer, state_.active_pipelines);
}
if (is_rendering) {
/* Suspend rendering as the next node group will contain data transfer/dispatch commands. */
is_rendering = false;
command_buffer.end_rendering();
}
}
void VKCommandBuilder::activate_debug_group(VKRenderGraph &render_graph,

@ -89,8 +89,7 @@ class VKCommandBuilder {
void build_node_group(VKRenderGraph &render_graph,
VKCommandBufferInterface &command_buffer,
Span<NodeHandle> node_group,
std::optional<NodeHandle> &r_rendering_scope,
bool &r_is_rendering);
std::optional<NodeHandle> &r_rendering_scope);
/**
* Build the pipeline barriers that should be recorded before any other commands of the node