Use Hierarchical Instanced Static Mesh with Custom Data on Android

How can I properly use custom data (per HISM instance) on Android?

Everything works fine when I run it on desktop, using the following code:

Setting up the HISM component:


  // now create the HISM voxel mesh
  voxelMesh = CreateDefaultSubobject(TEXT("VoxelMesh"));
  // attach it to our root component
  voxelMesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
  // set the collision on the voxel mesh to have no collision
  voxelMesh->bDisableCollision = true;
  voxelMesh->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName, true);
  // set the number of custom data channels per instance (3, RGB) or (0)
  voxelMesh->NumCustomDataFloats = showVoxelColor ? 3 : 0;
  // set the material that we loaded (or NULL if it could not be found
  // for default material)
  voxelMesh->SetMaterial(0, voxelMaterial);
  // set the rendered mesh for the instances
  voxelMesh->SetStaticMesh(voxelRenderMesh);
  // setup the material accordingly:
  // set the height map coloring according to showVoxelColor
  voxelMesh->SetCustomPrimitiveDataFloat(0, showVoxelColor ? 0.0 : 1.0);
  // set the height colormap range (meters)
  voxelMesh->SetCustomPrimitiveDataFloat(1, 2.0);
  // set the height colormap midpoint
  voxelMesh->SetCustomPrimitiveDataFloat(2, 0.5);

Creating / updating the voxels:


      double start, end;
      start = FPlatformTime::Seconds();
      FTransform t;
      FVector scale{ voxelSize, voxelSize, voxelSize };
      size_t numVoxels = voxelLocations.Num();
      bool teleportUpdate = true;
      bool setRenderStateDirty = false;
      bool transformIsWorldSpace = false;
      // update the instances here
      size_t index = 0;
      UE_LOG(LogTemp, Warning, TEXT("Updating %d existing instances"), voxelMesh->GetInstanceCount());
      // update voxels we already have
      for (; index < voxelMesh->GetInstanceCount(); index++) {
        // break if we have more voxels than we currently have meshes
        if (index >= numVoxels) break;
        // set the transform
        t.SetTranslationAndScale3D(voxelLocations[index], scale);
        voxelMesh->UpdateInstanceTransform(index, t,
                                           transformIsWorldSpace,
                                           setRenderStateDirty,
                                           teleportUpdate);
        if (showVoxelColor) {
          // set the color
          FLinearColor color = voxelColors[index];
          // TArray customData{color.R, color.G, color.B};
          // voxelMesh->SetCustomData(index, customData, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 0, color.R, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 1, color.G, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 2, color.B, setRenderStateDirty);
        }
      }
      // add new voxels if we have more than we have meshes
      UE_LOG(LogTemp, Warning, TEXT("Adding %d new instances"), numVoxels - index);
      for (; index < numVoxels; index++) {
        // create the new mesh instance
        t.SetTranslationAndScale3D(voxelLocations[index], scale);
        voxelMesh->AddInstance(t);
        if (showVoxelColor) {
          // set the color
          FLinearColor color = voxelColors[index];
          // TArray customData{color.R, color.G, color.B};
          // voxelMesh->SetCustomData(index, customData, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 0, color.R, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 1, color.G, setRenderStateDirty);
          voxelMesh->SetCustomDataValue(index, 2, color.B, setRenderStateDirty);
        }
      }
      // remove voxels we don't need anymore - TODO: probably should
      // just hide them and save them for later
      TArray instancesToRemove;
      for (; index < voxelMesh->GetInstanceCount(); index++) {
        instancesToRemove.Add(index);
      }
      UE_LOG(LogTemp, Warning, TEXT("Removing %d unneeded instances"), instancesToRemove.Num());
      voxelMesh->RemoveInstances(instancesToRemove);
      // now mark the render state as dirty!
      voxelMesh->MarkRenderStateDirty();
      // measure performance
      end = FPlatformTime::Seconds();
      UE_LOG(LogTemp, Warning, TEXT("Voxel Creation took %f seconds for %d voxels"), end - start, voxelMesh->GetInstanceCount());

