public unsafe void should_able_to_create_and_fetch_data_from_node_blob() { Debug.Log($"sizeof NodeA: {sizeof(NodeA.Data)}"); Debug.Log($"sizeof NodeB: {sizeof(NodeB.Data)}"); var size = sizeof(NodeA.Data) + sizeof(NodeB.Data); using (var blobBuilder = new BlobBuilder(Allocator.Temp)) { ref var blob = ref blobBuilder.ConstructRoot <NodeBlob>(); var endIndices = blobBuilder.Allocate(ref blob.EndIndices, 3); endIndices[0] = 3; endIndices[1] = 2; endIndices[2] = 3; var offsets = blobBuilder.Allocate(ref blob.Offsets, 3); var unsafePtr = (byte *)blobBuilder.Allocate(ref blob.DefaultDataBlob, size).GetUnsafePtr(); var offset = 0; offsets[0] = offset; offsets[1] = offset; UnsafeUtilityEx.AsRef <NodeA.Data>(unsafePtr + offset).A = 111; offset += sizeof(NodeA.Data); offsets[2] = offset; ref var local2 = ref UnsafeUtilityEx.AsRef <NodeB.Data>(unsafePtr + offset);
public unsafe T GetData <T>() where T : struct { var index = TypeManager.GetTypeIndex <T>(); var ptr = Entity.GetComponentDataRawRO(EntityManager, index); return(UnsafeUtilityEx.AsRef <T>(ptr)); }
public void OnCreate() { m_TypeArrayIndices = (ushort *)UnsafeUtility.Malloc(sizeof(ushort) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtilityEx.MemSet(m_TypeArrayIndices, 0xFF, sizeof(ushort) * kMaxTypes); #if ENABLE_UNITY_COLLECTIONS_CHECKS m_TempSafety = AtomicSafetyHandle.Create(); #endif m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes); m_ComponentSafetyHandles = (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16, Allocator.Persistent); UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes); m_JobDependencyCombineBufferCount = 4 * 1024; m_JobDependencyCombineBuffer = (JobHandle *)UnsafeUtility.Malloc( sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent); m_TypeCount = 0; IsInTransaction = false; m_ExclusiveTransactionDependency = default(JobHandle); }
unsafe public void TestCreateQuad() { float3[] vertices = { new float3(-4.5f, 0.0f, 1.0f), new float3(3.4f, 0.7f, 1.0f), new float3(3.4f, 2.7f, 1.0f), new float3(-3.4f, 1.2f, 1.0f) }; float3 normal = math.normalize(math.cross(vertices[2] - vertices[1], vertices[0] - vertices[1])); var collider = PolygonCollider.CreateQuad(vertices[0], vertices[1], vertices[2], vertices[3]); var quadCollider = UnsafeUtilityEx.AsRef <PolygonCollider>(collider.GetUnsafePtr()); Assert.IsFalse(quadCollider.IsTriangle); Assert.IsTrue(quadCollider.IsQuad); TestUtils.AreEqual(quadCollider.Vertices[0], vertices[0], 1e-3f); TestUtils.AreEqual(quadCollider.Vertices[1], vertices[1], 1e-3f); TestUtils.AreEqual(quadCollider.Vertices[2], vertices[2], 1e-3f); TestUtils.AreEqual(quadCollider.Vertices[3], vertices[3], 1e-3f); Assert.AreEqual(2, quadCollider.Planes.Length); TestUtils.AreEqual(normal, quadCollider.Planes[0].Normal, 1e-3f); TestUtils.AreEqual(-normal, quadCollider.Planes[1].Normal, 1e-3f); Assert.AreEqual(ColliderType.Quad, quadCollider.Type); Assert.AreEqual(CollisionType.Convex, quadCollider.CollisionType); }
public static unsafe void Execute(ref NativeMultiHashMapVisitKeyMutableValueJobStruct <TJob, TKey, TValue> fullData, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) { while (true) { int begin; int end; if (!JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out begin, out end)) { return; } var buckets = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->buckets; var nextPtrs = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->next; var keys = fullData.HashMap.m_MultiHashMapData.m_Buffer->keys; var values = fullData.HashMap.m_MultiHashMapData.m_Buffer->values; for (int i = begin; i < end; i++) { int entryIndex = buckets[i]; while (entryIndex != -1) { var key = UnsafeUtility.ReadArrayElement <TKey>(keys, entryIndex); fullData.JobData.ExecuteNext(key, ref UnsafeUtilityEx.ArrayElementAsRef <TValue>(values, entryIndex)); entryIndex = nextPtrs[entryIndex]; } } } }
public unsafe T GetData <T>() where T : struct { var index = TypeManager.GetTypeIndex <T>(); var ptr = GetPtrByTypeIndexRO(index); return(UnsafeUtilityEx.AsRef <T>(ptr)); }
unsafe public void TestCreateTriangle() { float3[] vertices = { new float3(-1.4f, 1.4f, 5.6f), new float3(1.4f, 1.4f, 3.6f), new float3(0.2f, 1.2f, 5.6f) }; float3 normal = math.normalize(math.cross(vertices[1] - vertices[0], vertices[2] - vertices[0])); var collider = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]); var triangleCollider = UnsafeUtilityEx.AsRef <PolygonCollider>(collider.GetUnsafePtr()); Assert.IsTrue(triangleCollider.IsTriangle); Assert.IsFalse(triangleCollider.IsQuad); TestUtils.AreEqual(triangleCollider.Vertices[0], vertices[0], 1e-3f); TestUtils.AreEqual(triangleCollider.Vertices[1], vertices[1], 1e-3f); TestUtils.AreEqual(triangleCollider.Vertices[2], vertices[2], 1e-3f); Assert.AreEqual(2, triangleCollider.Planes.Length); TestUtils.AreEqual(normal, triangleCollider.Planes[0].Normal, 1e-3f); TestUtils.AreEqual(-normal, triangleCollider.Planes[1].Normal, 1e-3f); Assert.AreEqual(ColliderType.Triangle, triangleCollider.Type); Assert.AreEqual(CollisionType.Convex, triangleCollider.CollisionType); }
public static void CheckIsUnmanaged <T>() { if (!UnsafeUtilityEx.IsUnmanaged <T>()) { throw new ArgumentException($"{typeof(T)} used in native collection is not blittable or primitive"); } }
static unsafe void ExecuteInnerLoop(ref JobStruct_Process1 <T, U0> jobData, int begin, int end) { ComponentChunkCache cache0; while (begin != end) { jobData.Iterator.Iterator0.UpdateCache(begin, out cache0); var ptr0 = UnsafeUtilityEx.RestrictNoAlias(cache0.CachedPtr); var curEnd = Math.Min(end, cache0.CachedEndIndex); for (var i = begin; i != curEnd; i++) { #if CSHARP_7_OR_LATER ref var value0 = ref UnsafeUtilityEx.ArrayElementAsRef <U0>(ptr0, i); jobData.Data.Execute(ref value0); #else var value0 = UnsafeUtility.ReadArrayElement <U0>(ptr0, i); jobData.Data.Execute(ref value0); if (jobData.Iterator.IsReadOnly0 == 0) { UnsafeUtility.WriteArrayElement(ptr0, i, value0); } #endif } begin = curEnd; }
public static unsafe void PoisonUnusedChunkData(Chunk *chunk, byte value) { Archetype *archetype = chunk.Archetype; int chunkBufferSize = Chunk.GetChunkBufferSize(archetype->TypesCount, archetype->NumSharedComponents); byte * numPtr = &chunk.Buffer.FixedElementField; int count = chunk.Count; int index = 0; while (true) { if (index >= (archetype->TypesCount - 1)) { int num3 = archetype->TypeMemoryOrder[archetype->TypesCount - 1]; int num4 = archetype->Offsets[num3] + (count * archetype->SizeOfs[num3]); UnsafeUtilityEx.MemSet((void *)(numPtr + num4), value, chunkBufferSize - num4); return; } int num6 = archetype->TypeMemoryOrder[index]; int num7 = archetype->TypeMemoryOrder[index + 1]; int num8 = archetype->Offsets[num6] + (count * archetype->SizeOfs[num6]); int num9 = archetype->Offsets[num7]; UnsafeUtilityEx.MemSet((void *)(numPtr + num8), value, num9 - num8); index++; } }
protected override unsafe void OnUpdate() { _mainThreadBlackboard.EntityCommandMainThread.EntityCommandBuffer = _endSimulationEntityCommandBufferSystem.CreateCommandBuffer(); var behaviorTreeJobDeps = new JobHandle(); Entities.WithoutBurst().ForEach((Entity entity, DynamicBuffer <BehaviorTreeBufferElement> buffers, ref CurrentBehaviorTreeComponent currentBehaviorTree) => { _mainThreadBlackboard.Entity = entity; _mainThreadBlackboard.EntityCommandMainThread.Entity = entity; for (var i = 0; i < buffers.Length; i++) { var bufferPtr = (IntPtr)buffers.GetUnsafeReadOnlyPtr() + UnsafeUtility.SizeOf <BehaviorTreeBufferElement>() * i; ref var buffer = ref UnsafeUtilityEx.AsRef <BehaviorTreeBufferElement>(bufferPtr.ToPointer()); if (buffer.RuntimeThread == BehaviorTreeRuntimeThread.MainThread || buffer.RuntimeThread == BehaviorTreeRuntimeThread.ForceMainThread) { if (buffer.QueryMask.Matches(entity)) { var blob = buffers[i].NodeBlob; currentBehaviorTree.Value = bufferPtr; VirtualMachine.Tick(ref blob, ref _mainThreadBlackboard); } } else { // TODO: is this right way to do this? seems not optimize? behaviorTreeJobDeps = JobHandle.CombineDependencies(behaviorTreeJobDeps, buffers[i].Dependency); } } }).Run();
public void RangeQuery(AABB bounds, NativeList <OctElement <T> > results) { var targetBounds = new Aabb { Min = bounds.Min, Max = bounds.Max }; var outputResults = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref results); if (Data->TotalElements > outputResults->Capacity) { // todo: find out why its possible to return more elements than exists // should be able to use 'TotalElements' for capacity here. 10/100 work, // but 1000 yields 1012-1018 elements... outputResults->Resize <OctElement <T> >(Data->TotalElements * 2); } var resultsPtr = (byte *)outputResults->Ptr; var nodesPtr = (byte *)Data->Nodes->Ptr; var elementPtr = (byte *)Data->Elements->Ptr; var quadPtr = (byte *)Data->Quads->Ptr; var quadCount = Data->Quads->Length; var maxLeaves = quadCount * 16 * Data->TotalDepth; int resultCount = 0; int containCount = 0; int overlapCount = 0; // Work around c# enforcing use of Span<T>. var useStack = maxLeaves <= 256; var size = useStack ? sizeof(int) * maxLeaves : 1; var ptr1 = stackalloc int[size]; var ptr2 = stackalloc int[size]; size = sizeof(int) * maxLeaves; var containOffsets = useStack ? ptr1 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp); var overlapOffsets = useStack ? ptr2 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp); for (int i = 0; i < quadCount; i++) { QuadGroup quad = *(QuadGroup *)(quadPtr + i * sizeof(QuadGroup)); bool4 isContainedA = quad.Bounds.ContainedBy(targetBounds); bool4 isOverlapA = quad.Bounds.OverlappedBy(targetBounds); bool4 skipMaskA = !isContainedA & !isOverlapA; bool4 containedLeafMaskA = !skipMaskA & isContainedA; bool4 intersectedMaskA = !containedLeafMaskA & isOverlapA; containCount = compress(containOffsets, containCount, quad.Offsets, containedLeafMaskA); overlapCount = compress(overlapOffsets, overlapCount, quad.Offsets, intersectedMaskA); } for (int i = 0; i < containCount; i++) { ref var node = ref UnsafeUtilityEx.ArrayElementAsRef <OctNode>(nodesPtr, containOffsets[i]); var src = elementPtr + node.firstChildIndex * UnsafeUtility.SizeOf <OctElement <T> >(); var dst = resultsPtr + resultCount * UnsafeUtility.SizeOf <OctElement <T> >(); UnsafeUtility.MemCpy(dst, src, node.count * UnsafeUtility.SizeOf <OctElement <T> >()); resultCount += node.count; }
public void FromArrayUnsafe(T[] array) { Length = array.Length; for (var i = 0; i < Length; i++) { UnsafeUtilityEx.ArrayElementAsRef <T>(ArrayDataPtr, i) = array[i]; } }
private static unsafe bool IsTrigger(NativeSlice <RigidBody> bodies, int rigidBodyIndex, ColliderKey colliderKey) { RigidBody hitBody = bodies[rigidBodyIndex]; hitBody.Collider.Value.GetLeaf(colliderKey, out ChildCollider leafCollider); Material material = UnsafeUtilityEx.AsRef <ConvexColliderHeader>(leafCollider.Collider).Material; return(material.IsTrigger); }
internal Enumerator(TSource start, long count, TAction action, Allocator allocator) { this.current = UnsafeUtilityEx.Malloc <TSource>(1, allocator); *this.current = start; this.count = count; this.index = -1; this.action = action; this.allocator = allocator; }
public static unsafe T GetData <T>(this IBlackboard bb, ulong componentStableHash, int componentDataOffset) where T : struct { var componentPtr = (byte *)bb.GetPtrRO(componentStableHash); // TODO: type safety check var dataPtr = componentPtr + componentDataOffset; return(UnsafeUtilityEx.AsRef <T>(dataPtr)); }
public unsafe void SetComponentData <T>(T value) where T : struct, IComponentData { var typeIndex = TypeManager.GetTypeIndex <T>(); if (TypeManager.IsZeroSized(typeIndex)) { throw new ArgumentException($"SetComponentData<{typeof(T)}> can not be called with a zero sized component."); } UnsafeUtilityEx.AsRef <T>(Chunk.GetComponentDataWithTypeRW(Index, typeIndex, GlobalSystemVersion)) = value; }
public static unsafe void Allocate <T>( this VariableProperty <T> variable , ref BlobBuilder builder , void *blobVariablePtr , INodeDataBuilder self , ITreeNode <INodeDataBuilder>[] tree ) where T : struct { variable.Allocate(ref builder, ref UnsafeUtilityEx.AsRef <BlobVariable <T> >(blobVariablePtr), self, tree); }
public unsafe T GetComponentData <T>() where T : struct, IComponentData { var typeIndex = TypeManager.GetTypeIndex <T>(); if (TypeManager.IsZeroSized(typeIndex)) { throw new ArgumentException($"GetComponentData<{typeof(T)}> can not be called with a zero sized component."); } return(UnsafeUtilityEx.AsRef <T>(Chunk.GetComponentDataWithTypeRO(Index, typeIndex))); }
unsafe public void TestSphereColliderCreate() { float3 center = new float3(-8.45f, 9.65f, -0.10f); float radius = 0.98f; var collider = SphereCollider.Create(center, radius); var sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr()); TestUtils.AreEqual(center, sphereCollider.Center, 1e-3f); TestUtils.AreEqual(radius, sphereCollider.Radius, 1e-3f); Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type); Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType); }
protected override unsafe void Build(void *dataPtr, BlobBuilder _, ITreeNode <INodeDataBuilder>[] __) { switch (_source) { case SourceType.Component: break; case SourceType.Custom: { ref var data = ref UnsafeUtilityEx.AsRef <SetTransformRotationWithCustomRotationNode>(dataPtr); data.Rotation = quaternion.Euler(CustomRotation); break; }
public T ReadBlittable <T>() where T : struct { T val; unsafe { int size = UnsafeUtility.SizeOf <T>(); NativeSlice <byte> bytes = ReadSlice(size); val = UnsafeUtilityEx.AsRef <T>((void *)((byte *)bytes.GetUnsafePtr())); } return(val); }
unsafe public void TestCapsuleColliderCreate() { float3 v0 = new float3(1.45f, 0.34f, -8.65f); float3 v1 = new float3(100.45f, -80.34f, -8.65f); float radius = 1.45f; var collider = CapsuleCollider.Create(v0, v1, radius); var capsuleCollider = UnsafeUtilityEx.AsRef <CapsuleCollider>(collider.GetUnsafePtr()); Assert.AreEqual(ColliderType.Capsule, capsuleCollider.Type); Assert.AreEqual(CollisionType.Convex, capsuleCollider.CollisionType); TestUtils.AreEqual(v0, capsuleCollider.Vertex0); TestUtils.AreEqual(v1, capsuleCollider.Vertex1); TestUtils.AreEqual(radius, capsuleCollider.Radius); }
public unsafe void TestBoxColliderCreate() { float3 center = new float3(-10.10f, 10.12f, 0.01f); quaternion orientation = quaternion.AxisAngle(math.normalize(new float3(1.4f, 0.2f, 1.1f)), 38.50f); float3 size = new float3(0.01f, 120.40f, 5.4f); float convexRadius = 0.0f; var collider = BoxCollider.Create(center, orientation, size, convexRadius); var boxCollider = UnsafeUtilityEx.AsRef <BoxCollider>(collider.GetUnsafePtr()); Assert.AreEqual(center, boxCollider.Center); Assert.AreEqual(orientation, boxCollider.Orientation); Assert.AreEqual(size, boxCollider.Size); Assert.AreEqual(convexRadius, boxCollider.ConvexRadius); Assert.AreEqual(CollisionType.Convex, boxCollider.CollisionType); Assert.AreEqual(ColliderType.Box, boxCollider.Type); }
protected override unsafe void OnUpdate() { var typeMoveCommand = GetArchetypeChunkComponentType <MoveCommand>(true); var typeDestroyable = GetArchetypeChunkComponentType <DestroyableComponentData>(); var typeTicks = GetArchetypeChunkComponentType <DateTimeTicksToProcess>(true); var typeTeamTag = GetArchetypeChunkComponentType <TeamTag>(true); var typePhysicsVelocity = GetArchetypeChunkComponentType <PhysicsVelocity>(); var currentTicks = DateTime.Now.Ticks; using (var moveCommandChunks = _queryMoveCommand.CreateArchetypeChunkArray(Allocator.TempJob)) using (var velocitiesChunks = _query.CreateArchetypeChunkArray(Allocator.TempJob)) { foreach (var moveCommandChunk in moveCommandChunks) { var moveCommands = moveCommandChunk.GetNativeArray(typeMoveCommand); var destroys = moveCommandChunk.GetNativeArray(typeDestroyable); var ticks = moveCommandChunk.GetNativeArray(typeTicks); for (var i = 0; i < ticks.Length; i++) { if (ticks[i].Value < currentTicks || destroys[i].ShouldDestroy) { continue; } destroys[i] = new DestroyableComponentData() { ShouldDestroy = true }; foreach (var velocitiesChunk in velocitiesChunks) { var teamTags = velocitiesChunk.GetNativeArray(typeTeamTag); var physicsVelocities = velocitiesChunk.GetNativeArray(typePhysicsVelocity); for (var j = 0; j < teamTags.Length; j++) { if (teamTags[j].Id != moveCommands[i].Id) { continue; } UnsafeUtilityEx .ArrayElementAsRef <PhysicsVelocity>(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(physicsVelocities), j) .Linear += moveCommands[i].DeltaVelocity; } } } } } }
public static void PoisonUnusedChunkData(Chunk *chunk, byte value) { var arch = chunk->Archetype; int bufferSize = Chunk.GetChunkBufferSize(arch->NumSharedComponents); byte *buffer = chunk->Buffer; int count = chunk->Count; for (int i = 0; i < arch->TypesCount - 1; ++i) { int startOffset = arch->Offsets[i] + count * arch->SizeOfs[i]; int endOffset = arch->Offsets[i + 1]; UnsafeUtilityEx.MemSet(buffer + startOffset, value, endOffset - startOffset); } int lastStartOffset = arch->Offsets[arch->TypesCount - 1] + count * arch->SizeOfs[arch->TypesCount - 1]; UnsafeUtilityEx.MemSet(buffer + lastStartOffset, value, bufferSize - lastStartOffset); }
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) { var random = new Unity.Mathematics.Random(RandomSeed); var index = chunk.GetSharedComponentIndex(SpriteAnimationChunkType); var spriteAnimation = UniqueSpriteAnimations[index]; var entities = chunk.GetNativeArray(EntityChunkType); var states = chunk.GetNativeArray(SpriteAnimationStateChunkType).GetUnsafePtr(); var randomizers = chunk.GetNativeArray(SpriteAnimationRandomizerChunkType); for (var i = 0; i < chunk.Count; ++i) { spriteAnimation.ClipIndex = random.NextInt(0, spriteAnimation.ClipCount); SpriteAnimationMap.TryAdd(entities[i], spriteAnimation); UnsafeUtilityEx.ArrayElementAsRef <SpriteAnimationState>(states, i).Speed = random.NextFloat(randomizers[i].RandomSpeedStart, randomizers[i].RandomSpeedEnd); } }
unsafe public void TestSphereColliderCreate() { var sphere = new SphereGeometry { Center = new float3(-8.45f, 9.65f, -0.10f), Radius = 0.98f }; var collider = SphereCollider.Create(sphere); var sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr()); TestUtils.AreEqual(sphere.Center, sphereCollider.Center, 1e-3f); TestUtils.AreEqual(sphere.Center, sphereCollider.Geometry.Center, 1e-3f); TestUtils.AreEqual(sphere.Radius, sphereCollider.Radius, 1e-3f); TestUtils.AreEqual(sphere.Radius, sphereCollider.Geometry.Radius, 1e-3f); Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type); Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType); }
protected override unsafe void Build(void *dataPtr, BlobBuilder _, ITreeNode <INodeDataBuilder>[] __) { switch (Source) { case VelocitySource.Component: return; case VelocitySource.CustomGlobal: UnsafeUtilityEx.AsRef <CharacterSimpleMoveWithCustomGlobalVelocityNode>(dataPtr).Velocity = CustomVelocity; break; case VelocitySource.CustomLocal: UnsafeUtilityEx.AsRef <CharacterSimpleMoveWithCustomLocalVelocityNode>(dataPtr).Velocity = CustomVelocity; break; default: throw new ArgumentOutOfRangeException(); } }
public static void PoisonUnusedChunkData(Chunk *chunk, byte value) { var arch = chunk->Archetype; var bufferSize = Chunk.GetChunkBufferSize(arch->TypesCount, arch->NumSharedComponents); var buffer = chunk->Buffer; var count = chunk->Count; for (int i = 0; i < arch->TypesCount - 1; ++i) { var index = arch->TypeMemoryOrder[i]; var nextIndex = arch->TypeMemoryOrder[i + 1]; var startOffset = arch->Offsets[index] + count * arch->SizeOfs[index]; var endOffset = arch->Offsets[nextIndex]; UnsafeUtilityEx.MemSet(buffer + startOffset, value, endOffset - startOffset); } var lastIndex = arch->TypeMemoryOrder[arch->TypesCount - 1]; var lastStartOffset = arch->Offsets[lastIndex] + count * arch->SizeOfs[lastIndex]; UnsafeUtilityEx.MemSet(buffer + lastStartOffset, value, bufferSize - lastStartOffset); }