D3D10CreateDeviceAndSwapChain() always failing with DXGI_ERROR_INVALID_CALL - c++

I'm creating a hidden window and I'm looking to getting a pointer to IDXGISwapChain::Present(). The problem is that I can't get a valid Direct3D10 device, nor a valid swap chain.
HWND hwnd = CreateWindow(TEXT("flhiSTATIC"), TEXT("flh DXGI Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, 0, NULL, NULL, 0);
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(scd));
scd.BufferCount = 2;
RECT rcWnd;
GetClientRect(hwnd, &rcWnd);
scd.BufferDesc.Width = rcWnd.right - rcWnd.left;
scd.BufferDesc.Height = rcWnd.bottom - rcWnd.top;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // also tried DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
scd.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
scd.BufferDesc.RefreshRate.Numerator = 60;
scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hwnd;
scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 0;
scd.Windowed = TRUE;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
pD3D10CreateDeviceAndSwapChain = reinterpret_cast<D3D10CREATEDEVICEANDSWAPCHAIN_PROC *>(GetProcAddress(d3d10, "D3D10CreateDeviceAndSwapChain"));
HRESULT hr = pD3D10CreateDeviceAndSwapChain(NULL /*pAdapter*/, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_DEBUG, D3D10_SDK_VERSION, &scd, &pSwapChain, &pDev);
// this guy always fails with 0 in both pSwapChain and pDev...
Any idea what might be wrong with the above code?

I completely forgot about the need to create or assign a pre-existing window class :(
That was the problem; lesson learned - always check the return codes of all the calls.
edit
I completely forgot to call CreateWindow with a valid window class, either one I'd previously registered or one that's registered by someone within the current module.

Related

How to stop Direct3D 11 from stretching fullscreen to monitor size?

I am trying to make my Direct3D window fullscreen, with an 800x600 resolution. However, everything I try makes the screen stretch to cover the entire monitor, instead of just taking up an 800x600 area with black bars on the sides. The cursor is also stretched.
I create my swap chain with this DXGI_SWAP_CHAIN_DESC:
DXGI_SWAP_CHAIN_DESC sd{};
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 0;
sd.BufferDesc.RefreshRate.Denominator = 0;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = hWnd;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
Then I set the screen resolution using this code:
DEVMODEW devMode{};
devMode.dmSize = sizeof(devMode);
devMode.dmPelsWidth = width;
devMode.dmPelsHeight = height;
devMode.dmFields = DM_PELSHEIGHT | DM_PELSWIDTH;
LONG res = ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN);
Finally I set the swap chain to be fullscreen:
HRESULT hr = swap->SetFullscreenState(on, nullptr);
Also, in my window procedure I call this whenever WM_SIZE is received:
swapChain.reset(); // Destroy swap chain
context->ClearState();
if (FAILED(swap->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0))) throw Exception("Failed to resize buffers");
swapChain.emplace(swap.Get(), device.Get(), context.Get(), hWnd); // Recreate swap chain
I have tried using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH in both the DXGI_SWAP_CHAIN_DESC and the ResizeBuffers, as well as calling IDXGISwapChain::ResizeTarget with my desired size, but I still get the same problem.

Creating Swap Chain causes Window Handle to become Invalid

