public static unsafe NativeArray <DOTSInstancingProperty> GetDOTSInstancingProperties(Shader shader) { if (shader == null) { return(new NativeArray <DOTSInstancingProperty>()); } int propertyCount = 0; IntPtr p = GetDOTSInstancingPropertiesPointer(shader, ref propertyCount); if (p == null) { return(new NativeArray <DOTSInstancingProperty>()); } var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <DOTSInstancingProperty>( (void *)p, propertyCount, Allocator.Temp); AtomicSafetyHandle safety = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, safety); return(array); }
public unsafe static NativeArray <DOTSInstancingProperty> GetDOTSInstancingProperties(Shader shader) { bool flag = shader == null; NativeArray <DOTSInstancingProperty> result; if (flag) { result = default(NativeArray <DOTSInstancingProperty>); } else { int length = 0; IntPtr dOTSInstancingPropertiesPointer = HybridV2ShaderReflection.GetDOTSInstancingPropertiesPointer(shader, ref length); bool flag2 = dOTSInstancingPropertiesPointer == IntPtr.Zero; if (flag2) { result = default(NativeArray <DOTSInstancingProperty>); } else { NativeArray <DOTSInstancingProperty> nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <DOTSInstancingProperty>((void *)dOTSInstancingPropertiesPointer, length, Allocator.Temp); AtomicSafetyHandle tempMemoryHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle <DOTSInstancingProperty>(ref nativeArray, tempMemoryHandle); result = nativeArray; } } return(result); }
unsafe void UpdateBuffers(ImDrawDataPtr drawData) { int drawArgCount = 0; // nr of drawArgs is the same as the nr of ImDrawCmd for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { drawArgCount += drawData.CmdListsRange[n].CmdBuffer.Size; } // create or resize vertex/index buffers if (_vtxBuf == null || _vtxBuf.count < drawData.TotalVtxCount) { CreateOrResizeVtxBuffer(ref _vtxBuf, drawData.TotalVtxCount); } if (_idxBuf == null || _idxBuf.count < drawData.TotalIdxCount) { CreateOrResizeIdxBuffer(ref _idxBuf, drawData.TotalIdxCount); } if (_argBuf == null || _argBuf.count < drawArgCount * 5) { CreateOrResizeArgBuffer(ref _argBuf, drawArgCount * 5); } // upload vertex/index data into buffers int vtxOf = 0; int idxOf = 0; int argOf = 0; for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { ImDrawListPtr drawList = drawData.CmdListsRange[n]; NativeArray <ImDrawVert> vtxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ImDrawVert>( (void *)drawList.VtxBuffer.Data, drawList.VtxBuffer.Size, Allocator.None); NativeArray <ushort> idxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ushort>( (void *)drawList.IdxBuffer.Data, drawList.IdxBuffer.Size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref vtxArray, AtomicSafetyHandle.GetTempMemoryHandle()); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref idxArray, AtomicSafetyHandle.GetTempMemoryHandle()); #endif // upload vertex/index data _vtxBuf.SetData(vtxArray, 0, vtxOf, vtxArray.Length); _idxBuf.SetData(idxArray, 0, idxOf, idxArray.Length); // arguments for indexed draw _drawArgs[3] = vtxOf; // base vertex location for (int i = 0, iMax = drawList.CmdBuffer.Size; i < iMax; ++i) { ImDrawCmdPtr cmd = drawList.CmdBuffer[i]; _drawArgs[0] = (int)cmd.ElemCount; // index count per instance _drawArgs[2] = idxOf + (int)cmd.IdxOffset; // start index location _argBuf.SetData(_drawArgs, 0, argOf, 5); argOf += 5; // 5 int for each cmd } vtxOf += vtxArray.Length; idxOf += idxArray.Length; } }
private unsafe void UpdateMesh(ImDrawDataPtr drawData, Vector2 fbSize) { int subMeshCount = 0; // nr of submeshes is the same as the nr of ImDrawCmd for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { subMeshCount += drawData.CmdListsRange[n].CmdBuffer.Size; } // set mesh structure if (_prevSubMeshCount != subMeshCount) { _mesh.Clear(true); // occasionally crashes when changing subMeshCount without clearing first _mesh.subMeshCount = _prevSubMeshCount = subMeshCount; } _mesh.SetVertexBufferParams(drawData.TotalVtxCount, s_attributes); _mesh.SetIndexBufferParams(drawData.TotalIdxCount, IndexFormat.UInt16); // upload data into mesh int vtxOf = 0; int idxOf = 0; List <SubMeshDescriptor> descriptors = new List <SubMeshDescriptor>(); for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { ImDrawListPtr drawList = drawData.CmdListsRange[n]; NativeArray <ImDrawVert> vtxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ImDrawVert>( (void *)drawList.VtxBuffer.Data, drawList.VtxBuffer.Size, Allocator.None); NativeArray <ushort> idxArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <ushort>( (void *)drawList.IdxBuffer.Data, drawList.IdxBuffer.Size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref vtxArray, AtomicSafetyHandle.GetTempMemoryHandle()); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref idxArray, AtomicSafetyHandle.GetTempMemoryHandle()); #endif // upload vertex/index data _mesh.SetVertexBufferData(vtxArray, 0, vtxOf, vtxArray.Length, 0, NoMeshChecks); _mesh.SetIndexBufferData(idxArray, 0, idxOf, idxArray.Length, NoMeshChecks); // define subMeshes for (int i = 0, iMax = drawList.CmdBuffer.Size; i < iMax; ++i) { ImDrawCmdPtr cmd = drawList.CmdBuffer[i]; SubMeshDescriptor descriptor = new SubMeshDescriptor { topology = MeshTopology.Triangles, indexStart = idxOf + (int)cmd.IdxOffset, indexCount = (int)cmd.ElemCount, baseVertex = vtxOf + (int)cmd.VtxOffset, }; descriptors.Add(descriptor); } vtxOf += vtxArray.Length; idxOf += idxArray.Length; } _mesh.SetSubMeshes(descriptors, NoMeshChecks); _mesh.UploadMeshData(false); }
public NativeArray <T> AsArray <T>() where T : unmanaged { var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <T>(m_ListData->Ptr, m_ListData->Length, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, AtomicSafetyHandle.GetTempMemoryHandle()); #endif return(array); }
unsafe NativeList(int capacity, Allocator i_label, int stackDepth) { #if ENABLE_UNITY_COLLECTIONS_CHECKS var guardian = new NativeBufferSentinel(stackDepth, i_label); m_Safety = (i_label == Allocator.Temp) ? AtomicSafetyHandle.GetTempMemoryHandle() : AtomicSafetyHandle.Create(); m_Impl = new NativeListImpl <T, DefaultMemoryManager, NativeBufferSentinel>(capacity, i_label, guardian); #else m_Impl = new NativeListImpl <T, DefaultMemoryManager>(capacity, i_label); #endif }
Entity CreateDstEntity(UnityObject uobject, int serial) { Entity returnValue; unsafe { var arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <Entity>(&returnValue, 1, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref arr, AtomicSafetyHandle.GetTempMemoryHandle()); #endif CreateDstEntity(uobject, arr, serial); } return(returnValue); }
public void CopyPixelDataToLayer <T>(NativeArray <T> colorData, int layerIdx) where T : struct { var layer = GetLayer(layerIdx); NativeArray <T> dstDataAsColor; AtomicSafetyHandle m_Safety = AtomicSafetyHandle.GetTempMemoryHandle(); unsafe { dstDataAsColor = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <T>(layer.data, layer.dataSize, Allocator.Temp); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref dstDataAsColor, m_Safety); } var dstWidth = layer.scanlineSize / UnsafeUtility.SizeOf <T>(); for (int i = 0; i < height; ++i) { NativeArray <T> .Copy(colorData, i *width, dstDataAsColor, i *dstWidth, width); } dstDataAsColor.Dispose(); }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); var oldSequenceId = (int *)ctx.internalProcessBuffer; ushort sequenceId = reader.ReadUShort(); if (SequenceHelpers.GreaterThan16(sequenceId, (ushort)*oldSequenceId)) { *oldSequenceId = sequenceId; // Skip over the part of the buffer which contains the header inboundBuffer = inboundBuffer.Slice(sizeof(ushort)); return; } inboundBuffer = default; }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { // Request a send update to see if a queued packet needs to be resent later or if an ack packet should be sent requests = NetworkPipelineStage.Requests.SendUpdate; bool needsResume = false; var header = default(ReliableUtility.PacketHeader); var slice = default(InboundRecvBuffer); ReliableUtility.Context * reliable = (ReliableUtility.Context *)ctx.internalProcessBuffer; ReliableUtility.SharedContext *shared = (ReliableUtility.SharedContext *)ctx.internalSharedProcessBuffer; shared->errorCode = 0; if (reliable->Resume == ReliableUtility.NullEntry) { if (inboundBuffer.bufferLength <= 0) { inboundBuffer = slice; return; } var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); reader.ReadBytes((byte *)&header, UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); if (header.Type == (ushort)ReliableUtility.PacketType.Ack) { ReliableUtility.ReadAckPacket(ctx, header); inboundBuffer = default; return; } var result = ReliableUtility.Read(ctx, header); if (result >= 0) { var nextExpectedSequenceId = (ushort)(reliable->Delivered + 1); if (result == nextExpectedSequenceId) { reliable->Delivered = result; slice = inboundBuffer.Slice(UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); if (needsResume = SequenceHelpers.GreaterThan16((ushort)shared->ReceivedPackets.Sequence, (ushort)result)) { reliable->Resume = (ushort)(result + 1); } } else { ReliableUtility.SetPacket(ctx.internalProcessBuffer, result, inboundBuffer.Slice(UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>())); slice = ReliableUtility.ResumeReceive(ctx, reliable->Delivered + 1, ref needsResume); } } } else { slice = ReliableUtility.ResumeReceive(ctx, reliable->Resume, ref needsResume); } if (needsResume) { requests |= NetworkPipelineStage.Requests.Resume; } inboundBuffer = slice; }
bool LoadPointCloudFile(string file) { var ret = load(file); if (ret == 0) { if (is_bigendian() == 0) { if (is_dense() == 1) { ulong size = size_blob(); if (size > 0) { if (size > int.MaxValue) { Debug.LogError("load failed as size_blob > int.MaxValue"); } else { if (contains_xyz()) { if (contains_rgb() || contains_rgba()) { size = load_as_xyzrgba(out IntPtr data_xyzrgb); if (size > (ulong)(int.MaxValue / sizeof(PointXYZRGBA))) { Debug.LogError($"load failed as breached max points amount {int.MaxValue / sizeof(PointXYZRGBA)} , this file have {size} points !"); } else if (size > (ulong)(int.MaxValue / sizeof(PCLPointXYZRGBA))) { var origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZRGBA>(data_xyzrgb.ToPointer(), int.MaxValue / sizeof(PCLPointXYZRGBA), Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp_1 = new NativeArray <PCLPointXYZRGBA>(origin, Allocator.TempJob); int remain = (int)size - temp_1.Length; origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZRGBA>(IntPtr.Add(data_xyzrgb, remain * 32).ToPointer(), remain, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp_2 = new NativeArray <PCLPointXYZRGBA>(origin, Allocator.TempJob); clear(); var densed_1 = Dense(temp_1); temp_1.Dispose(); var densed_2 = Dense(temp_2); temp_2.Dispose(); PointXYZRGBAs = new NativeArray <PointXYZRGBA>((int)size, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <PointXYZRGBA> .Copy(densed_1, PointXYZRGBAs, densed_1.Length); NativeArray <PointXYZRGBA> .Copy(densed_2, 0, PointXYZRGBAs, densed_1.Length, densed_2.Length); densed_1.Dispose(); densed_2.Dispose(); return(true); } else if (size > 0) { var origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZRGBA>(data_xyzrgb.ToPointer(), (int)size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp = new NativeArray <PCLPointXYZRGBA>(origin, Allocator.TempJob); clear(); PointXYZRGBAs = Dense(temp); temp.Dispose(); return(true); } else { Debug.LogError("load failed as points count zero !"); } } else if (contains_i()) { size = load_as_xyzi(out IntPtr data_xyzi); if (size > (ulong)(int.MaxValue / sizeof(PointXYZI))) { Debug.LogError($"load failed as breached max points amount {int.MaxValue / sizeof(PointXYZI)} , this file have {size} points !"); } else if (size > (ulong)(int.MaxValue / sizeof(PCLPointXYZI))) { var origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZI>(data_xyzi.ToPointer(), int.MaxValue / sizeof(PCLPointXYZI), Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp_1 = new NativeArray <PCLPointXYZI>(origin, Allocator.TempJob); int remain = (int)size - temp_1.Length; origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZI>(IntPtr.Add(data_xyzi, remain * 32).ToPointer(), remain, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp_2 = new NativeArray <PCLPointXYZI>(origin, Allocator.TempJob); clear(); var densed_1 = Dense(temp_1); temp_1.Dispose(); var densed_2 = Dense(temp_2); temp_2.Dispose(); PointXYZIs = new NativeArray <PointXYZI>((int)size, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <PointXYZI> .Copy(densed_1, PointXYZIs, densed_1.Length); NativeArray <PointXYZI> .Copy(densed_2, 0, PointXYZIs, densed_1.Length, densed_2.Length); densed_1.Dispose(); densed_2.Dispose(); return(true); } else if (size > 0) { var origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZI>(data_xyzi.ToPointer(), (int)size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp = new NativeArray <PCLPointXYZI>(origin, Allocator.TempJob); clear(); PointXYZIs = Dense(temp); temp.Dispose(); return(true); } else { Debug.LogError("load failed as points count zero !"); } } else { size = load_as_xyz(out IntPtr data_xyz); if (size > (ulong)(int.MaxValue / sizeof(PointXYZRGBA))) { Debug.LogError($"load failed as breached max points amount {int.MaxValue / sizeof(PointXYZRGBA)} , this file have {size} points !"); } else if (size > 0) { var origin = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <PCLPointXYZ>(data_xyz.ToPointer(), (int)size, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref origin, AtomicSafetyHandle.GetTempMemoryHandle()); #endif var temp = new NativeArray <PCLPointXYZ>(origin, Allocator.TempJob); clear(); PointXYZRGBAs = Dense(temp); temp.Dispose(); return(true); } else { Debug.LogError("load failed as points count zero !"); } } } else { Debug.LogError("load failed as missing field xyz!"); } } } else { Debug.LogError("load failed as size_blob == 0"); } } else { Debug.LogError($"load failed as is_dense != 1"); } } else { Debug.LogError($"load failed as is_bigendian != 0"); } } else { Debug.LogError($"load failed with return {ret}"); } clear(); return(false); }
internal unsafe int ProcessPipelineSend(NetworkDriver.Concurrent driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection, NetworkInterfaceSendHandle sendHandle, int headerSize, NativeList <UpdatePipeline> currentUpdates) { int retval = sendHandle.size; NetworkPipelineContext ctx = default(NetworkPipelineContext); ctx.timestamp = m_timestamp[0]; var p = m_Pipelines[pipeline.Id - 1]; var connectionId = connection.m_NetworkId; var resumeQ = new NativeList <int>(16, Allocator.Temp); int resumeQStart = 0; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (headerSize != p.headerCapacity + UnsafeUtility.SizeOf <UdpCHeader>() + 1 && sendHandle.data != IntPtr.Zero) { throw new InvalidOperationException("Invalid header size."); } #endif var inboundBuffer = default(InboundSendBuffer); if (sendHandle.data != IntPtr.Zero) { inboundBuffer.bufferWithHeaders = (byte *)sendHandle.data + UnsafeUtility.SizeOf <UdpCHeader>() + 1; inboundBuffer.bufferWithHeadersLength = sendHandle.size - UnsafeUtility.SizeOf <UdpCHeader>() - 1; inboundBuffer.buffer = inboundBuffer.bufferWithHeaders + p.headerCapacity; inboundBuffer.bufferLength = inboundBuffer.bufferWithHeadersLength - p.headerCapacity; } while (true) { headerSize = p.headerCapacity; int internalBufferOffset = p.sendBufferOffset + sizePerConnection[SendSizeOffset] * connectionId; int internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId; bool needsUpdate = false; // If this is not the first stage we need to fast forward the buffer offset to the correct place if (startStage > 0) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (inboundBuffer.bufferWithHeadersLength > 0) { throw new InvalidOperationException("Can't start from a stage with a buffer"); } #endif for (int i = 0; i < startStage; ++i) { internalBufferOffset += (m_StageCollection[m_StageList[p.FirstStageIndex + i]].SendCapacity + AlignmentMinusOne) & (~AlignmentMinusOne); internalSharedBufferOffset += (m_StageCollection[m_StageList[p.FirstStageIndex + i]].SharedStateCapacity + AlignmentMinusOne) & (~AlignmentMinusOne); headerSize -= m_StageCollection[m_StageList[p.FirstStageIndex + i]].HeaderCapacity; } } for (int i = startStage; i < p.NumStages; ++i) { int stageHeaderCapacity = m_StageCollection[m_StageList[p.FirstStageIndex + i]].HeaderCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (stageHeaderCapacity > headerSize) { throw new InvalidOperationException("Not enough header space"); } #endif inboundBuffer.headerPadding = headerSize; headerSize -= stageHeaderCapacity; if (stageHeaderCapacity > 0 && inboundBuffer.bufferWithHeadersLength > 0) { var headerArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.bufferWithHeaders + headerSize, stageHeaderCapacity, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref headerArray, AtomicSafetyHandle.GetTempMemoryHandle()); #endif ctx.header = new DataStreamWriter(headerArray); } else { ctx.header = new DataStreamWriter(stageHeaderCapacity, Allocator.Temp); } var prevInbound = inboundBuffer; ProcessSendStage(i, internalBufferOffset, internalSharedBufferOffset, p, ref resumeQ, ref ctx, ref inboundBuffer, ref needsUpdate); if (needsUpdate) { AddSendUpdate(connection, i, pipeline, currentUpdates); } if (inboundBuffer.bufferWithHeadersLength == 0) { break; } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (inboundBuffer.headerPadding != prevInbound.headerPadding) { throw new InvalidOperationException("Changing the header padding in a pipeline is not supported"); } #endif if (inboundBuffer.buffer != prevInbound.buffer) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (inboundBuffer.buffer != inboundBuffer.bufferWithHeaders + inboundBuffer.headerPadding || inboundBuffer.bufferLength + inboundBuffer.headerPadding > inboundBuffer.bufferWithHeadersLength) { throw new InvalidOperationException("When creating an internal buffer in piplines the buffer must be a subset of the buffer width headers"); } #endif // Copy header to new buffer so it is part of the payload UnsafeUtility.MemCpy(inboundBuffer.bufferWithHeaders + headerSize, ctx.header.AsNativeArray().GetUnsafeReadOnlyPtr(), ctx.header.Length); } #if ENABLE_UNITY_COLLECTIONS_CHECKS else { if (inboundBuffer.bufferWithHeaders != prevInbound.bufferWithHeaders) { throw new InvalidOperationException("Changing the send buffer with headers without changing the buffer is not supported"); } } #endif if (ctx.header.Length < stageHeaderCapacity) { int wastedSpace = stageHeaderCapacity - ctx.header.Length; // Remove wasted space in the header UnsafeUtility.MemMove(inboundBuffer.buffer - wastedSpace, inboundBuffer.buffer, inboundBuffer.bufferLength); } // Update the inbound buffer for next iteration inboundBuffer.buffer = inboundBuffer.bufferWithHeaders + headerSize; inboundBuffer.bufferLength = ctx.header.Length + inboundBuffer.bufferLength; needsUpdate = false; internalBufferOffset += (ctx.internalProcessBufferLength + AlignmentMinusOne) & (~AlignmentMinusOne); internalSharedBufferOffset += (ctx.internalSharedProcessBufferLength + AlignmentMinusOne) & (~AlignmentMinusOne); } if (inboundBuffer.bufferLength != 0) { if (sendHandle.data != IntPtr.Zero && inboundBuffer.bufferWithHeaders == (byte *)sendHandle.data + UnsafeUtility.SizeOf <UdpCHeader>() + 1) { // Actually send the data - after collapsing it again if (inboundBuffer.buffer != inboundBuffer.bufferWithHeaders) { UnsafeUtility.MemMove(inboundBuffer.bufferWithHeaders, inboundBuffer.buffer, inboundBuffer.bufferLength); inboundBuffer.buffer = inboundBuffer.bufferWithHeaders; } ((byte *)sendHandle.data)[UnsafeUtility.SizeOf <UdpCHeader>()] = (byte)pipeline.Id; int sendSize = UnsafeUtility.SizeOf <UdpCHeader>() + 1 + inboundBuffer.bufferLength; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (sendSize > sendHandle.size) { throw new InvalidOperationException("Pipeline increased the data in the buffer, this is not allowed"); } #endif sendHandle.size = sendSize; retval = driver.CompleteSend(connection, sendHandle); sendHandle = default; } else { // Sending without pipeline, the correct pipeline will be added by the default flags when this is called var writer = driver.BeginSend(connection); writer.WriteByte((byte)pipeline.Id); writer.WriteBytes(inboundBuffer.buffer, inboundBuffer.bufferLength); if (writer.HasFailedWrites) { driver.AbortSend(writer); } else { driver.EndSend(writer); } } } if (resumeQStart >= resumeQ.Length) { break; } startStage = resumeQ[resumeQStart++]; inboundBuffer = default(InboundSendBuffer); } if (sendHandle.data != IntPtr.Zero) { driver.AbortSend(sendHandle); } return(retval); }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var fragContext = (FragContext *)ctx.internalProcessBuffer; var dataBuffer = ctx.internalProcessBuffer + sizeof(FragContext); var param = (FragmentationUtility.Parameters *)ctx.staticInstanceBuffer; var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); var combined = reader.ReadShort(); var foundSequence = combined & (int)FragFlags.SeqMask; var flags = (FragFlags)combined & ~FragFlags.SeqMask; inboundBuffer = inboundBuffer.Slice(FragHeaderCapacity); var expectedSequence = fragContext->sequence; var isFirst = 0 != (flags & FragFlags.First); var isLast = 0 != (flags & FragFlags.Last); if (isFirst) { expectedSequence = foundSequence; fragContext->packetError = false; fragContext->endIndex = 0; } if (foundSequence != expectedSequence) { // We've missed a packet. fragContext->packetError = true; fragContext->endIndex = 0; // Discard data we have already collected } if (!fragContext->packetError) { if (!isLast || fragContext->endIndex > 0) { if (fragContext->endIndex + inboundBuffer.bufferLength > param->PayloadCapacity) { throw new InvalidOperationException($"Fragmentation capacity exceeded"); } // Append the data to the end UnsafeUtility.MemCpy(dataBuffer + fragContext->endIndex, inboundBuffer.buffer, inboundBuffer.bufferLength); fragContext->endIndex += inboundBuffer.bufferLength; } if (isLast && fragContext->endIndex > 0) { // Data is complete inboundBuffer = new InboundRecvBuffer { buffer = dataBuffer, bufferLength = fragContext->endIndex }; } } if (!isLast || fragContext->packetError) { // No output if we expect more data, or if data is incomplete due to packet loss inboundBuffer = default; } fragContext->sequence = (foundSequence + 1) & (int)FragFlags.SeqMask; }