Rendering to a texture from a plugin (D3D11)

I’m using D3D11 on a Windows 7 desktop platform to render to a texture that I want to apply to a quad in my scene. I have everything connected and I can debug the native C++ plugin and step through all of the lines with no errors.

Right now, all I’m doing is clearing the texture, I’m not rendering to it. But no matter what colour I clear it to, it always ends up being black. Here are the steps I’m using:

      D3D11RenderTargetViewPtr  pCurrentRenderTarget;
      D3D11DepthStencilViewPtr  pCurrentDepthStencil;

      // Get the current render targets
      pD3D11DC->OMGetRenderTargets(1, &pCurrentRenderTarget, &pCurrentDepthStencil);

      pD3D11DC->OMSetRenderTargets(1, &g_pD3D11RenderTargetView, nullptr);

      const float CLEAR_CLR[4] = { 1, 1, 0, 1 };

      pD3D11DC->ClearRenderTargetView(g_pD3D11RenderTargetView, CLEAR_CLR);

      // Restore the original rendertarget
      pD3D11DC->OMSetRenderTargets(1, &(pCurrentRenderTarget.p), pCurrentDepthStencil);

I have my Unity material on the quad setup as Unlit/Texture. I have also tried Unlit/Transparent, but if I do that, I don’t get anything. I’m assuming that the texture is fully transparent which is why I can’t see it in that case.

The texture is created in Unity like this:

    m_Texture = new RenderTexture(1600, 900, 0, RenderTextureFormat.ARGB32);

    m_Texture.filterMode = FilterMode.Point;
    m_Texture.Create();

I then pass the texture to my plugin:

U_EXPORT void SetTexturePtr(void* pTexture)
{
  Log(L"Setting texture pointer\n");

  switch (g_iGfxDeviceType)
  {
    case GFXRENDERER_D3D11:
      g_pD3D11RenderTexture = reinterpret_cast<D3D11TexPtr>(pTexture);

      if (nullptr != g_pD3D11Device && nullptr != g_pD3D11RenderTexture )
      {
        D3D11_TEXTURE2D_DESC texDesc = { 0 };

        // Get the format of the texture
        g_pD3D11RenderTexture ->GetDesc(&texDesc);

        D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = { texDesc.Format };
        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;

        // Create the render target view for the texture
        g_pD3D11Device->CreateRenderTargetView
        (
          g_pD3D11RenderTexture ,
          &rtvDesc,
          &g_pD3D11RenderTargetView
        );
      }
      break;
  }
}

I’m sure I’m missing something, but I can’t seem to find it. If you have any suggestions, I would love to hear them.

Thanks

I am having a similar issue. If you found a solution, I would be interested in knowing what it was.

I reimplemented the problem from the unity Native Plugin Example and added these changes and I also only get a black texture.
https://github.com/bwrsandman/Unity-DX11-Native-Plugin-Texture-Clear

Maybe there is a special way to use ctx->OMSetRenderTargets ?

The issue was with which version of the DirectX SDK we were using to build the plugin. I am assuming that the version Unity uses when they build their engine is probably fully up to date with things like Windows 8 and 10. This means that you will need to be using the DX stuff from the Windows 8 SDK (or later) as they don’t ship a separate install for the DirectX SDK any more.

In our case, once we switched the rendering to use DX9 it all worked just fine as that SDK hasn’t changed in many years. The DX SDK we had on hand was the June 2010 version. If you try to use that version to build and link a plugin that uses D3D10/11 stuff, it may run initially, but some odd behaviour will eventually show up. Crashing/freezing is likely too.

Unfortunately, I couldn’t find a reference saying what version of the DirectX stuff you should be using according which version of Unity you are using. I was using 4.6 at the time.

Hi
I tested bwrsandman’s code on win7 64bit and win10 32bit Pc. Same result.

HRESULT hr = g_D3D11Device->CreateRenderTargetView
                (
                    g_TexturePointer,
                    &rtvDesc,
                    &g_pD3D11RenderTargetView
                    );

after this line.
HRESULT Fail
return g_pD3D11RenderTargetView => NULL

I have tried everything.
I could not find the problem

2670043--188396--Noname.png

Hi.
I’m also having problems with rendering to texture from native plugin.
Is there anyone who succeeded with this?

I found the reason texture unity createed is of format DXGI_FORMAT_R8G8B8A8_TYPELESS, which can not be used as render target. Normally, It should be DXGI_FORMAT_R32G32B32A32_FLOAT

And finally I found a solution. create a render texture with DXGI_FORMAT_R32G32B32A32_FLOAT, and when the rendering is done, we can copy the resouce to unity texture ( format is **_TYPELESS), because they are in same group,
It works… ctx->CopyResource(g_TexturePointer, g_renderTargetTexture);

To save everyone some time after struggling with this for a while, you can use a command buffer to set the render target to a render texture and then call the plugin event.

private IEnumerator CallPluginEachFrame()
    {
        RenderTargetIdentifier rti = new(renderTexture);
        CommandBuffer cb = new();

        while (true)
        {
            yield return null;

            cb.SetRenderTarget(rti);

            cb.IssuePluginEvent(
                GetRenderEventFunc(),
                -1
            );

            Graphics.ExecuteCommandBuffer(cb);
            cb.Clear();
         
        }
    }
1 Like