I'm trying to work with both Direct2D and Direct3D. Right now, I'm having Direct2D draw content to a separate Device Context (with an HDC) and then copy the contents of that Device Context into my window. I could show the code I use to set that up in an edit to this post if requested, but before Direct3D gets involved, that part works.
Here is a simplified version of the Window Drawing code I use.
if (d3dEngine.Get()) // Object used to hold Direct3D Resources (.Get() returns a pointer for a null check)
{
// d3dEngine->PrepareScene(D2D1::ColorF(D2D1::ColorF::Wheat));
}
// Drawing Board holds the Direct 2D Render Target
drawingBoard->GetRenderer()->BeginDraw();
drawingBoard->GetRenderer()->Clear(D2D1::ColorF(1.0f,1.0f,1.0f,1.0f));
mainPage->Draw(); // Main Page Holds various objects that draw to Direct2D
if (d3dEngine.Get())
d3dEngine->FinalizeScene();
drawingBoard->GetRenderer()->EndDraw();
// Get the Secondary Device Context that Direct2D draws to
HDC dc = drawingBoard->GetDc();
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
// Use the BitBlt function to copy Direct2D content into a window
if (!BitBlt(GetDC(currentWindow), r.left, r.top, r.right - r.left, r.bottom - r.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
Before any Direct3D resources are created (and the d3dEngine.Get() call returns null), this code runs to my satisfaction.
However, following the creation of Direct3D resources, the code fails:
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
The window handle currentWindow becomes invalid as GetLastError() returns 1400 after the call to GetClientRect. I suspect that the Swap Chain in Direct3D 11 may play a role due to the following code used to activate Direct3D.
GetClientRect(window, &Location);
unsigned int width = Location.right - Location.left,
height = Location.bottom - Location.top;
D3D_DRIVER_TYPE dTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE//, D3D_DRIVER_TYPE_WARP
};
int tTypes = ARRAYSIZE(dTypes);
D3D_FEATURE_LEVEL dLevels[] =
{
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0
};
int tLevels = ARRAYSIZE(dLevels);
DXGI_SWAP_CHAIN_DESC swapChainDescription;
// Initialize the swap cahin
swapChainDescription.BufferCount = 2;
swapChainDescription.BufferDesc.Width = Location.right - Location.left;
swapChainDescription.BufferDesc.Height = Location.bottom - Location.top;
swapChainDescription.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDescription.BufferDesc.RefreshRate.Numerator = 30;
swapChainDescription.BufferDesc.RefreshRate.Denominator = 1;
swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDescription.OutputWindow = window;
swapChainDescription.Windowed = true;
swapChainDescription.SampleDesc.Count = 1;
swapChainDescription.SampleDesc.Quality = 0;
swapChainDescription.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDescription.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDescription.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;// DXGI_SWAP_EFFECT_DISCARD;
unsigned int flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
/// Other initialization Code
HRESULT results = 0;
// Initialize ID3D11Device "graphicsDevice"
IDXGISwapChain* sc = nullptr;
results = dxFact->CreateSwapChain(graphicsDevice, &swapChainDescription, &sc);
This code is in a different class than the Window drawing code towards the beginning.
The window variable in the Direct3D code holds the same value that currentWindow holds in the Window Code.
Is there anyone who could provide insight as to what is going on and why the window handle stops working? And perhaps suggest a workaround?
While I'm still unsure why the window handle seemed to be useless when I checked, I was able to develop a workaround.
Basically, I have my Window class hold a RECT indicating the size of the Window and I use that instead of getting the RECT from the Window every time.
RECT r{ 0,0,0,0 };
int err = 0;
// Retrieve the Rectangle for the window (currentWindow is the window handle used)
if(!GetClientRect(currentWindow, &r))
err = GetLastError();
// Use the BitBlt function to copy Direct2D content into a window
if (!BitBlt(GetDC(currentWindow), r.left, r.top, r.right - r.left, r.bottom - r.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
// Now, it uses a 'size' attribute
int err = 0;
if (!BitBlt(GetTWindowDc(), size.left, size.top, size.right - size.left, size.bottom - size.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
When it comes to getting the Window Device Context, the new GetTWindowDc() method takes care of that:
if (d3dEngine.Get())
return d3dEngine->GetDC();
return GetDC(currentWindow);
Basically, if Direct3D is activated, the 3D manager object (which holds a DXGISurface) retrieves the HDC from Direct3D to use.
HDC TWindowEngine::GetDC()
{
if (!surface.Get()) // My Unique Smart pointer to a DXGISurface1 object
return 0;
HDC dc;
assert(SUCCEEDED(surface->GetDC(FALSE, &dc)));
return dc;
}
According to Surface-GetDc Documentation, you need to call the corresponding ReleaseDc on the DXGISurface1 object. So this is how I do it.
In the Window Draw code:
if (!BitBlt(GetTWindowDc(), size.left, size.top, size.right - size.left, size.bottom - size.top, dc, 0, 0, SRCCOPY))
err = GetLastError();
FlushDc();
Here is the FlushDc method:
void TWindow::FlushDc()
{
if (d3dEngine.Get())
d3dEngine->ClearDC();
}
And the ClearDC method is impelented.
void TWindowEngine::ClearDC()
{
if (surface.Get())
surface->ReleaseDC(nullptr);
}

D3D11CreateDeviceAndSwapChain fails with S_False on different computer

I've made quite a bit of progress since the last time I asked a question. I've got a really cool build now with a terrain mesh with mountains and lakes:
LakeAndMountains
I made a release build, debugged it, and now it works just fine on my computer. I can take the application folder and move it around on my computer and run the .exe file with no issues. However, when I copy the application directory over to my other computer (and my friend's computer), it fails during the D3D11CreateDeviceAndSwapChain step with an HR of S_False.
For both my other computer and my friend's computer, it triggers only the if(failed(hr)) after the create function is called, and it says dev/devcon/swapchain are all NULL. Because they are all null, when it hits the function from swapchain, it crashes with an access violation error.
I searched for a few days looking for solutions, but I have yet to see one that had the S_FALSE occur. I tried some of the more straightforward answers but got nothing. All the computers are running 64bit on 64 bit OS, all have DirectX12, all are high end gaming PCs, my other computer actually has VS2017CE as well set up for c++ game programming, but they both still fail on that line. I'd really appreciate it if anyone could give me some guidance on where to begin deciphering why a release build works on my computer but not on anyone else's computer. Here is the code where it gets initialized, as well as the code for the window creation (code is excerpted to just the relevant parts of the functions):
WinMain:
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//MessageBox(NULL, "Start of WinMain", "WinMain", 0);
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
//Screen size variables
long screenWidth = 1280;
long screenHeight = 720;
UINT screenWidthUINT = 1280;
UINT screenHeightUINT = 720;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass1";
// register the window class
RegisterClassEx(&wc);
RECT wr = { 0, 0, screenWidth, screenHeight }; // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
"WindowClass1",
"Game",
WS_OVERLAPPEDWINDOW,
0, // x-position of the window
0, // y-position of the window
wr.right - wr.left, // width of the window
wr.bottom - wr.top, // height of the window
NULL,
NULL,
hInstance,
NULL);
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
//MessageBox(NULL, "called ShowWindow", "WinMain", 0);
/*****************************************
// GAME ENGINE INITIALIZATION
******************************************/
//Need to initialize the graphics engine. This passes the window pointer through the
//game engine to the D3D engine so it knows what window to look at.
//MessageBox(NULL, "Calling InitGraphics", "WinMain", 0);
InitGraphics(hWnd);
InitGraphics:
//DEVICE CREATION
#include Windows.h
#include <windowsx.h>
#include <d3d11.h>
#include <DirectXMath.h>
#include <D3Dcompiler.h>
#include <dxgi.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#include "DirectXDeviceEngine.h"
using namespace DirectX;
InitGraphics(HWND hWnd)
{
//call at start to initialize D3DX
if (hWnd == NULL)
{
MessageBox(NULL, "hWnd was NULL", "DirectXDeviceEngine", 0);
}
HRESULT hr;
//initialize swap chain
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = winWidth;
bufferDesc.Height = winHeight;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc = bufferDesc;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.SampleDesc.Quality = 1;
scd.Windowed = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // windowed/full-screen mode
scd.Flags = 0;
// create a device, device context and swap chain using the information in the scd struct
dev = NULL;
devcon = NULL;
swapchain = NULL;
hr = D3D11CreateDeviceAndSwapChain(
NULL, //null
D3D_DRIVER_TYPE_HARDWARE, //driver type
NULL, //handle to a software rasterizer, should be null if driver type isn't software
NULL, //UINT device creation flags, can be ORed together
NULL, //D3D Feature level, when NULL defaults to 11.0-9.1 feature levels
NULL, //the number of elements in the D3D feature level array
D3D11_SDK_VERSION, //set to D3D11_SDK_VERSION
&scd, //reference to the swap chain desc
&swapchain, //reference to the pointer to the swap chain
&dev, //reference to the pointer to the device
NULL, //returns a reference to the first supported element in the feature level array
&devcon); //reference to the pointer to the device context
if (FAILED(hr))
{
//CODE FALLS INTO THIS BLOCK ON OTHER COMPUTER
MessageBox(NULL, "Create Device and SwapChain FAILED", "DirectXDeviceEngine", 0);
if (swapchain == NULL)
{
MessageBox(NULL, "swapchain was NULL", "DirectXDeviceEngine", 0);
}
if (dev == NULL)
{
MessageBox(NULL, "dev was NULL", "DirectXDeviceEngine", 0);
}
if (devcon == NULL)
{
MessageBox(NULL, "devcon was NULL", "DirectXDeviceEngine", 0);
}
}
//prepare buffers
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
//VVVV CODE THEN CRASHES ON NEXT LINE BECAUSE SWAPCHAIN IS NULL VVVV
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
Thanks in advance.
----UPDATE 2017/09/08-----
So I swapped some code around but I still get the error on the other computer. Current code looks like this:
//call at start to initialize D3DX
if (&hWnd == NULL)
{
MessageBox(NULL, "hWnd was NULL", "DirectXDeviceEngine", 0);
}
HRESULT hr;
// create a device, device context and swap chain using the information in the scd struct
dev = NULL;
devcon = NULL;
swapchain = NULL;
D3D_FEATURE_LEVEL lvl[] = {
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 };
DWORD createDeviceFlags = 0;
hash ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
hash endif
D3D_FEATURE_LEVEL fl;
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
createDeviceFlags, lvl, _countof(lvl),
D3D11_SDK_VERSION, &dev, &fl, &devcon);
if (hr == E_INVALIDARG)
{
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
createDeviceFlags, &lvl[1], _countof(lvl) - 1,
D3D11_SDK_VERSION, &dev, &fl, &devcon);
}
if (FAILED(hr))
{
MessageBox(NULL, "Create Device Failed", "DirectXDeviceEngine", 0);
}
IDXGIDevice * dxgiDevice = 0;
dev->QueryInterface(__uuidof(IDXGIDevice), (void **)& dxgiDevice);
IDXGIAdapter * dxgiAdapter = 0;
dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)& dxgiAdapter);
IDXGIFactory * dxgiFactory = 0;
dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)& dxgiFactory);
//initialize swap chain
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
/*bufferDesc.Width = winWidth;
bufferDesc.Height = winHeight;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
*/
bufferDesc.Width = 0;
bufferDesc.Height = 0;
bufferDesc.RefreshRate.Numerator = 0;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc = bufferDesc;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.SampleDesc.Quality = 1;
scd.Windowed = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // windowed/full-screen mode
scd.Flags = 0;
hr = dxgiFactory->CreateSwapChain(dev, &scd, &swapchain);
if (FAILED(hr))
{
//fails here
MessageBox(NULL, "Create Swap Chain Failed", "DirectXDeviceEngine", 0);
}
if (dxgiDevice != NULL)
{
dxgiDevice->Release();
}
if (dxgiAdapter != NULL)
{
dxgiAdapter->Release();
}
if (dxgiFactory != NULL)
{
dxgiFactory->Release();
}
//prepare buffers
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
So, there is still some weird stuff happening here I'm not getting. If someone has an example of how to use FindClosestMatchingMode properly, I'd really appreciate it.
There is one other really peculiar thing though. When I am in the debugger on my laptop, the variable hWnd has a value, but the compiler says that it is Unused and can't display a value for it. Is this normal or could this be the source of the problem as hWnd is used in the Swap Chain Description? How can hWnd be bad/unused on the other computer but not on my desktop?
Thanks again.
So I FINALLY found the cause of the issue. For some reason, the Count 4 Quality 1 MSAA was not working on the other computer. When I set it to 1/0, it ran perfectly. I'll need to look into how to properly enumerate the MSAA stuff so it can be adjusted depending on the computer.

