Unity Native Texture Create/Release causes GPU suspension

Hello!

I have an issue with textures created natively in the native c++ plugin and being passed to Unity causing the GPU to suspend and unity to freeze. The code I use is below.

Creating the Native Texture, Setting it on the Texture2D, Destroying the GameObject, then Creating a New Native texture etc, rapidly, causes the program to freeze and I dont see any reason why.

I caught an error from the HRESULT at one point that said “0x887a0005: The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.”

The c++ native function for creating texture

void* RenderAPI_D3D11::CreateNewTexture(int textureWidth, int textureHeight)
{
    ID3D11Texture2D* m_renderTargetTexture;
    //ID3D11RenderTargetView* m_renderTargetView;
    ID3D11ShaderResourceView* m_shaderResourceView;

    HRESULT result;

    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
    //D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
    D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
    ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
   
    desc.Width = textureWidth;
    desc.Height = textureHeight;
    desc.MipLevels = desc.ArraySize = 1;
    desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    desc.SampleDesc.Count = 1;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.MiscFlags = 0;
    HRESULT res1 = m_Device->CreateTexture2D(&desc, NULL, &m_renderTargetTexture);

    if (FAILED(res1))
    {
        OutputDebugStringW(L"Failed to create Texture2D");
        return nullptr;
    }
   
    // Setup the description of the shader resource view.
    shaderResourceViewDesc.Format = desc.Format;
    shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
    shaderResourceViewDesc.Texture2D.MipLevels = 1;
    // Create the shader resource view.
    HRESULT res2 = m_Device->CreateShaderResourceView(m_renderTargetTexture, &shaderResourceViewDesc, &m_shaderResourceView);

    if (FAILED(res2))
    {
        m_renderTargetTexture->Release();
        OutputDebugStringW(L"Failed to Create Shader Resource View");
        return nullptr;
    }

    return m_shaderResourceView;
}

The c++ function for releasing native texture and shader resource view

// Removing texture
        ID3D11Texture2D* texture = (ID3D11Texture2D*)winText->g_TextureHandle;

        if (texture != nullptr)
            texture->Release();

        ID3D11ShaderResourceView* shaderResource = (ID3D11ShaderResourceView*)winText->g_ShaderHandle;
        if (shaderResource != nullptr)
            shaderResource->Release();

The unity C# code the creates the texture natively then uses Texture2D.CreateExternalTexture

IntPtr shaderIndex = CreateNativeTexture(renderData.textureIndex, renderData.resolutionX, renderData.resolutionY);
        if (shaderIndex == null)
            return;
        windowTexture = Texture2D.CreateExternalTexture(renderData.resolutionX, renderData.resolutionY, TextureFormat.BGRA32, false, false, shaderIndex);
      
        windowTexture.filterMode = FilterMode.Bilinear;

        Renderer renderer = GetComponent<Renderer>();
        // Set texture onto our material
        renderer.material.mainTexture = windowTexture;
      
        SetTextureFromUnity(renderData.textureIndex, windowTexture.GetNativeTexturePtr(), renderData.resolutionX, renderData.resolutionY);

The Destroy function that tells the native plugin to release the texture/shader resource view

public void OnDestroy()
    {
        Renderer renderer = GetComponent<Renderer>();
        renderer.material.mainTexture = null;
        SetTextureFromUnity(renderData.textureIndex, IntPtr.Zero, renderData.resolutionX, renderData.resolutionY);
    }
1 Like

Also waiting between a Full Create->Destroy drastically reduces the likelihood that the freeze will occur but it will still happen eventually usually with successive repetitions

This is in my c++ debugger

D3D11: Removing Device.
Exception thrown at 0x00007FFCBD457788 in Unity.exe: Microsoft C++ exception: _com_error at memory location 0x00000000005FB5A0.
Exception thrown at 0x00007FFCBD457788 in Unity.exe: Microsoft C++ exception: _com_error at memory location 0x00000000005FD020.
Exception thrown at 0x00007FFCBD457788 in Unity.exe: Microsoft C++ exception: _com_error at memory location 0x00000000005FD378.
Failed to create Texture2D

I would turn the debug layer on for the device, but Unity creates it internally T_T

I am wondering if I should file a bug in unity for this. There isnt any reason why it should be broken. Unity doesnt seem to handle releasing of native textures very well.

Hi! I have this same problem outside Unity, given your report I’m beginning to think it’s either a bug on DirectX or on the video board driver. In my case I allocate and release about two textures per frame, and the quicker it is, the quicker it brakes.
It only occurs when allocating the texture on video memory, if I use normal RAM it’s ok.

Did you ever find a solution for this?

Thanks!

Unfortunately I havnt found a solution for this yet sorry :frowning:

I had exactly same issue that creating texture in native plugin causes “D3D11: Removing Device.” message and Unity freeze with massive COM exceptions. It does not happen every time, more likely a timing issue or race condition.

I fixed this issue by creating texture in rendering thread instead of Unity main thread, using GL.IssuePluginEvent(…)

It is interesting to note that D3D document explicitly said that ID3D11Device is thread safe (the immediate context is not thread safe but was not needed to create texture). While Unity doc said “IUnityGraphicsD3D11” should only be used on the rendering thread.

Hope that helps.

1 Like

take a look at this : Unity Asset Store - The Best Assets for Game Making