internal unsafe void ReadArray <T>(long position, T[] buffer, int index, int count) where T : struct { uint elementSize = (uint)FastStructure.SizeOf <T>(); if (buffer == null) { throw new ArgumentNullException("buffer"); } if (position > this._view.Size - (elementSize * count)) { throw new ArgumentOutOfRangeException("position"); } try { byte *ptr = null; _view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); ptr += _view.ViewStartOffset + position; FastStructure.ReadArray <T>(buffer, (IntPtr)ptr, index, count); //for (var i = 0; i < count; i++) //{ // PtrToStructure(ptr + (i * elementSize), out buffer[index + i]); //} } finally { _view.SafeMemoryMappedViewHandle.ReleasePointer(); } }
public virtual void SimpleImageCaptureLoop() { using (var consumer = new CircularBuffer(name: "MySharedMemory", nodeCount: 4, nodeBufferSize: ((8294400 + FastStructure <MetaDataStruct> .Size)) * 2)) // Should be large enough to store 2 full hd raw image data + 4 Size of Struct { Stopwatch stopwatch = new Stopwatch(); do { stopwatch.Reset(); stopwatch.Start(); try { consumer.Read(intPtr => { MetaDataStruct metaData = FastStructure.PtrToStructure <MetaDataStruct>(intPtr); if (metaData.length > 0) { byte[] byteArray = new byte[metaData.length]; FastStructure.ReadArray <byte>(byteArray, intPtr, 0, byteArray.Length); using (var bm = byteArray.ToBitmap(metaData.width, metaData.height, metaData.pitch, metaData.format)) { byte[] compressedJpgByteArray = bm.ToByteCompessedArray(); Bitmap bitmap = compressedJpgByteArray.ToBitmap(); pictureBox1.Invoke(new MethodInvoker(delegate() { if (pictureBox1.Image != null) { pictureBox1.Image.Dispose(); } pictureBox1.Image = bitmap; })); } } return(0); }, timeout: MAX_SLEEP_TIME); } catch (TimeoutException exception) { Console.WriteLine(exception); } catch (Exception ex) { Console.WriteLine(ex); } int timeout = (int)(MAX_SLEEP_TIME - stopwatch.ElapsedMilliseconds); Thread.Sleep(timeout >= 0 ? timeout : 0); } while (true); } }
/// <summary> /// Fill the buffer from the source memory location and mark dirty /// </summary> /// <param name="ptr">The source memory location</param> /// <param name="index">The start index within this buffer</param> /// <param name="count">The number of elements to read</param> public void CopyFrom(IntPtr src, int index, int count) { if (Offset > 0) { throw new NotImplementedException( "Cannot CopyFrom into a subarray" ); } if (index + count > Length) { throw new OverflowException( $"index({index}) + count({count}) is larger than Length({Length})" ); } FastStructure.ReadArray(data, src, index, count); Dirty(index, index + count - 1); }
/// <summary> /// Consume a single message off the interop message queue /// </summary> /// <returns>Number of bytes read</returns> private int ConsumeMessage() { var disconnected = false; var bytesRead = messages.Read((target, header, ptr) => { // While not connected - only accept connection requests if (!IsConnected) { if (header.type != RpcRequest.Connect) { Debug.LogWarning($"Unhandled request type {header.type} for {target} - expected RpcRequest.Connect"); } blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr); OnConnectToBlender(); return(0); } switch (header.type) { case RpcRequest.UpdateBlenderState: blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr); break; case RpcRequest.Disconnect: // Don't call OnDisconnectFromBlender() from within // the read handler - we want to release the read node // safely first before disposing the connection. disconnected = true; break; // Viewport messages case RpcRequest.AddViewport: AddViewport( target, FastStructure.PtrToStructure <InteropViewport>(ptr) ); break; case RpcRequest.RemoveViewport: RemoveViewport(target); break; case RpcRequest.UpdateViewport: GetViewport(target).UpdateFromInterop( FastStructure.PtrToStructure <InteropViewport>(ptr) ); break; case RpcRequest.UpdateVisibleObjects: var visibleObjectIds = new int[header.count]; FastStructure.ReadArray(visibleObjectIds, ptr, 0, header.count); GetViewport(target).SetVisibleObjects( visibleObjectIds ); break; // Object messages case RpcRequest.AddObjectToScene: AddObject( target, FastStructure.PtrToStructure <InteropSceneObject>(ptr) ); break; case RpcRequest.RemoveObjectFromScene: RemoveObject(target); break; case RpcRequest.UpdateSceneObject: UpdateObject( target, FastStructure.PtrToStructure <InteropSceneObject>(ptr) ); break; // Mesh messages case RpcRequest.UpdateTriangles: GetOrCreateMesh(target) .triangles .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateVertices: GetOrCreateMesh(target) .vertices .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateNormals: GetOrCreateMesh(target) .normals .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateUV: GetOrCreateMesh(target) .uv .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateUV2: GetOrCreateMesh(target) .uv2 .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateUV3: GetOrCreateMesh(target) .uv3 .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateUV4: GetOrCreateMesh(target) .uv4 .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; case RpcRequest.UpdateVertexColors: GetOrCreateMesh(target) .colors .Resize(header.length) .CopyFrom(ptr, header.index, header.count); break; // TODO: ... and so on for weights/bones/etc case RpcRequest.UpdateMesh: GetOrCreateMesh(target).UpdateFromInterop( FastStructure.PtrToStructure <InteropMesh>(ptr) ); break; // Texture messages case RpcRequest.UpdateTexture: GetTexture(target).UpdateFromInterop( FastStructure.PtrToStructure <InteropTexture>(ptr) ); break; case RpcRequest.UpdateTextureData: GetTexture(target).CopyFrom( ptr, header.index, header.count, header.length ); break; default: Debug.LogWarning($"Unhandled request type {header.type} for {target}"); break; } // TODO: Necessary to count bytes? We won't read anything off this // buffer at this point so it's safe to drop the whole thing. // bytesRead will count the header size (indicating a message *was* read) return(0); }); // Handle any disconnects that may have occured during the read if (disconnected) { OnDisconnectFromBlender(); } return(bytesRead); }
/// <summary> /// Handle any messages coming from Blender /// </summary> private void ConsumeMessages() { Profiler.BeginSample("Consume Message"); var disconnected = false; // TODO: Some messages should be skipped if !IsConnected. // Otherwise we may get a bad state. E.g. we see a disconnect // from Blender and THEN some other viewport/object data messages. messages.Read((target, header, ptr) => { ObjectController obj; switch (header.type) { case RpcRequest.Connect: blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr); OnConnectToBlender(); break; case RpcRequest.UpdateBlenderState: blenderState = FastStructure.PtrToStructure <InteropBlenderState>(ptr); break; case RpcRequest.Disconnect: // Don't call OnDisconnectFromBlender() from within // the read handler - we want to release the read node // safely first before disposing the connection. disconnected = true; break; case RpcRequest.AddViewport: AddViewport( target, FastStructure.PtrToStructure <InteropViewport>(ptr) ); break; case RpcRequest.RemoveViewport: RemoveViewport(target); break; case RpcRequest.UpdateViewport: GetViewport(target).UpdateFromInterop( FastStructure.PtrToStructure <InteropViewport>(ptr) ); break; case RpcRequest.UpdateVisibleObjects: var visibleObjectIds = new int[header.count]; FastStructure.ReadArray(visibleObjectIds, ptr, 0, header.count); GetViewport(target).SetVisibleObjects( visibleObjectIds ); break; case RpcRequest.AddObjectToScene: AddObject( target, FastStructure.PtrToStructure <InteropSceneObject>(ptr) ); break; case RpcRequest.RemoveObjectFromScene: RemoveObject(target); break; case RpcRequest.UpdateSceneObject: GetObject(target).UpdateFromInterop( FastStructure.PtrToStructure <InteropSceneObject>(ptr) ); break; case RpcRequest.UpdateTriangles: obj = GetObject(target); FastStructure.ReadArray(obj.GetOrCreateTriangleBuffer(), ptr, header.index, header.count); obj.OnUpdateTriangleRange(header.index, header.count); break; case RpcRequest.UpdateVertices: obj = GetObject(target); FastStructure.ReadArray(obj.GetOrCreateVertexBuffer(), ptr, header.index, header.count); obj.OnUpdateVertexRange(header.index, header.count); break; case RpcRequest.UpdateNormals: obj = GetObject(target); FastStructure.ReadArray(obj.GetOrCreateNormalBuffer(), ptr, header.index, header.count); obj.OnUpdateNormalRange(header.index, header.count); break; // TODO: ... and so on for UV/weights default: Debug.LogWarning($"Unhandled request type {header.type} for {target}"); break; } // TODO: Necessary to count bytes? We won't read anything off this // buffer at this point so it's safe to drop the whole thing. return(0); }); // Handle any disconnects that may have occured during the read if (disconnected) { OnDisconnectFromBlender(); } Profiler.EndSample(); }