But when I run it on Android I get this error (when enabling the voxel colors):

D/UE4     : [2020.06.09-19.45.41:639][  1]LogTemp: Warning: Voxel Creation took 0.047294 seconds for 10000 voxels
D/UE4     : [2020.06.09-19.45.41:649][  1]LogSlate: Took 0.000545 seconds to synchronously load lazily loaded font '../../../Engine/Content/EngineFonts/Faces/RobotoBold.ufont' (160K)
F/DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
F/DEBUG   : Build fingerprint: 'google/taimen/taimen:10/QQ2A.200501.001.B3/6396602:user/release-keys'
F/DEBUG   : Revision: 'rev_10'
F/DEBUG   : ABI: 'arm'
F/DEBUG   : Timestamp: 2020-06-09 14:45:41-0500
F/DEBUG   : pid: 26693, tid: 26781, name: RHIThread  >>> com.permobil.MobileRoshiCPP <<<
F/DEBUG   : uid: 10777
F/DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
F/DEBUG   : Cause: null pointer dereference
F/DEBUG   :     r0  00000010  r1  00000000  r2  925c3ea0  r3  ffffffff
F/DEBUG   :     r4  00000000  r5  00000000  r6  b10dd000  r7  bd7ce840
F/DEBUG   :     r8  97e37f90  r9  00000002  r10 979ce7b0  r11 b04b8df0
F/DEBUG   :     ip  bd7b3f4c  sp  b04b8da8  lr  b7db6d3c  pc  bca3fab4
F/DEBUG   : 
F/DEBUG   : backtrace:
F/DEBUG   :       #00 pc 0aafcab4  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FOpenGLDynamicRHI::CommitGraphicsResourceTablesInner()+612) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #01 pc 0ab01644  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FOpenGLDynamicRHI::RHIDrawIndexedPrimitive(FRHIIndexBuffer*, int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)+1860) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #02 pc 07248f00  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FRHICommandDrawIndexedPrimitive::Execute(FRHICommandListBase&)+48) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #03 pc 0724d244  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FRHICommandListExecutor::ExecuteInner_DoExecute(FRHICommandListBase&)+1956) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #04 pc 0729c19c  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FExecuteRHIThreadTask::DoTask(ENamedThreads::Type, TRefCountPtr const&)+800) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #05 pc 0729b940  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (_ZN10TGraphTaskI21FExecuteRHIThreadTaskE11ExecuteTaskER6TArrayIP14FBaseGraphTask22TSizedDefaultAllocatorILi32EEEN13ENamedThreads4TypeE+700) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #06 pc 05d72bc8  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FNamedTaskThread::ProcessTasksNamedThread(int, bool)+2144) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #07 pc 05d71950  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FNamedTaskThread::ProcessTasksUntilQuit(int)+108) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #08 pc 0731496c  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FRHIThread::Run()+92) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #09 pc 05e6fff4  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FRunnableThreadPThread::Run()+152) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #10 pc 05d6d044  /data/app/com.permobil.MobileRoshiCPP-WBlY5QajIchHg4iF7GViIg==/lib/arm/libUE4.so (FRunnableThreadPThread::_ThreadProc(void*)+80) (BuildId: d3463a1e87d5a5cbfd4b8b6a9a937f8566e45766)
F/DEBUG   :       #11 pc 000a5ea3  /apex/com.android.runtime/lib/bionic/libc.so (__pthread_start(void*)+20) (BuildId: f9f8835945b295b609712530651a95ae)
F/DEBUG   :       #12 pc 00060773  /apex/com.android.runtime/lib/bionic/libc.so (__start_thread+30) (BuildId: f9f8835945b295b609712530651a95ae)

If I do not set the custom data, everything works fine.

This issue appears to have been fixed in 4.25.4:

Fixed UE-100159 Using per-instance custom data causes crash on mobile devices