diff --git a/cpp/render/render_opengles.cpp b/cpp/render/render_opengles.cpp index 55d2270..6a36b29 100644 --- a/cpp/render/render_opengles.cpp +++ b/cpp/render/render_opengles.cpp @@ -837,6 +837,32 @@ static void rk_pack_batch( batch.state = RK_BATCH_STATE_PACKED; } +static bool rk_compare_replace( + void * __restrict _dst, + void const * __restrict _src, + unsigned const size) { + rk_ulong hash = 0; + rk_ulong * dst = reinterpret_cast(_dst); + rk_ulong const * src = reinterpret_cast(_src); + unsigned count = size / sizeof(rk_ulong); + unsigned remain = (size - count * sizeof(rk_ulong)); + if (count) { + do { + hash |= *dst ^ *src; + *dst++ = *src++; + } while(--count > 0); + } + rk_ubyte * rdst = reinterpret_cast(dst); + rk_ubyte const * rsrc = reinterpret_cast(src); + if (remain) { + do { + hash |= *rdst ^ *rsrc; + *rdst++ = *rsrc++; + } while(--remain > 0); + } + return (hash != 0); +} + void rk_fill_batch( rk_batch_t _batch, rk_uint count, @@ -861,30 +887,28 @@ void rk_fill_batch( } } bool const is_empty = (batch->state < RK_BATCH_STATE_FILLED); + bool const resized = (count != batch->count); bool const got_everything = (flags && meshes && got_all_params); - bool const need_sorting = (is_empty || flags || meshes || count != batch->count); if (is_empty && !got_everything) { rk_printf("rk_fill_batch(): cannot freeze and empty batch."); + return; } else if (count > batch->count && !got_everything) { rk_printf("rk_fill_batch(): cannot grow a frozen batch."); - } else { - batch->count = count; - } - if (flags) { - memcpy(batch->flags, flags, batch->count * sizeof(rk_instance_flags)); - } - if (meshes) { - memcpy(batch->meshes, meshes, batch->count * sizeof(rk_mesh)); + return; } + batch->count = count; + bool const cmp_flags = + (flags && rk_compare_replace(batch->flags, flags, batch->count * sizeof(rk_instance_flags))); + bool const cmp_meshes = + (meshes && rk_compare_replace(batch->meshes, meshes, batch->count * sizeof(rk_mesh))); + bool const need_sorting = (cmp_flags || cmp_meshes || resized); if (batch->nparams) { rk_parameter const * const last_param = batch->params + batch->nparams; if (got_any_params) { rk_ubyte const * const * src = params; for (rk_parameter const * dst = batch->params; dst < last_param; ++dst, ++src) { - dst->dirty = (need_sorting || *src); - if (*src) { - memcpy(dst->source, *src, batch->count * dst->src_size); - } + dst->dirty = + (*src && rk_compare_replace(dst->source, *src, batch->count * dst->src_size)) || need_sorting; } } else if (need_sorting) { for (rk_parameter const * dst = batch->params; dst < last_param; ++dst) {