Page MenuHome

Bones in Envelope Display break apart after selecting bone at id 0.
Closed, ResolvedPublicBUG


Blender Version
Broken: 2.80, 81b68f7279cd

This happens both in pose mode and edit mode, only in Envelope armature display mode. It seems to be related to which bone was created first.


  • In envelope display mode, have a bunch of bones, but know which one is on id 0. Pose mode or edit mode, doesn't matter.
  • Select and move them around, avoiding the id 0 bone, and everything should be working fine.
  • When you select id 0 bone for the first time, everything is still fine.
  • Now when you select another bone, you will see the envelope of the bone that was selected before id 0 bone, even if that is not the bone you just selected. Uh oh.
  • Selecting any other bone will not update the displayed envelope. You can only see that same envelope. Even if you move the bone the envelope belongs to, it stays in place, not following that bone.
  • That is, until you select id 0 bone again. Now if you try to move it, everything falls apart!
  • Switching between Pose/Edit mode will clean the mess up until you switch back to the other mode. Switching to Object mode will clean the mess up permanently until you do the ritual again.

Event Timeline

Philipp Oeser (lichtwerk) lowered the priority of this task from 90 to 50.

I assume this is drawing code [not sure though], @Clément Foucault (fclem): dose this ring a bell?

Clément Foucault (fclem) raised the priority of this task from 50 to High.Jun 11 2019, 9:29 PM

The problem is that DRW_temp_buffer_request deletes the vbo_id of the instance, which invalidates the batch/vao even though it has the same pointers.

A solution I have found is not to delete the vbo_id:

diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index e7a41ee3e43..bcc5a58e58e 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -124,8 +124,11 @@ GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist,
   if (handle->format != format) {
     handle->format = format;
     /* TODO/PERF: Save the allocated data from freeing to avoid reallocation. */
-    GPU_vertbuf_clear(vert);
-    GPU_vertbuf_init_with_format_ex(vert, format, GPU_USAGE_DYNAMIC);
+    GPU_vertformat_copy(&vert->format, format);
+    vert->usage = GPU_USAGE_DYNAMIC;
+    /* Skip assert. */
+    vert->vertex_alloc = -1;
     GPU_vertbuf_data_alloc(vert, DRW_BUFFER_VERTS_CHUNK);
   return vert;

Or we can indicate the batch not is_compatible if buf->vbo_id is 0:

diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index e7a41ee3e43..b1eefc6f8a6 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -140,8 +140,8 @@ GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist,
   BLI_assert(geom->inst == NULL);
   GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_instancing);
-  bool is_compatible = (batch->gl_prim_type == geom->gl_prim_type) && (batch->inst == buf) &&
-                       (batch->phase == GPU_BATCH_READY_TO_DRAW);
+  bool is_compatible = (buf->vbo_id != 0 && batch->gl_prim_type == geom->gl_prim_type) &&
+                       (batch->inst == buf) && (batch->phase == GPU_BATCH_READY_TO_DRAW);
   for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && is_compatible; i++) {
     if (batch->verts[i] != geom->verts[i]) {
       is_compatible = false;

I have already fixed this issue locally i just didn't pushed it yet. :)