[3308] DXGI Error:
[3308] Swapchain Released while fullscreen. Switch it to the windowed state first.
Fair enough. I decided to change the code to create a new form, new swap chain, and new render target for every switch to fullscreen, and to Dispose it when switched back. If the application tries to exit while fullscreen, the swapchain is switched to windowed and the form destroyed before this can happen. Seems fine to me so far.
But DebugView had more to say:
[3308] DXGI Warning:
[3308] IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH. DXGI_SWAP_CHAIN_DESC::BufferDesc = { 1680, 1050, { 60, 1 }, R8G8B8A8_UNORM, 0, 0 }; DXGI_SWAP_CHAIN_DESC::SampleDesc = { 1, 0 }; DXGI_SWAP_CHAIN_DESC::Flags = 0;
Presentation inefficiencies!? Oh noes what can this mean! It means that the swapchain is blitting the backbuffer to the front buffer each time I call Present(), instead of page flipping. This isn't what I signed up for!
Luckily the DXGI error itself is full of friendly advice. Am I calling ResizeBuffers appropriately? I'm not calling it at all, I'm creating the window explicitly for fullscreen, then killing it. Am I specifying a MODE_DESC that's not available? Well, R8G8B8A8_UNORM, 1680x1050 at 60Hz is my monitors native display mode, so I didn't think so. Though, the truth is I was. Selecting the same mode from the result set of GetDisplayModeList works fine.
var modes = dxgiFactory.GetAdapter(0).GetOutput(0).GetDisplayModeList(DXGI.Format.R8G8B8A8_UNorm, DXGI.DisplayModeEnumerationFlags.Scaling | DXGI.DisplayModeEnumerationFlags.Interlaced);
DXGI.ModeDescription desc = modes[modes.Count() - 1];
The above code is pretty sloppy, I'll bind the mode collection to a nice combo box and allow the user the choice. It's also hard coded to the primary display adapter, and primary display - which is probably the right choice in most cases, but I'll make this stuff configurable too. It's selecting the highest available mode, which with my hardware happens to be my LCD's native resolution and refresh rate.
Since the output of a NES is so low res, stretching it to a 1680x1050 back buffer is overkill, but nothing the hardware cant handle. Running it in 640x480 mode visually looks exactly the same, as the image is scaled fullscreen when it's presented. I'm considering a little algorithm to look for the first available display mode that has a larger resolution than the last stage in rendering, since it should be the least needed to do the job.
On the topic D3D10/11 surfaces which you can embed in WPF, and overlay with content, it's doable, and I'll play around with another swapchain which renders to a shared resource, which is then presented by D3D9 into WPF's D3DImage. Simple on the surface, but getting it to work properly seems full of little gotchas.
There's no reason to be working in D3D10 anymore, a port to D3D11 should be extremely painless. It's all the same if you aren't using the new stuff. Right now I'm on the fence between continuing down the D3D path, or porting everything over to OpenGL and going that way. It'll likely be the latter, but the last time I tried I had trouble setting it up. Tao Framework doesn't seem to be updated anymore. I think the best way to go would be a native dll for opengl.
Oh, one more thing on the topic of this hybrid fullscreen solution:
dxgiFactory.SetWindowAssociation(fullForm.Handle, DXGI.WindowAssociationFlags.IgnoreAltEnter);
You want to associate your factory with the window it's drawing to, as my switch back to windowed wasn't working right if my current focus was on a different display (ie; my mouse pointer is resting over on the second monitor). I also tell D3D to ignore AltEnter, since I'm handling and calling SetFullScreenState by myself and I don't need it in my face - D3D would put the "hidden" form back into windowed mode and do nothing else.
No comments:
Post a Comment