예제 #1
0
        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;
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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
        }
예제 #7
0
        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);
        }
예제 #8
0
                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;
        }
예제 #11
0
        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);
        }
예제 #12
0
            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);
            }
예제 #13
0
        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;
        }