/// <summary> /// Copy the RenderTexture data from the ViewportController into shared memory with Blender. /// /// <para> /// The <paramref name="pixelsRGB24Func"/> callback is executed IFF we have room in the /// buffer to write - letting us skip the heavy pixel copy operations if the consumer /// is backed up in processing data. /// </para> /// </summary> internal void PublishRenderTexture(ViewportController viewport, Func <byte[]> pixelsRGB24Func) { if (!IsConnected) { Debug.LogWarning("Cannot send RT - No connection"); } Profiler.BeginSample("Write wait on pixelsProducer"); int bytesWritten = pixelsProducer.Write((ptr) => { // If we have a node we can write on, actually do the heavy lifting // of pulling the pixel data from the RenderTexture (in the callback) // and write into the buffer. var pixelsRGB24 = pixelsRGB24Func(); Profiler.BeginSample("Write Pixels into Shared Memory"); // Pack a header into shared memory var header = new InteropRenderHeader { viewportId = viewport.ID, width = viewport.Width, height = viewport.Height }; var headerSize = FastStructure.SizeOf <InteropRenderHeader>(); FastStructure.WriteBytes(ptr, FastStructure.ToBytes(ref header), 0, headerSize); // Copy render image data into shared memory FastStructure.WriteBytes(ptr + headerSize, pixelsRGB24, 0, pixelsRGB24.Length); /*InteropLogger.Debug($"Writing {pixelsRGB24.Length} bytes with meta {header.width} x {header.height} and pix 0 is " + * $"{pixelsRGB24[0]}, {pixelsRGB24[1]}, {pixelsRGB24[2]}" * );*/ Profiler.EndSample(); return(headerSize + pixelsRGB24.Length); }, WRITE_WAIT); /* * if (bytesWritten < 1) * { * Debug.LogWarning("pixelsProducer buffer is backed up. Skipped write."); * }*/ Profiler.EndSample(); }
/// <summary> /// Write <paramref name="message"/> into the next available /// node's buffer at <paramref name="ptr"/>. /// </summary> /// <param name="message"></param> /// <param name="ptr"></param> /// <returns></returns> private int WriteMessage(InteropMessage message, IntPtr ptr) { int bytesWritten = 0; // Write the target name (varying length string) byte[] target = Encoding.UTF8.GetBytes(message.target); int targetLen = target.Length; FastStructure.StructureToPtr(ref targetLen, ptr + bytesWritten); bytesWritten += FastStructure.SizeOf <int>(); if (targetLen > 0) { FastStructure.WriteBytes(ptr + bytesWritten, target, 0, targetLen); bytesWritten += targetLen; } // Write the message header var headerSize = FastStructure.SizeOf <InteropMessageHeader>(); var header = message.header; FastStructure.StructureToPtr(ref header, ptr + bytesWritten); bytesWritten += headerSize; // If there's a custom producer, execute it for writing the payload if (message.producer != null) { bytesWritten += message.producer(message.target, header, ptr + bytesWritten); } // If there's a payload included with the message, copy it if (message.payload != null) { FastStructure.WriteBytes(ptr + bytesWritten, message.payload, 0, message.payload.Length); bytesWritten += message.payload.Length; } // InteropLogger.Debug($"Produce {bytesWritten} bytes - {header.type} for `{message.target}`"); return(bytesWritten); }