diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc index 2dbfaadc1ec..717ae294cf5 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc @@ -23,14 +23,7 @@ static void extract_tris_mesh(const MeshRenderData &mr, const Span corner_tris = mr.mesh->corner_tris(); if (!face_sorted.face_tri_offsets) { /* There are no hidden faces and no reordering is necessary to group triangles with the same - * material. The corner indices from #Mesh::corner_tris() can be copied directly to the GPU - * without the usual CPU-side copy owned by the index buffer. Crucially, this assumes that the - * data is uploaded to the GPU *before* the dependency graph's evaluated state is cleared (and - * with it, the evaluated mesh's triangulation data). - * - * Eventually these local copies should be completely removed, and code should write directly - * to GPU memory, but even then it could be helpful to know that the data already exists - * contiguously, owned elsewhere by Blender. */ + * material. The corner indices from #Mesh::corner_tris() can be copied directly to the GPU. */ BLI_assert(face_sorted.visible_tris_num == corner_tris.size()); GPU_indexbuf_build_in_place_from_memory(&ibo, GPU_PRIM_TRIS, diff --git a/source/blender/gpu/GPU_index_buffer.hh b/source/blender/gpu/GPU_index_buffer.hh index d0575753fda..aa9f1bf6a10 100644 --- a/source/blender/gpu/GPU_index_buffer.hh +++ b/source/blender/gpu/GPU_index_buffer.hh @@ -53,8 +53,6 @@ class IndexBuf { bool is_subrange_ = false; /** True if buffer only contains restart indices. */ bool is_empty_ = false; - /** #data_ is read-only, not owned by an index buffer. */ - bool reference_data_ = false; union { /** Mapped buffer data. non-NULL indicates not yet sent to VRAM. */ @@ -72,8 +70,7 @@ class IndexBuf { uint min_index, uint max_index, GPUPrimType prim_type, - bool uses_restart_indices, - bool reference_data); + bool uses_restart_indices); void init_subrange(IndexBuf *elem_src, uint start, uint length); void init_build_on_device(uint index_len); diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc index 4b77857672e..fdd3ae5db85 100644 --- a/source/blender/gpu/intern/gpu_index_buffer.cc +++ b/source/blender/gpu/intern/gpu_index_buffer.cc @@ -315,15 +315,13 @@ void IndexBuf::init(uint indices_len, uint min_index, uint max_index, GPUPrimType prim_type, - bool uses_restart_indices, - bool reference_data) + bool uses_restart_indices) { is_init_ = true; data_ = indices; index_start_ = 0; index_len_ = indices_len; is_empty_ = min_index > max_index; - reference_data_ = reference_data; /* Patch index buffer to remove restart indices from * non-restart-compatible primitive types. Restart indices @@ -494,8 +492,7 @@ void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, IndexBuf *elem) builder->index_min, builder->index_max, builder->prim_type, - builder->uses_restart_indices, - false); + builder->uses_restart_indices); builder->data = nullptr; } @@ -513,8 +510,7 @@ void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder, index_min, index_max, builder->prim_type, - uses_restart_indices, - false); + uses_restart_indices); builder->data = nullptr; } @@ -526,16 +522,15 @@ void GPU_indexbuf_build_in_place_from_memory(IndexBuf *ibo, const int32_t index_max, const bool uses_restart_indices) { - /* If restart indices are used, they need to be stripped on Metal which would require a copy. */ - BLI_assert(!uses_restart_indices); const uint32_t indices_num = data_len * indices_per_primitive(prim_type); - ibo->init(indices_num, - const_cast(data), - index_min, - index_max, - prim_type, - uses_restart_indices, - true); + /* TODO: The need for this copy is meant to be temporary. The data should be uploaded directly to + * the GPU here rather than copied to an array owned by the IBO first. */ + uint32_t *copy = static_cast( + MEM_malloc_arrayN(indices_num, sizeof(uint32_t), __func__)); + threading::memory_bandwidth_bound_task(sizeof(uint32_t) * indices_num * 2, [&]() { + array_utils::copy(Span(data, indices_num), MutableSpan(copy, indices_num)); + }); + ibo->init(indices_num, copy, index_min, index_max, prim_type, uses_restart_indices); } void GPU_indexbuf_create_subrange_in_place(IndexBuf *elem, diff --git a/source/blender/gpu/metal/mtl_index_buffer.mm b/source/blender/gpu/metal/mtl_index_buffer.mm index 08bb08b2634..99febea9036 100644 --- a/source/blender/gpu/metal/mtl_index_buffer.mm +++ b/source/blender/gpu/metal/mtl_index_buffer.mm @@ -139,10 +139,7 @@ void MTLIndexBuf::upload_data() } /* No need to keep copy of data_ in system memory. */ - if (reference_data_) { - data_ = nullptr; - } - else { + if (data_) { MEM_SAFE_FREE(data_); } } diff --git a/source/blender/gpu/opengl/gl_index_buffer.cc b/source/blender/gpu/opengl/gl_index_buffer.cc index 318f90bb871..b069bdfa0e6 100644 --- a/source/blender/gpu/opengl/gl_index_buffer.cc +++ b/source/blender/gpu/opengl/gl_index_buffer.cc @@ -36,12 +36,7 @@ void GLIndexBuf::bind() /* Sends data to GPU. */ glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data_, GL_STATIC_DRAW); /* No need to keep copy of data in system memory. */ - if (reference_data_) { - data_ = nullptr; - } - else { - MEM_SAFE_FREE(data_); - } + MEM_SAFE_FREE(data_); } } diff --git a/source/blender/gpu/vulkan/vk_index_buffer.cc b/source/blender/gpu/vulkan/vk_index_buffer.cc index b2657f275a2..83a2aa88a44 100644 --- a/source/blender/gpu/vulkan/vk_index_buffer.cc +++ b/source/blender/gpu/vulkan/vk_index_buffer.cc @@ -33,12 +33,7 @@ void VKIndexBuffer::ensure_updated() VKStagingBuffer staging_buffer(buffer_, VKStagingBuffer::Direction::HostToDevice); staging_buffer.host_buffer_get().update(data_); staging_buffer.copy_to_device(context); - if (reference_data_) { - data_ = nullptr; - } - else { - MEM_SAFE_FREE(data_); - } + MEM_SAFE_FREE(data_); } void VKIndexBuffer::upload_data()