简体   繁体   English

C#(Unity)不同托管数组类型之间的快速复制

[英]C# (Unity) Quick copy between different managed array types

I have a byte[] of colors that I need to transfer to Texture2D object via SetPixels(Color32[]) . 我有一个byte[]颜色,我需要通过SetPixels(Color32[])传输到Texture2D对象。 I want to know what the fastest way to create the Color32[] from the byte[] is. 我想知道从byte[]创建Color32[]的最快方法是什么。 Since each Color32 is 4 bytes (1 byte per channel), there would be one quarter the number of elements. 由于每个Color32是4个字节(每个通道1个字节),因此将有四分之一的元素。

Array.CopyTo doesn't allow different object array types. Array.CopyTo不允许不同的对象数组类型。

From what I read, it seems like managed code can't reinterpret the byte[] as Color32[] and skip the copy altogether. 从我读到的,似乎托管代码不能将byte[]重新解释为Color32[]并完全跳过副本。

The reverse of this ( Color32[] -> byte[] ) has a SO solution via marshalling, but there seems to be a ton of copying involved. 与此相反( Color32[] - > byte[] )通过编组有一个SO解决方案 ,但似乎涉及大量复制。

private static byte[] Color32ArrayToByteArray(Color32[] colors)
{
int length = 4 * colors.Length;
byte[] bytes = new byte[length];
IntPtr ptr = Marshal.AllocHGlobal(length); // unmanaged memory alloc
Marshal.StructureToPtr(colors, ptr, true); // memcpy 1
Marshal.Copy(ptr, bytes, 0, length); // memcpy 2
Marshal.FreeHGlobal(ptr);
return bytes;
}

For my case, I'm using: 对于我的情况,我正在使用:

 int length = bytes.Length;
 IntPtr ptr = Marshal.AllocHGlobal(length); // unmanaged mem alloc
 Marshal.Copy(bytes, 0, ptr, length); // memcpy 1
 Marshal.PtrToStructure(ptr, colors); // memcpy 2
 Marshal.FreeHGlobal(ptr);

However, I don't see the texture updating after doing myTexture.SetPixels(colors) . 但是,在执行myTexture.SetPixels(colors)后,我没有看到纹理更新。 Still trying to figure out why. 还在试图找出原因。

Regardless, do I have to do 2 mem copies to accomplish this in C#? 无论如何,我必须做2份内存副本才能在C#中实现这一目标吗? Seems like such a waste.. I was looking at unions in C# to get around the copies. 看起来像这样的浪费..我正在看C#中的工会来绕过副本。

Here's what I learned: 这是我学到的:

1) There is no need to Marshal b/w managed and unmanaged memory to convert byte[] to Color32[] and vice versa. 1)没有必要使用b / w托管和非托管内存来将byte []转换为Color32 [],反之亦然。 Instead, use a union in C#: 相反,在C#中使用union:

[StructLayout(LayoutKind.Explicit)]
public struct Color32Bytes
{
    [FieldOffset(0)]
    public byte[] byteArray;

    [FieldOffset(0)]
    public Color32[] colors;
}

Color32Bytes data = new Color32Bytes();
data.byteArray = new byte[width * height * bytesPerPixel];
data.colors = new Color32[width * height];

Now, if you update the byteArray with data from a camera, you can apply it to the Texture2D using myTexture.SetPixels(data.colors) ; 现在,如果使用来自摄像头的数据更新byteArray,则可以使用myTexture.SetPixels(data.colors)将其应用于Texture2D ;

No copying involved. 不涉及复制。

2) No need for the union solution above. 2)不需要上面的联合解决方案。 Haha. 哈哈。 As NineBerry pointed out, you can just upload a raw byte buffer to a texture via myTexture.LoadRawTextureData(bytes); 正如NineBerry指出的那样,你可以通过myTexture.LoadRawTextureData(bytes);将原始字节缓冲区上传到纹理myTexture.LoadRawTextureData(bytes);

This is perfect in my case, since my camera bytebuffer comes as BGRA (low to high) and I'd need to swizzle the channels before upload (expensive) OR solve it in my shader if i went with (1) 这在我的情况下是完美的,因为我的相机字节缓冲来自BGRA(从低到高)并且我需要在上传之前调整频道(昂贵)或者如果我一起去(1)我在着色器中解决它

3) The SetPixels method in Unity can be expensive on low end systems. 3)Unity中的SetPixels方法在低端系统上可能很昂贵。 I haven't dug deeper, but I suspect it's because the D3D textures created under the hood use D3D_USAGE_DEFAULT , which means updating them has to use UpdateSubresource which incurs a driver copy and possible stall (can't update a resource currently in use by the GPU). 我没有深入挖掘,但我怀疑这是因为在引擎盖下创建的D3D纹理使用D3D_USAGE_DEFAULT ,这意味着更新它们必须使用UpdateSubresource ,它会导致驱动程序副本和可能的停顿(无法更新当前正在使用的资源) GPU)。

So, the ideal solution is to write a native plugin that creates a 2D texture with D3D_USAGE_DYNAMIC, maps-updates-unmaps it, and pass that reference back to Unity. 因此,理想的解决方案是编写一个本机插件,使用D3D_USAGE_DYNAMIC创建2D纹理,map-updates-unmaps,并将该引用传递回Unity。 Overkill for now, but I might revisit this later. 现在有点矫枉过正,但我​​可能会在稍后重新审视。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM