Sometimes, you want to share a Texture that you have created in one application to another application on the same machine. When performance is important, the DirectX Texture Sharing feature should be interesting for you. It let’s you share a DirectX texture between multiple processes – for example, if you want to make a Texture that you have created in Unity available to another program or, vice versa, when you want to use an externally created texture inside Unity. The Texture Sharing feature lets you access the texture with zero latency, instantaneously – nice!
In this tutorial, I will just very briefly explain how to get your external created DirectX texture into Unity using the SharpDX library. However, I will only describe the part on the Unity side; the DirectX-part (the texture creation etc.) will not be covered in this.
Importing SharpDX into your Unity project
SharpDX is a library that acts as a C# wrapper for DirectX. Since Unity does not allow easily to call DirectX native functions, we need to import this library into Unity. This is easiest if you download the SharpDX DLLs via Visual Studio’s NuGet functionality: Just open the Visual Studio Solution for your Unity project and download the SharpDX NuGet packages you need (in my case, this was the SharpDX package and the SharpDX Direct3D11 package). You can download the packages via NuGet: https://www.nuget.org/packages/SharpDX
Now, inside your project find the DLLs from the NuGet packages (e.g. in Packages\SharpDX.Direct3D11.4.2.0\lib\net45) and copy them into the Plugins folder of your Unity Assets. After a restart, you should be able to now import SharpDX and call the respective functions.
But first, I had to receive the pointer to the shared texture and initialize it inside Unity:
private IntPtr mlabTextureHandle = IntPtr.Zero;
private void GetImageFromDX11TextureSharing(byte[] data)
{
if (texSharingInitiated)
return;
var intptrstr = System.Text.Encoding.UTF8.GetString(data);
long intptr;
if (long.TryParse(intptrstr, out intptr))
{
mlabTextureHandle = new IntPtr(intptr);
shouldUpdateMlabTextureRef = true;
FlipCameraTexture(true);
}
else
throw new FormatException("Shared texture pointer has not the right format");
}
Accessing the shared texture inside Unity
The tricky part is now that Unity tries to hide the DirectX device to you, but you need it for the proper communication with your graphics card. Therefore, I had to find a kind of „hack“ to get the device Unity is using (see code). Once you have the device, you can call your DirectX functions as usual. In this case, you have to call OpenSharedResource
and create a new ShaderResourceView
on the shared texture. Then you just have to call Unity’s CreateExternalTexture
function, passing the native pointer to your ShaderResourceView
of your shared texture. That’s it!
Please mind that the Texture you are creating inside Unity of course has to match the Type, width and height of the shared texture you want to access.
private void UpdateMlabTextureRef()
{
if (texSharingInitiated)
return;
if (mlabTextureHandle == IntPtr.Zero || mlabTextureHandle == null)
throw new ArgumentNullException("DX11SharedTextureHandle");
// Hack into Unity's D3D device
var castedTex = new SharpDX.Direct3D11.Texture2D(texture.GetNativeTexturePtr());
var deviceChild = castedTex.QueryInterface<SharpDX.Direct3D11.DeviceChild>();
var d3d11device = deviceChild.Device;
// Get Shader Resource View to shared texture
var d3d11tex = d3d11device.OpenSharedResource<SharpDX.Direct3D11.Texture2D>(mlabTextureHandle);
var d3d11srv = new SharpDX.Direct3D11.ShaderResourceView(d3d11device, d3d11tex);
// Create texture in Unity context
var unityTex = Texture2D.CreateExternalTexture((int)renderWidth * 2,
(int)renderHeight,
TextureFormat.RGBA32,
false,
true,
d3d11srv.NativePointer);
leftEyeImage.texture = unityTex;
rightEyeImage.texture = unityTex;
ConsoleDispatcher.Print("Successfully established DirectX texture sharing with MeVisLab");
texSharingInitiated = true;
}
This was tested using Windows 10 64Bit, SharpDX 4.2.0, Visual Studio 2017 and Unity 2018.3.5.
Can you include the Unity Project for your example code snippets?
I can access a SharpDX.Direct3D11.Texture2D from a Unity RTHandle. I can update the SharpDX.Direct3D11.Texture2D using OpenCL, but I can’t find a way to push my modified texture back into Unity. I’m using Unity HDRP CustomPass to add my behavior into Unity.
Please send me an email, and I’ll send you the project.
Please send me an email, and I’ll send you the project.
Thanks for share and I hpoe you can send me the project too.
This is my email:zhxmdefj@outlook.com.
Thanks a lot.