message: small optimization that helps avoid bindUniformBufferRange calls
  a lot of primitive may use the same UBO slot, if they happen to be
  in a sequence, we don't need to rebind the UBO.
diff: @@ -601,6 +601,7 @@ void RenderPass::Executor::recordDriverCommands(FEngine& engine, backend::Driver
  Handle<HwBufferObject> uboHandle = mUboHandle;
  FMaterialInstance const* UTILS_RESTRICT mi = nullptr;
  FMaterial const* UTILS_RESTRICT ma = nullptr;
  + uint32_t uboDataIndex = std::numeric_limits<uint32_t>::max();
  auto customCommands = mCustomCommands.data();
  first--;
  @@ -637,9 +638,13 @@ void RenderPass::Executor::recordDriverCommands(FEngine& engine, backend::Driver
  }
  pipeline.program = ma->getProgram(info.materialVariant);
  - size_t offset = info.index * sizeof(PerRenderableData);
  +
  + if (uboDataIndex != info.index) {
  + uboDataIndex = info.index;
  driver.bindUniformBufferRange(BindingPoints::PER_RENDERABLE,
  - uboHandle, offset, sizeof(PerRenderableUib));
  + uboHandle, uboDataIndex * sizeof(PerRenderableData),
  + sizeof(PerRenderableUib));
  + }
  if (UTILS_UNLIKELY(info.skinningHandle)) {
  // note: we can't bind less than sizeof(PerRenderableBoneUib) due to glsl limitations
  