KeyedMutex fails to acquire after Present

Started by
2 comments, last by arbitus 13 years, 1 month ago
I am working on Direct2D and Direct3D 11 interop and have managed to create the shared DXGI resources necessary to do this, but now I have an issue with the DXGI.KeyedMutex.

I have a simple render loop that looks like this:


GraphicsContext.OutputMerger.SetTargets(DepthStencilView, BackBufferView);
GraphicsContext.ClearRenderTargetView(BackBufferView, Color.CornflowerBlue);
GraphicsContext.ClearDepthStencilView(DepthStencilView, D3D11.DepthStencilClearFlags.Depth, 1.0f, 0);

// Draw to texture
D2DKeyedMutex.Acquire(0, 100);

D2DKeyedMutex.Release(1);

// Render texture to screen
D3D11KeyedMutex.Acquire(1, 100);

D3D11KeyedMutex.Release(0);

System.Diagnostics.Debug.WriteLine("We got here");

SwapChain.Present(0, DXGI.PresentFlags.None);


The loop will execute once before throwing an exception on the D3D11KeyedMutex.Acquire() on the second pass. I have tested it using multiple Acquire() and Release() method calls inside the loop, and everything works fine until the SwapChain.Present() call is made. Also, only the D3D11KeyedMutex is affected, as the D2DKeyedMutex.Acquire() always succeeds. The exception is as follows:

First-chance exception at 0x772cb727 in Direct2DTest.exe: Microsoft C++ exception: _com_error at memory location 0x0033e6d8..
A first chance exception of type 'SlimDX.DXGI.DXGIException' occurred in SlimDX.dll
An unhandled exception of type 'SlimDX.DXGI.DXGIException' occurred in SlimDX.dll

Additional information: E_INVALIDARG: An invalid parameter was passed to the returning function (-2147024809)

The resources are initialized here:

GraphicsDevice10_1 = new D3D10_1.Device1(Factory.GetAdapter(0), D3D10.DriverType.Hardware, D3D10.DeviceCreationFlags.BgraSupport | D3D10.DeviceCreationFlags.Debug, D3D10_1.FeatureLevel.Level_10_0);

SharedTextureD3D11 = new D3D11.Texture2D(GraphicsDevice11, SharedTextureDesc);
D3D11KeyedMutex = new DXGI.KeyedMutex(SharedTextureD3D11);

SharedResource = new DXGI.Resource(SharedTextureD3D11);
SharedTextureD3D10 = GraphicsDevice10_1.OpenSharedResource<D3D10.Texture2D>(SharedResource.SharedHandle);
SharedSurface = SharedTextureD3D10.AsSurface();

D2DKeyedMutex = new DXGI.KeyedMutex(SharedTextureD3D10);


D2DFactory = new D2D.Factory(SlimDX.Direct2D.FactoryType.Multithreaded, SlimDX.Direct2D.DebugLevel.Information);

PixelFormat = new SlimDX.Direct2D.PixelFormat
{
AlphaMode = SlimDX.Direct2D.AlphaMode.Ignore,
Format = DXGI.Format.B8G8R8A8_UNorm
};

RenderTargetProperties = new SlimDX.Direct2D.RenderTargetProperties
{
HorizontalDpi = 96,
MinimumFeatureLevel = SlimDX.Direct2D.FeatureLevel.Direct3D10,
PixelFormat = PixelFormat,
Type = SlimDX.Direct2D.RenderTargetType.Hardware,
Usage = SlimDX.Direct2D.RenderTargetUsage.None,
VerticalDpi = 96
};

D2DRenderTarget = SlimDX.Direct2D.RenderTarget.FromDXGI(D2DFactory, SharedSurface, RenderTargetProperties);


GraphicsDevice11 and GraphicsContext are a direct3d 11 device/context initialized previously.
Advertisement
After considering the information found here, I decided to try something new. I changed my back buffer and depth stencil descriptions in my SwapChain to not use any multisampling. Now my mutex locks do not fail. I know that a multisampled surface cannot be shared, however, I am sharing a non-multisampled texture (and not doing anything with it yet).

Can anyone explain this behavior? Is there any way I can work around it? I cannot sacrifice MSAA in my rendered scene just to allow me to share a non-MSAA texture so I can overlay some text.
In case anyone is interested in trying this out, I have created a minimal working sample that reproduces the error.

Just execute it and press A to initialize. Once D is pressed (and the screen turns green), any subsequent push of S should cause an exception (prior to that, S should not cause any errors).

If the SwapChainDescription is changed to use SampleDescription(1,0), then the error should not occur.

If I am an idiot and doing something obviously wrong in this code, I would like that feedback as well.


using System;

using System.Drawing;
using System.Windows.Forms;

using D3D11 = SlimDX.Direct3D11;
using D3D10 = SlimDX.Direct3D10;
using D3D10_1 = SlimDX.Direct3D10_1;
using DXGI = SlimDX.DXGI;