IDXGISwapChain::ResizeBuffers triggers breakpoint when switching from fullscreen to windowed

Whenever my Direct3D 11 application switches from fullscreen to windowed mode, IDXGISwapChain::ResizeBuffers triggers a breakpoint. In Visual Studio's console, the message "Critical error 0xc0000374" is printed, with no other information. Apparently this means a heap corruption has occurred. Okay then. I can't get any more information about why this occurred because the window obnoxiously obscures my view and prevents me from controlling the visual studio window.
I'm following the suggestions made on this MSDN page. By that I mean I copied and pasted the code.
This is my setup code (ignore the lack of error checking):
DXGI_SWAP_CHAIN_DESC swap_chain_desc = { 0 };
swap_chain_desc.BufferCount = 2;
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.OutputWindow = window::get();
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swap_chain_desc.Windowed = TRUE;
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
if (fullscreen == 1) {
swap_chain_desc.BufferDesc.Width = window::desktop_width();
swap_chain_desc.BufferDesc.Height = window::desktop_height();
} else {
swap_chain_desc.BufferDesc.Width = window::width();
swap_chain_desc.BufferDesc.Height = window::height();
}
HRESULT hr = D3D11CreateDeviceAndSwapChain (
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&swap_chain_desc,
&m_swap_chain,
&m_device,
NULL,
&m_context
);
ID3D11Texture2D* back_buffer;
hr = m_swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
hr = m_device->CreateRenderTargetView(back_buffer, NULL, &m_view);
back_buffer->Release();
m_context->OMSetRenderTargets(1, &m_view, NULL);
D3D11_VIEWPORT viewport = { 0 };
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
if (fullscreen == 1) {
viewport.Width = window::desktop_width();
viewport.Height = window::desktop_height();
} else {
viewport.Width = window::width();
viewport.Height = window::height();
}
m_context->RSSetViewports(1, &viewport);
if (fullscreen == 1) {
m_swap_chain->SetFullscreenState(TRUE, NULL);
}
Is there anything there that might have caused this problem? The rendering code is just a ClearRenderTargetView and Present after a PeekMessage loop, nothing important.
This issue was fixed by showing the window before setting the swap chain's fullscreen state. Either call UpdateWindow(hwnd) and ShowWindow(hwnd, SW_SHOW) or set the window style to WS_VISIBLE when calling CreateWindow() or CreateWindowEx(), preferably before doing anything DirectX related.

