Files
test/source/blender/gpu/intern/gpu_vertex_buffer.cc
Hans Goudey ec33994c62 Cleanup: Remove unused VertBuf::duplicate() function
This is completely unused, not implemented for the Vulkan backend, and
seems to add quite a bit of complexity to the Metal and OpenGL backends.
It was added for EEVEE legacy motion blur, and the last use was removed
along with EEVEE legacy. We're probably better off not maintaining it since
we should avoid duplicating vertex buffer data anyway.

Pull Request: https://projects.blender.org/blender/blender/pulls/138226
2025-04-30 22:35:47 +02:00

320 lines
7.8 KiB
C++

/* SPDX-FileCopyrightText: 2016 by Mike Erwin. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*
* GPU vertex buffer
*/
#include "MEM_guardedalloc.h"
#include "gpu_backend.hh"
#include "gpu_vertex_format_private.hh"
#include "GPU_vertex_buffer.hh"
#include "gpu_context_private.hh" /* TODO: remove. */
#include <cstring>
/* -------------------------------------------------------------------- */
/** \name VertBuf
* \{ */
namespace blender::gpu {
size_t VertBuf::memory_usage = 0;
VertBuf::VertBuf()
{
/* Needed by some code check. */
format.attr_len = 0;
}
VertBuf::~VertBuf()
{
/* Should already have been cleared. */
BLI_assert(flag == GPU_VERTBUF_INVALID);
}
void VertBuf::init(const GPUVertFormat &format, GPUUsageType usage)
{
/* Strip extended usage flags. */
usage_ = usage & ~GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
#ifndef NDEBUG
/* Store extended usage. */
extended_usage_ = usage;
#endif
flag = GPU_VERTBUF_DATA_DIRTY;
GPU_vertformat_copy(&this->format, format);
/* Avoid packing vertex formats which are used for texture buffers.
* These cases use singular types and do not need packing. They must
* also not have increased alignment padding to the minimum per-vertex stride. */
if (usage & GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY) {
VertexFormat_texture_buffer_pack(&this->format);
}
if (!this->format.packed) {
VertexFormat_pack(&this->format);
}
flag |= GPU_VERTBUF_INIT;
}
void VertBuf::clear()
{
this->release_data();
flag = GPU_VERTBUF_INVALID;
}
void VertBuf::allocate(uint vert_len)
{
BLI_assert(format.packed);
/* Catch any unnecessary usage. */
BLI_assert(vertex_alloc != vert_len || data_ == nullptr);
vertex_len = vertex_alloc = vert_len;
this->acquire_data();
flag |= GPU_VERTBUF_DATA_DIRTY;
}
void VertBuf::resize(uint vert_len)
{
/* Catch any unnecessary usage. */
BLI_assert(vertex_alloc != vert_len);
vertex_len = vertex_alloc = vert_len;
this->resize_data();
flag |= GPU_VERTBUF_DATA_DIRTY;
}
void VertBuf::upload()
{
this->upload_data();
}
} // namespace blender::gpu
/** \} */
/* -------------------------------------------------------------------- */
/** \name C-API
* \{ */
using namespace blender;
using namespace blender::gpu;
/* -------- Creation & deletion -------- */
VertBuf *GPU_vertbuf_calloc()
{
return GPUBackend::get()->vertbuf_alloc();
}
VertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat &format, GPUUsageType usage)
{
VertBuf *verts = GPU_vertbuf_calloc();
verts->init(format, usage);
return verts;
}
void GPU_vertbuf_init_with_format_ex(VertBuf &verts,
const GPUVertFormat &format,
GPUUsageType usage)
{
verts.init(format, usage);
}
void GPU_vertbuf_init_build_on_device(VertBuf &verts, const GPUVertFormat &format, uint v_len)
{
GPU_vertbuf_init_with_format_ex(verts, format, GPU_USAGE_DEVICE_ONLY);
GPU_vertbuf_data_alloc(verts, v_len);
}
VertBuf *GPU_vertbuf_create_on_device(const GPUVertFormat &format, uint v_len)
{
VertBuf *verts = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DEVICE_ONLY);
GPU_vertbuf_data_alloc(*verts, v_len);
return verts;
}
void GPU_vertbuf_read(const VertBuf *verts, void *data)
{
verts->read(data);
}
void GPU_vertbuf_clear(VertBuf *verts)
{
verts->clear();
}
void GPU_vertbuf_discard(VertBuf *verts)
{
verts->clear();
verts->reference_remove();
}
void GPU_vertbuf_handle_ref_add(VertBuf *verts)
{
verts->reference_add();
}
void GPU_vertbuf_handle_ref_remove(VertBuf *verts)
{
verts->reference_remove();
}
/* -------- Data update -------- */
void GPU_vertbuf_data_alloc(VertBuf &verts, uint v_len)
{
verts.allocate(v_len);
}
void GPU_vertbuf_data_resize(VertBuf &verts, uint v_len)
{
verts.resize(v_len);
}
void GPU_vertbuf_data_len_set(VertBuf &verts, uint v_len)
{
BLI_assert(verts.data<uchar>().data() != nullptr); /* Only for dynamic data. */
BLI_assert(v_len <= verts.vertex_alloc);
verts.vertex_len = v_len;
}
void GPU_vertbuf_attr_set(VertBuf *verts, uint a_idx, uint v_idx, const void *data)
{
BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY);
const GPUVertFormat *format = &verts->format;
const GPUVertAttr *a = &format->attrs[a_idx];
BLI_assert(v_idx < verts->vertex_alloc);
BLI_assert(a_idx < format->attr_len);
BLI_assert(verts->data<uchar>().data() != nullptr);
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
memcpy(verts->data<uchar>().data() + a->offset + v_idx * format->stride, data, a->size);
}
void GPU_vertbuf_attr_fill(VertBuf *verts, uint a_idx, const void *data)
{
const GPUVertFormat *format = &verts->format;
BLI_assert(a_idx < format->attr_len);
const GPUVertAttr *a = &format->attrs[a_idx];
const uint stride = a->size; /* tightly packed input data */
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
GPU_vertbuf_attr_fill_stride(verts, a_idx, stride, data);
}
void GPU_vertbuf_vert_set(VertBuf *verts, uint v_idx, const void *data)
{
BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY);
const GPUVertFormat *format = &verts->format;
BLI_assert(v_idx < verts->vertex_alloc);
BLI_assert(verts->data<uchar>().data() != nullptr);
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
memcpy(verts->data<uchar>().data() + v_idx * format->stride, data, format->stride);
}
void GPU_vertbuf_attr_fill_stride(VertBuf *verts, uint a_idx, uint stride, const void *data)
{
BLI_assert(verts->get_usage_type() != GPU_USAGE_DEVICE_ONLY);
const GPUVertFormat *format = &verts->format;
const GPUVertAttr *a = &format->attrs[a_idx];
BLI_assert(a_idx < format->attr_len);
BLI_assert(verts->data<uchar>().data() != nullptr);
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
const uint vertex_len = verts->vertex_len;
if (format->attr_len == 1 && stride == format->stride) {
/* we can copy it all at once */
memcpy(verts->data<uchar>().data(), data, vertex_len * a->size);
}
else {
/* we must copy it per vertex */
for (uint v = 0; v < vertex_len; v++) {
memcpy(verts->data<uchar>().data() + a->offset + v * format->stride,
(const uchar *)data + v * stride,
a->size);
}
}
}
void GPU_vertbuf_attr_get_raw_data(VertBuf *verts, uint a_idx, GPUVertBufRaw *access)
{
const GPUVertFormat *format = &verts->format;
const GPUVertAttr *a = &format->attrs[a_idx];
BLI_assert(a_idx < format->attr_len);
BLI_assert(verts->data<uchar>().data() != nullptr);
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
verts->flag &= ~GPU_VERTBUF_DATA_UPLOADED;
access->size = a->size;
access->stride = format->stride;
access->data = (uchar *)verts->data<uchar>().data() + a->offset;
access->data_init = access->data;
#ifndef NDEBUG
access->_data_end = access->data_init + size_t(verts->vertex_alloc * format->stride);
#endif
}
/* -------- Getters -------- */
const GPUVertFormat *GPU_vertbuf_get_format(const VertBuf *verts)
{
return &verts->format;
}
uint GPU_vertbuf_get_vertex_alloc(const VertBuf *verts)
{
return verts->vertex_alloc;
}
uint GPU_vertbuf_get_vertex_len(const VertBuf *verts)
{
return verts->vertex_len;
}
GPUVertBufStatus GPU_vertbuf_get_status(const VertBuf *verts)
{
return verts->flag;
}
void GPU_vertbuf_tag_dirty(VertBuf *verts)
{
verts->flag |= GPU_VERTBUF_DATA_DIRTY;
}
uint GPU_vertbuf_get_memory_usage()
{
return VertBuf::memory_usage;
}
void GPU_vertbuf_use(VertBuf *verts)
{
verts->upload();
}
void GPU_vertbuf_wrap_handle(VertBuf *verts, uint64_t handle)
{
verts->wrap_handle(handle);
}
void GPU_vertbuf_bind_as_ssbo(VertBuf *verts, int binding)
{
verts->bind_as_ssbo(binding);
}
void GPU_vertbuf_bind_as_texture(VertBuf *verts, int binding)
{
verts->bind_as_texture(binding);
}
void GPU_vertbuf_update_sub(VertBuf *verts, uint start, uint len, const void *data)
{
verts->update_sub(start, len, data);
}
/** \} */