namespace SharedResourceTest
{
public class RenderForm : IDisposable
{
private Form BackingForm { get; set; }

private D3D11.Device device11;
private D3D11.Texture2D textureD3D11;
private D3D11.RenderTargetView backBufferView;

private D3D10.Texture2D textureD3D10;

private DXGI.Factory1 factory1;
private DXGI.Adapter1 adapter1;
private DXGI.SwapChain swapChain;
private DXGI.Resource sharedResource;
private DXGI.KeyedMutex mutexD3D11;
private DXGI.KeyedMutex mutexD3D10;

private D3D10_1.Device1 device10_1;

private bool isInitialized = false;

public RenderForm()
{
BackingForm = new Form
{
ClientSize = new Size(800, 600),
Text = "Test"
};

BackingForm.KeyDown += (o, e) =>
{
if (e.KeyCode == Keys.A)
{
factory1 = new DXGI.Factory1();
adapter1 = factory1.GetAdapter1(0);
device11 = new D3D11.Device(adapter1, D3D11.DeviceCreationFlags.BgraSupport | D3D11.DeviceCreationFlags.Debug);

swapChain = new DXGI.SwapChain(factory1, device11, new DXGI.SwapChainDescription
{
BufferCount = 1,
ModeDescription = new DXGI.ModeDescription(BackingForm.ClientSize.Width, BackingForm.ClientSize.Height, new SlimDX.Rational(0, 1), DXGI.Format.R8G8B8A8_UNorm),
IsWindowed = true,
OutputHandle = BackingForm.Handle,
SampleDescription = new DXGI.SampleDescription(8, 0),
SwapEffect = DXGI.SwapEffect.Discard,
Usage = DXGI.Usage.RenderTargetOutput
});

factory1.SetWindowAssociation(BackingForm.Handle, DXGI.WindowAssociationFlags.IgnoreAltEnter);

using (var backBuffer = D3D11.Resource.FromSwapChain<D3D11.Texture2D>(swapChain, 0))
{
backBufferView = new D3D11.RenderTargetView(device11, backBuffer);
}

device10_1 = new D3D10_1.Device1(adapter1, D3D10.DriverType.Hardware, D3D10.DeviceCreationFlags.BgraSupport | D3D10.DeviceCreationFlags.Debug, D3D10_1.FeatureLevel.Level_10_1);

textureD3D11 = new D3D11.Texture2D(device11, new D3D11.Texture2DDescription
{
Width = 800,
Height = 600,
MipLevels = 1,
ArraySize = 1,
Format = DXGI.Format.B8G8R8A8_UNorm,
SampleDescription = new DXGI.SampleDescription(1, 0),
Usage = D3D11.ResourceUsage.Default,
BindFlags = D3D11.BindFlags.RenderTarget | D3D11.BindFlags.ShaderResource,
CpuAccessFlags = D3D11.CpuAccessFlags.None,
OptionFlags = D3D11.ResourceOptionFlags.KeyedMutex
});

sharedResource = new DXGI.Resource(textureD3D11);
textureD3D10 = device10_1.OpenSharedResource<D3D10.Texture2D>(sharedResource.SharedHandle);

mutexD3D10 = new DXGI.KeyedMutex(textureD3D10);
mutexD3D11 = new DXGI.KeyedMutex(textureD3D11);

isInitialized = true;
}

if (e.KeyCode == Keys.S && isInitialized)
{
mutexD3D10.Acquire(0, 100);
mutexD3D10.Release(1);
mutexD3D11.Acquire(1, 100);
mutexD3D11.Release(0);
}

if (e.KeyCode == Keys.D && isInitialized)
{
device11.ImmediateContext.OutputMerger.SetTargets(backBufferView);
device11.ImmediateContext.ClearRenderTargetView(backBufferView, Color.Green);

swapChain.Present(0, DXGI.PresentFlags.None);
}
};
}

public void Run()
{
Application.Run(BackingForm);
}

public void Dispose()
{
adapter1.Dispose();
factory1.Dispose();
swapChain.Dispose();

sharedResource.Dispose();

mutexD3D10.Dispose();
mutexD3D11.Dispose();

backBufferView.Dispose();

textureD3D10.Dispose();
textureD3D11.Dispose();

device11.Dispose();
device10_1.Dispose();
}
}
}

Sorry to keep replying to this and bumping the post, but I wanted to put my latest results down in case anyone finds this thread and has the same problem.

Ultimately, it seems that there is no problem, or that it might be a driver issue or some other point of failure. I loaded up the exact same code today and it executed flawlessly. Then I added code to add a depth stencil buffer in with my back buffer, and the problem appeared again. I closed my browser window in frustration (and preparation for a reboot) and the issue disappeared. I added more code for using a Direct2D factory and the issue surfaced once again, but after a reboot, it went away. For the most part, cleaning my solution and forcing a full rebuild often makes the problem disappear. Also, closing other running applications seemed to have an impact.

This topic is closed to new replies.

Advertisement