pouët.net

D3D11CreateDeviceAndSwapChain, Fullscreen & Optimus

category: code [glöplog]
 
Maybe I'm doing it wrong, but the DX11 window creation code I use looks something like this:
Code: HWND hWnd = CreateWindowExA(...); swapChainDesc.OutputWindow = hWnd; HRESULT result = D3D11CreateDeviceAndSwapChain(...);

I'm pretty certain that the "..." part is correct and working.

The problem:
When using this with the following on an NV Optimus enabled device result becomes DXGI_STATUS_OCCLUDED instead of S_OK:
Code: extern "C" { _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; }


Simply ignoring result seems to work here, but since the standard way is usually checking for S_OK (which is zero) care should be taken.
When executed on the intel card result is S_OK - as one would expect.
No problems with this code (with and without the export) on a NV desktop.

Did anyone experience that problem? Is there a nice and elegant fix for this issue?
added on the 2015-08-11 00:48:10 by las las
https://msdn.microsoft.com/en-us/library/windows/desktop/cc308061(v=vs.85).aspx

Conjecture: I'd say "ignoring" the return code is the way to go here; the correct way to check for DX errors isn't checking for S_OK but rather for bit 31 anyway. Seems that Optimus takes a frame or two to activate properly.
added on the 2015-08-11 02:05:53 by kb_ kb_
Don't check for a specific status like S_OK... You have the SUCCEEDED(hr) and FAILED(hr) Macros...

And SUCCEEDED(DXGI_STATUS_OCCLUDED) returns true :-D
added on the 2015-08-11 09:32:18 by EvilOne EvilOne
Now I'm asking myself how I came up with the S_OK bullshit in the first place - most probably caused by reverse engineering too many DX11 intros which actually do the "wrong kind" of error checking.

I usually just don't check for errors - Debug context & breakpoints from the debug layer do the job pretty well if you mostly do research prototypes.

I still find it rather interesting that optimus causes this behavior, it also seems to "take longer" to switch to fullscreen, with some more flickering. Windowed mode works without any problems whatsoever.
added on the 2015-08-11 10:28:29 by las las
is the window created as fullscreen or windowed?
added on the 2015-08-11 11:31:48 by smash smash
Only happens with DXGI_SWAP_CHAIN_DESC.Windowed = 0 (i.e. fullscreen mode).
The D3D11CreateDeviceAndSwapChain call also throws some first chance exceptions - nevertheless swapchain/context/device are usable, as mentioned above.
The window itself is created using dirty & lazy win32 sizecoding tricks, leaving some work for DX (no ChangeDisplaySettingsA etc.):
Code: HWND hWnd = CreateWindowExA(0, (LPCSTR)0xC018, 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0);


Additional strange behaviors (again fullscreen only) DXGI_SWAP_CHAIN_DESC.Flags = 0
Given the DX-Debug-output Intel would prefer this to be set to DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH which causes some totally strange rescaling "sometimes" (I don't know exactly when this happens yet) when using the NV device.

Another thing... Intel seems to have some issues with DXGI_SWAP_CHAIN_DESC.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT (this could also be fullscreen only, did not check windowed yet), totally strange, colors look pretty "oldschool" until I middle-click onto the window which "fixes it", uuuahhhghh.
Given the Remarks that format should be ok to use (DX > 10), right?
added on the 2015-08-11 12:44:30 by las las
Proper handling of DXGI_STATUS_OCCLUDED would be to pause the application, and periodically call Present with the TEST flag, and when it returns S_OK, resume rendering. The interesting bit is that CreateDevice isn't supposed to return DXGI_STATUS_OCCLUDED, at least according to the docs, but hey, there's been stranger things in dxland :)
added on the 2015-08-12 00:22:26 by reptile reptile
I'd also like to add that Optimus needs to die, for several reasons, but just to give you one: i'm getting _DIAGONAL_ tearing even in the browser if i'm using the nvidia gpu for rendering. They can't even pass a bloody quad properly through that thing.
added on the 2015-08-12 00:25:09 by reptile reptile
Well, it's not as bad as it was some time ago and since I had to get a reasonably lightweight mobile machine - I now have that stuff... Are they still using a version of detours which is not supposed to be used with end user products? *cough*
Btw. the export switch seems to work "pretty well", but it also uses the NV device if you set the exported value to zero, which is not exactly what is written in the specs.

Code: CreateDevice isn't supposed to return DXGI_STATUS_OCCLUDED

That's why I asked in the first place.
added on the 2015-08-12 10:45:58 by las las
I'm not sure about DXGI_STATUS_OCCLUDED.

I bet my ass on D3D11CreateDeviceAndSwapChain returning not only the D3D return codes, but also the codes passed through from the lower level DXGI magic. Documentation issue?
added on the 2015-08-12 10:57:18 by EvilOne EvilOne
Possible.
From D3D11CreateDeviceAndSwapChain:
Quote:

This method returns one of the following Direct3D 11 Return Codes.

No DXGI_STATUS_OCCLUDED listed there.
added on the 2015-08-12 11:16:16 by las las
As I said, I guess it's a documentation issue. Time to write some D3D11 test code this evening, I have an Optimus laptop too.
added on the 2015-08-12 12:31:48 by EvilOne EvilOne
Oh btw. instead of the export, there is also the somewhat undocumented env-variable SHIM_MCCOMPAT. This seems to be set/used when utilizing the "Run with graphics processor" context menu shell extension (I had a look with IDA, Nv3DAppShExt.dll).

"Integrated"
Code: set SHIM_MCCOMPAT=0x80000000 awesomeIntro.exe


"High-performance NVIDIA processor"
Code: set SHIM_MCCOMPAT=0x80000001 awesomeIntro.exe


As seen here.

From other sources, 0x80000000/MSB, seems to be the "override" bit, LSB selects the state here.
added on the 2015-08-13 09:40:29 by las las
To bad I couldn't write any line of code yesterday, thanks to Evil[2]... any new findings regarding the glitches when going fullscreen?
added on the 2015-08-13 10:29:07 by EvilOne EvilOne
Actually there is another function you can use to create your context... As long you go NV only anyways, you can use NvAPI_D3D11_CreateDeviceAndSwapChain(...).

Despite the description in the header claiming this function to be the same as D3D11CreateDeviceAndSwapChain with an extra argument, it always selected the NV card in my tests (I assumed that would happen.). Fun fact: It still raises the first chance exceptions but returns S_OK.

In order to use this function you have to link against a static lib or do some (ugly) undocumented things.
added on the 2015-08-13 23:54:03 by las las

login