I'm writing a Unity plugin which uses WPF for UI , Plugin runs in same process of Unity and has direct access to unity's memory.
Unity Code :
render_rt_desc = new RenderTextureDescriptor(300, 300, RenderTextureFormat.BGRA32);
render_rt = new RenderTexture(render_rt_desc);
rendering_camera.targetTexture = render_rt;
rendering_camera.Render();
render_pointer = t2d_format.GetNativeTexturePtr();
if (WPFWindow.IsWindowValid)
{
WPFWindow.UpdateImagePointer(render_pointer);
}
Now in my wpf app I get the texture pointer and properties are right, it has B8G8R8A8_Typeless format with ShaderResource and RenderTarget bind flags and I write it to file and it's fine.
To show it in WPF I need this texture be OptionFlags.Shared
So i tried to copy it like this (using https://github.com/Marlamin/SharpDX.WPF ) :
Device wpfdevice = new Device(SharpDX.Direct3D.DriverType.Hardware,DeviceCreationFlags.BgraSupport);
Texture2D dx11t2D = CppObject.FromPointer<Texture2D>(Dx11Textureptr); /// pointer from unity
Texture2DDescription texture2DDescription = dx11t2D.Description;
texture2DDescription.OptionFlags = ResourceOptionFlags.Shared;
texture2DDescription.BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget;
texture2DDescription.Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm;
Texture2D sharedt2d = new Texture2D(wpfdevice, texture2DDescription);
Device d3d11device = dx11t2D.QueryInterface<DeviceChild>().Device;
d3d11device.ImmediateContext.CopyResource(dx11t2D, sharedt2d);
DXImageSource dXImageSource = new DXImageSource();
dXImageSource.Lock();
dx_output.Source = dXImageSource;
dXImageSource.SetBackBuffer(sharedt2d);
dXImageSource.Unlock();
Result is black but it throws no error using SharpDX.WPF.
I found new wpf directx 11 D3DImage from Microsoft can be find here : https://github.com/microsoft/WPFDXInterop
WPF Global Objects :
IntPtr _resourcePointer;
SharpDX.Direct3D11.Device _device;
SwapChain _swapChain;
RenderTargetView _renderTargetView;
WPF Startup Code :
var _swapChainDescription = new SwapChainDescription();
_swapChainDescription.OutputHandle = new WindowInteropHelper(this).Handle;
_swapChainDescription.BufferCount = 1;
_swapChainDescription.Flags = SwapChainFlags.AllowModeSwitch;
_swapChainDescription.IsWindowed = true;
_swapChainDescription.ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.B8G8R8A8_UNorm);
_swapChainDescription.SampleDescription = new SampleDescription(1, 0);
_swapChainDescription.SwapEffect = SwapEffect.Discard;
_swapChainDescription.Usage = Usage.RenderTargetOutput | Usage.Shared;
var flags = DeviceCreationFlags.BgraSupport;
Device.CreateWithSwapChain(SharpDX.Direct3D.DriverType.Hardware,
flags, _swapChainDescription, out _device, out _swapChain);
InteropImage.SetPixelSize(300, 300);
InteropImage.WindowOwner = new WindowInteropHelper(this).Handle;
InteropImage.OnRender = this.xRENDER;
InteropImage.RequestRender();
dx_output.Source = InteropImage;
DoRender
Function Code :
void DoRender(IntPtr resourcePointer)
{
if (_resourcePointer != resourcePointer)
{
if (_resourcePointer != IntPtr.Zero)
{
_renderTargetView.Dispose();
_renderTargetView = null;
}
_resourcePointer = resourcePointer;
}
else
{
var texture = _renderTargetView.ResourceAs<SharpDX.Direct3D11.Texture2D>();
if (texture.Description.Width != (int)this.ActualWidth || texture.Description.Height != (int)this.ActualHeight)
{
_renderTargetView.Dispose();
_renderTargetView = null;
}
}
if (_renderTargetView == null)
{
SharpDX.DXGI.Resource dxgiResource;
using (var r = new SharpDX.ComObject(resourcePointer))
{
dxgiResource = r.QueryInterface<SharpDX.DXGI.Resource>();
}
var directx11Texture = _device.OpenSharedResource<Texture2D>(dxgiResource.SharedHandle);
_renderTargetView = new RenderTargetView(_device, directx11Texture);
}
_device.ImmediateContext.Rasterizer.SetViewport(0, 0, (float)this.ActualWidth, (float)this.ActualHeight, 0.0f, 1.0f);
_device.ImmediateContext.OutputMerger.SetRenderTargets(_renderTargetView);
_device.ImmediateContext.ClearRenderTargetView(_renderTargetView, new SharpDX.Color4(0.7f, 0.5f, 0.2f, 1.0f));
_device.ImmediateContext.Flush();
}
This code works fine but I have no idea how can I use my unity render texture to place in DoRender function without any copying or extra steps.
Performance is very important to me, I don't want to leave extra memory blocks or footprints.