Files
test2/source/blender/gpu/vulkan/vk_drawlist.cc
Jeroen Bakker 958ec9f37f Vulkan: Use Generic Buffer to Store DrawList Commands
Previously a storage buffer was used to store draw list commands as it
matches already existing APIs. Unfortunately StorageBuffers prefers to
be stored on the GPU device and would reduce the benefit of a dynamic
draw list.

This PR replaces the storage buffer with a regular buffer, which keeps
more control where to store the buffer.

Pull Request: https://projects.blender.org/blender/blender/pulls/117712
2024-02-01 10:03:47 +01:00

92 lines
2.6 KiB
C++

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "GPU_batch.h"
#include "vk_batch.hh"
#include "vk_common.hh"
#include "vk_drawlist.hh"
#include "vk_index_buffer.hh"
#include "vk_vertex_buffer.hh"
namespace blender::gpu {
VKDrawList::VKDrawList(int list_length) : length_(list_length)
{
command_buffer_.create(list_length * sizeof(VkDrawIndexedIndirectCommand),
GPU_USAGE_DYNAMIC,
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
true);
}
void VKDrawList::append(GPUBatch *gpu_batch, int instance_first, int instance_count)
{
/* Check for different batch. When batch is different the previous commands should be flushed to
* the gpu. */
VKBatch *batch = unwrap(gpu_batch);
if (batch_ != batch) {
submit();
batch_ = batch;
}
/* Record the new command */
const VKIndexBuffer *index_buffer = batch_->index_buffer_get();
const bool is_indexed = index_buffer != nullptr;
if (is_indexed) {
VkDrawIndexedIndirectCommand &command = get_command<VkDrawIndexedIndirectCommand>();
command.firstIndex = index_buffer->index_base_get();
command.vertexOffset = index_buffer->index_start_get();
command.indexCount = index_buffer->index_len_get();
command.firstInstance = instance_first;
command.instanceCount = instance_count;
}
else {
const VKVertexBuffer *vertex_buffer = batch_->vertex_buffer_get(0);
if (vertex_buffer == nullptr) {
batch_ = nullptr;
return;
}
VkDrawIndirectCommand &command = get_command<VkDrawIndirectCommand>();
command.vertexCount = vertex_buffer->vertex_len;
command.instanceCount = instance_count;
command.firstVertex = 0;
command.firstInstance = instance_first;
}
command_index_++;
/* Submit commands when command buffer is full. */
if (command_index_ == length_) {
submit();
}
}
void VKDrawList::submit()
{
if (batch_ == nullptr || command_index_ == 0) {
command_index_ = 0;
batch_ = nullptr;
return;
}
if (command_index_ > 1) {
printf("%s: %d\n", __func__, command_index_);
}
const VKIndexBuffer *index_buffer = batch_->index_buffer_get();
const bool is_indexed = index_buffer != nullptr;
command_buffer_.flush();
batch_->multi_draw_indirect(command_buffer_.vk_handle(),
command_index_,
0,
is_indexed ? sizeof(VkDrawIndexedIndirectCommand) :
sizeof(VkDrawIndirectCommand));
command_index_ = 0;
batch_ = nullptr;
}
} // namespace blender::gpu