`E_FAIL` when creating DirectX 10 Device and Swap Chain - _com_error

I am working though some simple DX tutorials, and have hit an early snag. I am working on both an old laptop and a new PC, so I'm using d3d10_1.lib which lets me use a 9 feature set. The PC, however, does support all the way to DX11, so nothing should be a problem on there.
So here's the function where it fails:
bool DirectX9Renderer::Initialise(HWND* handle)
{
//window handle
hWnd = handle;
//get window dimensions
RECT rc;
GetClientRect( *hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
//set buffer dimensions and format
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;;
//set refresh rate
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
//sampling settings
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.SampleDesc.Count = 1;
//output window handle
swapChainDesc.OutputWindow = *hWnd;
swapChainDesc.Windowed = true;
HRESULT result = D3D10CreateDeviceAndSwapChain1( // this is line 57
NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
D3D10_CREATE_DEVICE_SINGLETHREADED | D3D10_CREATE_DEVICE_DEBUG,
D3D10_FEATURE_LEVEL_9_1,
D3D10_1_SDK_VERSION,
&swapChainDesc,
&pSwapChain,
&pD3DDevice
);
if(FAILED(result))
{
return FatalError("D3D device creation failed");
}
// there's more stuff after this, but I don't get that far
}
So the call to D3D10CreateDeviceAndSwapChain1 fails with the less-helpful error code E_FAIL.
There is a line in the Debug output too:
First-chance exception at 0x770f56c4 in TileTest.exe: Microsoft C++ exception: _com_error at memory location 0x00b6e8d4..
I have tried using D3D10_DRIVER_TYPE_REFERENCE and different D3D10_FEATURE_LEVEL_xx values, but it doesn't seem to work.
I think the problem may have been to do with the D3D10_CREATE_DEVICE_FLAG I sent in. I changed the D3D10_CREATE_DEVICE_SINGLETHREADED | D3D10_CREATE_DEVICE_DEBUG to 0 and it now works.
I tried to create the device inside a VMware virtual machine. It failed (device stayed NULL) until I changed the requested FEATURE_LEVEL from D3D10_FEATURE_LEVEL_10_1 to D3D10_FEATURE_LEVEL_9_3. I've heard this also helps other PCs with real hardware.