Files
test2/source/blender/gpu/vulkan/vk_streaming_buffer.cc
Jeroen Bakker af0d98bf1d Fix #147254: Vulkan: Text Rendering artifacts
b2eaf812b1 made sure that the min offset alignment for text rendering
was used to calculate the correct offset. However the change didn't
update the region to be uploaded to the GPU. The artifacts are caused by
reading from allocated, but uninitialized memory.

This PR fixes this by calculating the correct region to copy to the GPU.
The artifact didn't appear on AMD/NVIDIA GPUs as their alignment are
4 bytes. Intel GPU is 64 bytes.

Pull Request: https://projects.blender.org/blender/blender/pulls/147265
2025-10-03 10:34:49 +02:00

71 lines
2.4 KiB
C++

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "vk_streaming_buffer.hh"
#include "vk_buffer.hh"
#include "vk_context.hh"
namespace blender::gpu {
VKStreamingBuffer::VKStreamingBuffer(VKBuffer &buffer, VkDeviceSize min_offset_alignment)
: min_offset_alignment_(min_offset_alignment),
vk_buffer_dst_(buffer.vk_handle()),
vk_buffer_size_(buffer.size_in_bytes())
{
}
VKStreamingBuffer::~VKStreamingBuffer()
{
vk_buffer_dst_ = VK_NULL_HANDLE;
}
VkDeviceSize VKStreamingBuffer::update(VKContext &context, const void *data, size_t data_size)
{
render_graph::VKRenderGraph &render_graph = context.render_graph();
const bool allocate_new_buffer = !(host_buffer_.has_value() &&
data_size <
host_buffer_.value().get()->size_in_bytes() - offset_);
if (allocate_new_buffer) {
host_buffer_.emplace(std::make_unique<VKBuffer>());
VKBuffer &host_buffer = *host_buffer_.value().get();
host_buffer.create(vk_buffer_size_,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VMA_ALLOCATION_CREATE_MAPPED_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
0.4f);
offset_ = 0;
render_graph::VKCopyBufferNode::CreateInfo copy_buffer = {
host_buffer.vk_handle(), vk_buffer_dst(), {0, 0, 0}};
copy_buffer_handle_ = render_graph.add_node(copy_buffer);
}
VKBuffer &host_buffer = *host_buffer_.value().get();
VkDeviceSize start_offset = offset_;
/* Advance the offset to the next possible offset considering the minimum allowed offset
* alignment. */
offset_ += data_size;
if (min_offset_alignment_ > 1) {
offset_ = ceil_to_multiple_ul(offset_, min_offset_alignment_);
}
memcpy(
static_cast<void *>(static_cast<uint8_t *>(host_buffer.mapped_memory_get()) + start_offset),
data,
data_size);
/* Increace the region size to copy to include the min offset alignment. */
render_graph::VKCopyBufferNode::Data &copy_buffer_data = render_graph.get_node_data(
copy_buffer_handle_);
copy_buffer_data.region.size += offset_ - start_offset;
return start_offset;
}
} // namespace blender::gpu