27 this->free_optimized_buffer();
31 ssbo_wrapper_ =
nullptr;
35void MTLIndexBuf::free_optimized_buffer()
38 optimized_ibo_->
free();
39 optimized_ibo_ =
nullptr;
48 this->free_optimized_buffer();
57 if (ssbo_wrapper_ ==
nullptr) {
62 ssbo_wrapper_->bind(binding);
67 if (ibo_ !=
nullptr) {
73 id<MTLBuffer> source_buffer = ibo_->get_metal_buffer();
74 if (source_buffer.storageMode == MTLStorageModeManaged) {
76 [enc synchronizeResource:source_buffer];
83 void *host_ptr = ibo_->get_host_ptr();
87 BLI_assert(
false &&
"Index buffer not ready to be read.");
99 "Cannot use sub-range on stripped point buffer.");
104 if (alloc_size_ != mtlsrc->alloc_size_ || ibo_ != mtlsrc->ibo_) {
107 alloc_size_ = mtlsrc->alloc_size_;
111 this->free_optimized_buffer();
117 if ((ibo_ !=
nullptr) && (this->
data_ !=
nullptr)) {
118 MTL_LOG_DEBUG(
"Re-creating index buffer with new data. IndexBuf %p",
this);
124 if (ibo_ ==
nullptr) {
126 if (alloc_size_ == 0) {
127 MTL_LOG_WARNING(
"Warning! Trying to allocate index buffer with size=0 bytes");
132 alloc_size_,
true,
data_);
138 ibo_->set_label(
@"Index Buffer");
153 if (
data_ !=
nullptr) {
164 void *modified_base_ptr =
data_;
165 uint8_t *
ptr =
static_cast<uint8_t *
>(modified_base_ptr);
167 modified_base_ptr =
static_cast<void *
>(
ptr);
170 memcpy(modified_base_ptr,
data,
len);
186 id<MTLBuffer> dest_buffer = ibo_->get_metal_buffer();
193 destinationOffset:start
198 if (dest_buffer.storageMode == MTLStorageModeManaged) {
199 [enc synchronizeResource:dest_buffer];
203 this->free_optimized_buffer();
214 can_optimize_ = can_optimize;
222 "Index buffer optimization disabled, but optimal buffer already generated.");
238 uint32_t input_index_len)
241 uint32_t current_vert_len = 0;
242 uint32_t current_output_ind = 0;
245 for (
int c_index = 0; c_index < input_index_len; c_index++) {
246 T current_index = original_data[c_index];
247 if (current_index ==
T(-1)) {
249 current_vert_len = 0;
252 if (current_vert_len < 3) {
255 indices[current_vert_len] = current_index;
259 if (current_vert_len == 3) {
261 output_data[current_output_ind++] =
indices[0];
262 output_data[current_output_ind++] =
indices[1];
263 output_data[current_output_ind++] =
indices[2];
265 else if (current_vert_len > 3) {
269 uint32_t tri_id = current_vert_len - 3;
270 uint32_t base_output_ind = current_output_ind;
271 if ((tri_id % 2) == 0) {
272 output_data[base_output_ind + 0] = output_data[base_output_ind - 2];
273 output_data[base_output_ind + 1] = current_index;
274 output_data[base_output_ind + 2] = output_data[base_output_ind - 1];
277 output_data[base_output_ind + 0] = output_data[base_output_ind - 1];
278 output_data[base_output_ind + 1] = output_data[base_output_ind - 2];
279 output_data[base_output_ind + 2] = current_index;
281 current_output_ind += 3;
288 return current_output_ind;
295 uint32_t input_index_len)
298 T base_prim_ind_val = 0;
299 uint32_t current_vert_len = 0;
300 uint32_t current_output_ind = 0;
303 for (
int c_index = 0; c_index < input_index_len; c_index++) {
304 T current_index = original_data[c_index];
305 if (current_index ==
T(-1)) {
307 current_vert_len = 0;
310 if (current_vert_len < 3) {
313 indices[current_vert_len] = current_index;
317 if (current_vert_len == 3) {
319 output_data[current_output_ind++] =
indices[0];
320 output_data[current_output_ind++] =
indices[1];
321 output_data[current_output_ind++] =
indices[2];
322 base_prim_ind_val =
indices[0];
324 else if (current_vert_len > 3) {
328 uint32_t base_output_ind = current_output_ind;
330 output_data[base_output_ind + 0] = base_prim_ind_val;
331 output_data[base_output_ind + 1] = output_data[base_output_ind - 1];
332 output_data[base_output_ind + 2] = current_index;
333 current_output_ind += 3;
340 return current_output_ind;
344 uint32_t &in_out_v_count)
349 bool should_optimize_or_emulate = (in_out_primitive_type ==
GPU_PRIM_TRI_FAN) ||
351 if (!should_optimize_or_emulate ||
is_subrange_ || !can_optimize_) {
356 BLI_assert(this->ibo_ && this->ibo_->get_metal_buffer());
357 return this->ibo_->get_metal_buffer();
361 GPUPrimType input_prim_type = in_out_primitive_type;
363 if (!ibo_ && optimized_ibo_ ==
nullptr) {
369 if (optimized_ibo_ !=
nullptr && optimized_primitive_type_ != input_prim_type) {
371 "Cannot change the optimized primitive format after generation, as source "
372 "index buffer data is discarded.");
377 if (optimized_ibo_ ==
nullptr) {
380 switch (input_prim_type) {
384 uint32_t max_possible_verts = (this->
index_len_ - 2) * 3;
395 Span<uint16_t> orig_data(
static_cast<const uint16_t *
>(ibo_->get_host_ptr()),
398 static_cast<uint16_t *
>(optimized_ibo_->get_host_ptr()), max_possible_verts);
403 Span<uint32_t> orig_data(
static_cast<const uint32_t *
>(ibo_->get_host_ptr()),
406 static_cast<uint32_t *
>(optimized_ibo_->get_host_ptr()), max_possible_verts);
411 BLI_assert(emulated_v_count <= max_possible_verts);
414 optimized_ibo_->flush();
415 optimized_primitive_type_ = input_prim_type;
416 in_out_v_count = emulated_v_count;
423 uint32_t max_possible_verts = (this->
index_len_ - 2) * 3;
434 Span<uint16_t> orig_data(
static_cast<const uint16_t *
>(ibo_->get_host_ptr()),
437 static_cast<uint16_t *
>(optimized_ibo_->get_host_ptr()), max_possible_verts);
442 Span<uint32_t> orig_data(
static_cast<const uint32_t *
>(ibo_->get_host_ptr()),
445 static_cast<uint32_t *
>(optimized_ibo_->get_host_ptr()), max_possible_verts);
450 BLI_assert(emulated_v_count <= max_possible_verts);
453 optimized_ibo_->flush();
454 optimized_primitive_type_ = input_prim_type;
455 in_out_v_count = emulated_v_count;
463 MTL_LOG_DEBUG(
"TODO: Primitive topology: Optimize line strip topology types");
471 "TODO: Primitive topology: Line Loop Index buffer optimization required for "
491 if (optimized_ibo_ !=
nullptr) {
494 if (ibo_ !=
nullptr) {
500 in_out_v_count = emulated_v_count;
502 return optimized_ibo_->get_metal_buffer();
507void MTLIndexBuf::strip_restart_indices()
519 if (uint_idx[
i] == 0xFFFFFFFFu) {
525 if (uint_idx[j] == 0xFFFFFFFFu) {
541 if (swap_index == -1) {
548 uint32_t swap_index_value = uint_idx[swap_index];
549 uint_idx[
i] = swap_index_value;
550 uint_idx[swap_index] = 0xFFFFFFFFu;
560 point_restarts_stripped_ =
true;
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
MINLINE uint ceil_to_multiple_u(uint a, uint b)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
GPUIndexBufType index_type_
gpu::MTLBuffer * allocate_with_data(uint64_t size, bool cpu_visible, const void *data=nullptr)
gpu::MTLBuffer * allocate(uint64_t size, bool cpu_visible)
id< MTLBlitCommandEncoder > ensure_begin_blit_encoder()
static MTLContext * get()
MTLCommandBufferManager main_command_buffer
MTLScratchBufferManager & get_scratchbuffer_manager()
static MTLBufferPool * get_global_memory_manager()
void upload_data() override
void read(uint32_t *data) const override
friend class MTLStorageBuf
id< MTLBuffer > get_index_buffer(GPUPrimType &in_out_primitive_type, uint &in_out_v_count)
void bind_as_ssbo(uint32_t binding) override
void update_sub(uint32_t start, uint32_t len, const void *data) override
void flag_can_optimize(bool can_optimize)
MTLTemporaryBuffer scratch_buffer_allocate_range(uint64_t alloc_size)
#define MTL_LOG_WARNING(info,...)
#define MTL_LOG_DEBUG(info,...)
static uint32_t populate_emulated_tri_fan_buf(Span< T > original_data, MutableSpan< T > output_data, uint32_t input_index_len)
static uint32_t populate_optimized_tri_strip_buf(Span< T > original_data, MutableSpan< T > output_data, uint32_t input_index_len)
MTLBufferRange MTLTemporaryBuffer
id< MTLBuffer > metal_buffer