Debug DirectX code - c++

I've been learning DirectX by following some tutorials but every time I type something myself then DirectX won't work. Here is an example of the latest error that I can't fix after hours of research:
//Header.h
static HWND hWnd;
static IDXGISwapChain* swapChain;
static ID3D11Device* dev;
static ID3D11DeviceContext* devCon;
static ID3D11RenderTargetView* renderTarget;
//DirectX.cpp
bool InitD3D11(HINSTANCE hInst)
{
HRESULT hr;
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = 800;
bufferDesc.Height = 600;
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;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.Windowed = true;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &dev, NULL, &devCon);
ID3D11Texture2D* backBuffer;
hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBuffer);
hr = dev->CreateRenderTargetView(backBuffer, NULL, &renderTarget);
backBuffer->Release();
devCon->OMSetRenderTargets(1, &renderTarget, NULL);
return true;
}
//This is not the full code - I linked directx and lib files and stuff like that.
//If I copy and paste code from tutorials, everything runs fine
Whenever I call InitD3d11, I get an error saying that the swapChain is a NULL pointer. I assume that bufferDesc and/or swapChainDesc has some invalid data but the compiler can't give me any clue what is responsible for the error. Can someone please show me how to trace and fix errors like this? Thanks.

You are not checking the HRESULT values so you are missing all error-handling. For COM programming, even with Direct3D, you must check the HRESULT of every method that can return one for failure. If the return value is safe to ignore, it returns void instead.
Checking HRESULT values in old-school C/C++ programs is done with either the FAILED or SUCCEEDED macros.
hr = D3D11CreateDeviceAndSwapChain( /* ... */ *);
if (FAILED(hr))
return false;
In most cases, a failed HRESULT is treated as a 'fast-fail' or a fatal error. In other words, the program cannot proceed if the call fails.
In other cases there can be special case handling to recover from the error perhaps by using different options. For a detailed example of that, see Anatomy of Direct3D 11 Create Device.
In older Microsoft samples based on the legacy DXUT framework, the error handling was done with macros like V or V_RETURN which did some tracing or tracing & fatal exit.
In modern C++ samples, we actually use a helper DX::ThrowIfFailed that generates a C++ exception on a failed HRESULT for the fast-fail scenario. This makes the code more streamlined and readable:
DX::ThrowIfFailed(
D3D11CreateDeviceAndSwapChain( /* ... */ *)
);
The function itself is defined as:
#include <exception>
namespace DX
{
inline void ThrowIfFailed(HRESULT hr)
{
if (FAILED(hr))
{
// Set a breakpoint on this line to catch DirectX API errors
throw std::exception();
}
}
}
Your program should be compiled with /EHsc which is already in the default Visual Studio templates. See this topic page for more details.
From your code snippet above, you are following a pretty old-school tutorial. A lot has changed even for DirectX 11 development and most of those older tutorials are going to lead to confusion. As you are new to DirectX, I recommend you take a look at the DirectX Tool Kit and the tutorials there first. You can then come back to the older tutorials with a better understanding of 'modern' Direct3D and be able to extract more relevant information from the old stuff.
After checking all HRESULTS, the next thing you should do is enable the Direct3D debug layer which provides extra debugging information in the output window.
DWORD createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
hr = D3D11CreateDeviceAndSwapChain(
nullptr, D3D_DRIVER_TYPE_HARDWARE,
nullptr, createDeviceFlags, nullptr,
0, D3D11_SDK_VERSION,
&swapChainDesc, &swapChain, &dev, nullptr, &devCon);
You'll note I'm using the C++11 nullptr which is supported on Visual C++ 2010 or later instead of the old-school NULL. That's because it is typed. You were using NULL in two places in your version where the parameter wasn't actually a pointer, it's a number.
With this, you'll get a lot of feedback on basic errors that would help diagnose why in your particular case the swapchain is failing to create. I suspect it's because you are providing some values that are only meaningful for "exclusive fullscreen mode" and not for windowed mode (bufferDesc.RefreshRate). Instead, try:
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferDesc.Width = 800;
swapChainDesc.BufferDesc.Height = 600;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
This works on VS 2013 or VS 2015 which will initialize the structure to 0 with the ={}; syntax. On older compilers, you'll need to use ZeroMemory like you did in your old-school code above.
Note that using D3D11_CREATE_DEVICE_DEBUG will fail on a system that lacks the debugging device which is intended only for developers to use. Details on where you obtain the debug device layer differs based on which version of Windows you are using. See Direct3D SDK Debug Layer Tricks which has a little summary table at the bottom.
Also, debugging in the presence of uninitialized variables is a huge pain. Uninitialized pointers in particular can be a huge time waster. It would help if you did the following:
static HWND hWnd = nullptr;
static IDXGISwapChain* swapChain = nullptr;
static ID3D11Device* dev = nullptr;
static ID3D11DeviceContext* devCon = nullptr;
static ID3D11RenderTargetView* renderTarget = nullptr;
Even better, instead of using raw pointers for your COM objects, you should be using a C++ smart-pointer like Microsoft::WRL::ComPtr. See this topic page for details. Our modern samples use it, and it works for classic Win32 desktop apps as well as for Windows Store, UWP, and Xbox One apps since it's just a C++ template.

Related

HRESULT 0x8876086c D3DERR_INVALIDCALL with DirectX9 pretty much following the documentation example

So i wanna draw an overlay over another window, but im getting no real runtime error the visual Studio debugging tools tell me that the result of
HRESULT res = object->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, &params, NULL, &device);
is 0x8876086c. So here are the snippets of my code that are important and lead to this error(D3DERR_INVALIDCALL), which leads to the device being a nullpointer, which means i can't do anything with it.
I couldn't really figure out what led to this as i pretty much followed the documentation
int Paint::init(HWND hWND) {
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &object))) {
exit(1);
}
ZeroMemory(&params, sizeof(params));
params.BackBufferWidth = width;
params.BackBufferHeight = height;
params.Windowed = true;
params.hDeviceWindow = hWND;
params.MultiSampleQuality = D3DMULTISAMPLE_NONE;
params.BackBufferFormat = D3DFMT_A8R8G8B8;
params.EnableAutoDepthStencil = TRUE;
params.AutoDepthStencilFormat = D3DFMT_D16;
HRESULT res = object->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, &params, NULL, &device);
and in the header file:
class Paint {
private:
IDirect3D9Ex* object = NULL;
IDirect3DDevice9Ex* device = NULL;
DWORD behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
D3DPRESENT_PARAMETERS params;
ID3DXFont* font = 0;
HWND TargetHWND;
int width, height;
int init(HWND(hWND));
}
D3DPRESENT_PARAMETERS params = {};
// Use Win32 BOOL "TRUE" instead of C++ "true"
params.Windowed = TRUE;
params.hDeviceWindow = m_window;
// params.BackBufferWidth, BackBufferHeight are ignored for Windowed = TRUE
// For Windowed = TRUE, use params.BackBufferFormat = D3DFMT_UNKNOWN, which is zero.
// For params.BackBufferCount zero is assumed to be 1, but best practice
// would be to set it
params.BackBufferCount = 1;
// You used D3DMULTISAMPLE_NONE for the MultiSampleQuality instead of MultiSampleType.
// It's all zero anyhow.
params.EnableAutoDepthStencil = TRUE;
params.AutoDepthStencilFormat = D3DFMT_D16;
// --->>> This is the actual bug: there is no valid SwapEffect that has a value of zero <<<---
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
You are making the assumption that the Direct3D9 device supports D3DCREATE_HARDWARE_VERTEXPROCESSING, but you haven't validated it actually supports it. That said, D3DCREATE_SOFTWARE_VERTEXPROCESSING has known performance issues on Windows 10 so you should probably just require HW anyhow.
You should not be using legacy Direct3D9 or Direct3D9Ex for new projects. It's mostly emulated on newer versions of Windows, has lots of strange behaviors, and is almost 20 years old at this point. There's no support for the Direct3D 9 debug device on Windows 8.x or Windows 10. You should consider Direct3D 11 as a much better starting place for developers new to DirectX.

how do I get DirectX 11 debug layer working

I'm trying to get DirectX 11 debug layer working. So far I've enabled debugging on the device, and that's as far as I can get. I'm not getting any kind of debug output. All the guides I can find are basically just lumps of code without any real explanation of what's going on, so when it gets to applying what's in there to my specific problem it immediately breaks down and I get nowhere. I'm also not actually learning anything about how to use the debug layer, I'm not learning how to best utilise these technologies for my needs etc.
Basically, can anyone provide me with a step by step of how to get the debug output working?
This is what I've got so far:
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 4;
swapChainDesc.Windowed = true;
D3D_FEATURE_LEVEL featureLevels [] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
UINT creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL capabilities;
D3D11CreateDeviceAndSwapChain( NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
creationFlags,
featureLevels, //D3D_FEATURE_LEVEL *
ARRAYSIZE(featureLevels), //number of feature levels
D3D11_SDK_VERSION,
&swapChainDesc,
&m_swapChain,
&m_device,
&capabilities,
&m_devCon);
Thanks!

E_INVALIDARG One or more arguments are invalid. - CreateDevice

I have a d3dDevice:
ComPtr<ID3D11Device1>d3dDevice;
I use it here for the dxgiDevice:
ComPtr<IDXGIDevice3> dxgiDevice2;
HRESULT hr;
hr = d3dDevice.As( &dxgiDevice2 ); // S_OK
hr = d2dFactory->CreateDevice( dxgiDevice2.Get(), d2dDevice.GetAddressOf() ); // E_INVALIDARG One or more arguments are invalid
hr = d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&d2dDeviceContext
);
Why might this error be happening on runtime?
http://msdn.microsoft.com/en-us/library/windows/desktop/dn280482(v=vs.85).aspx
Entirety of my code that is relevant to problem: http://pastebin.com/P7Rs9xdh
The problem is that you haven't created your DX11 device to be compatible with Direct2D. You need to pass the correct creation flags and you should also consider defining the required feature level. Something like:
// This flag adds support for surfaces with a different color channel
// ordering than the API default.
// You need it for compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
// This array defines the set of DirectX hardware feature levels this
// app supports.
// The ordering is important and you should preserve it.
// Don't forget to declare your app's minimum required feature level in its
// description. All apps are assumed to support 9.1 unless otherwise stated.
D3D_FEATURE_LEVEL featureLevels[] =
{
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
};
D3D_FEATURE_LEVEL m_featureLevel;
// Create 3D device and device context objects
D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
creationFlags,
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&d3dDevice11,
&m_featureLevel,
&d3dDeviceContext11);

' Error Code: E_FAIL ' when creating DirectX 10 Device and Swap Chain

I am working though some simple DX tutorials of the book 'Introduction to 3D Game Programming with Direct3D 10.0'. I encountered some problems when I use the function of D3D10CreateDeviceAndSwapChain. The following is the codeļ¼š
// Fill out a DXGI_SWAP_CHAIN_DESC to describe our swap chain.
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = mClientWidth;
sd.BufferDesc.Height = mClientHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// No multisampling.
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = mhMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
// Create the device.
UINT createDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif
HR( D3D10CreateDeviceAndSwapChain(
0, //default adapter
md3dDriverType,
//D3D10_DRIVER_TYPE_HARDWARE,
0, // no software device
createDeviceFlags,
D3D10_SDK_VERSION,
&sd,
&mSwapChain,
&md3dDevice) );
And the error information is that:
Error Code: E_FAIL (0x80004005) Calling:D3D10CreateDeviceAndSwapChain(.....
when I change the parameter 'createDeviceFlags' of D3D10CreateDeviceAndSwapChain to 0 , then It works. But why?? I want to know the reason, who can tell me ???
MSDN Says
To create a device that supports the debug layer, you must install the DirectX SDK (to get D3D10SDKLayers.DLL), and then specify the D3D10_CREATE_DEVICE_DEBUG flag when calling D3D10CreateDevice.
So, did you install the SDK and do you have D3D10SDKLayers.DLL?
I'm having this exact problem. I got it to work when I switched out the D3D10_CREATE_DEVICE_DEBUG flag for 0. I think my computer is having trouble creating the debug layer for some reason. Not sure why, but at least I was able to create a window that way.
I have exactly the same issue with VS2010 on Windows 8 with DirectX SDK June 2010.
If I disable the debug layer everything works fine. This is of course rather annoying because the debug layer of DirectX is rather handy.
I also tried this workaround for a succesful installation of the DirectX SDK, but it didn't help me:
http://blogs.msdn.com/b/chuckw/archive/2011/12/09/known-issue-directx-sdk-june-2010-setup-and-the-s1023-error.aspx
Is there already a solution for this?

Create Swap Chain Failed 2.0

I had a problem with my D3D11CreateDeviceAndSwapChain(). I thought I got a solution in a prev thread, so I already marked it as solved. [Create Swap Chain Failed
Looks like I fooled myself when I accidentally returned the HRESULT as a bool...
I been fighting this problem all day & still have not figured it out. Here are bunch of debug info about the inputs & outputs...
1] Taking the advice to use UNKNOWN with a non-null vAdapter:
Debug Pic http://content.wuala.com/contents/RandomClown/Public/RandomCrap/Debug%201.png
2] Following the DX sample by leaving it null & using type HARDWARE:
Debug Pic http://content.wuala.com/contents/RandomClown/Public/RandomCrap/Debug%202.png
The pics might be enough for someone to spot out the problem, but in case it was something else, code:
// This is some relevant stuff [anything referenced] in the class.
Graphics(){
selectedVAdapter=NULL;
deviceInterface=NULL;
deviceContext=NULL;
swapChain=NULL;
}
bool initDevice(HWND &hWnd){
HRESULT success=S_OK;
D3D_FEATURE_LEVEL featureLevels[]={
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
};
uint featuresSize=ARRAYSIZE(featureLevels);
D3D_DRIVER_TYPE driverTypes[]={
D3D_DRIVER_TYPE_UNKNOWN, // Needed for manual vid adapter setting
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
uint driversSize=ARRAYSIZE(driverTypes);
refreshVideoAdapters();
setVideoAdapter();
//setSampleQuality();
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = settings.bufferCount;
sd.BufferDesc.Width = settings.width;
sd.BufferDesc.Height = settings.height;
sd.BufferDesc.Format = settings.colorDepth;
sd.BufferDesc.RefreshRate.Numerator = settings.rateNumerator;
sd.BufferDesc.RefreshRate.Denominator = settings.rateDenominator;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = settings.sampleCount;
sd.SampleDesc.Quality = settings.sampleQuality;
sd.Windowed = !settings.fullScreen;
uint flag=0;
#ifdef _DEBUG
flag|=D3D11_CREATE_DEVICE_DEBUG;
#endif
for(uint i=0; i<driversSize; i++){ // SwapChain: http://msdn.microsoft.com/en-us/library/ff476083%28v=vs.85%29.aspx
D3D_DRIVER_TYPE driver=driverTypes[i];
success=D3D11CreateDeviceAndSwapChain(
//NULL,
selectedVAdapter, driver, NULL, flag,
featureLevels, featuresSize, D3D11_SDK_VERSION, &sd,
&swapChain, &deviceInterface, &selectedFeatureLevel, &deviceContext);
if(SUCCEEDED(success)) break;
}
return SUCCEEDED(success);
}
// Methods to manage video adapters
void refreshVideoAdapters(){
IDXGIAdapter1* pAdapter;
IDXGIFactory1* pFactory=NULL;
uint lastID=0;
if(selectedVAdapter){
DXGI_ADAPTER_DESC1* desc=NULL;
selectedVAdapter->GetDesc1(desc);
lastID=desc->DeviceId;
releaseVideoAdapters();
}
if(FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))) return;
for(uint i=0; pFactory->EnumAdapters1(i, &pAdapter)!=DXGI_ERROR_NOT_FOUND; i++){
vAdapters.push_back(pAdapter);
if(lastID){
DXGI_ADAPTER_DESC1* desc=NULL;
pAdapter->GetDesc1(desc);
if(lastID==desc->DeviceId){
selectedVAdapter=pAdapter;
lastID=0;
}
}
}
if(pFactory) pFactory->Release();
}
void releaseVideoAdapters(){
for(uint i=0; i<vAdapters.size(); i++){
vAdapters[i]->Release();
vAdapters[i]=NULL;
}
vAdapters.clear();
selectedVAdapter=NULL;
}
IDXGIAdapter1* getVideoAdapter(){return selectedVAdapter;}
bool setVideoAdapter(uint num=0){
if(num<vAdapters.size()){
selectedVAdapter=vAdapters[num];
return 1;
}
return 0;
}
// Member vars
private:
SettingsGraphicsDevice settings;
D3D_FEATURE_LEVEL selectedFeatureLevel;
vector<IDXGIAdapter1*> vAdapters;
IDXGIAdapter1* selectedVAdapter;
ID3D11Device* deviceInterface;
ID3D11DeviceContext* deviceContext;
IDXGISwapChain* swapChain;
Settings struct from that code:
struct SettingsGraphicsDevice{
uint width, height;
bool fullScreen, vsync;
uint rateNumerator;
uint rateDenominator;
uint bufferCount;
uint sampleCount, sampleQuality;
DXGI_FORMAT colorDepth;
float minDist, maxDist;
SettingsGraphicsDevice(){
width=height=0;
fullScreen=0;
vsync=0;
rateNumerator=0;
rateDenominator=1;
bufferCount=1;
sampleCount=1, sampleQuality=0;
colorDepth=DXGI_FORMAT_R8G8B8A8_UINT;
minDist=0.1f;
maxDist=1000.0f;
}
};
Thanks for reading. Hope a solution is found this time.
Copy and Paste from my comment: "Also, a quick peek at my code shows that I use DXGI_FORMAT_R8G8B8A8_UNORM, although I currently have no clue whether that's the correct mode.". Ok, so it's in an answer now :-)
Yeah, the formats... the DXGI_FORMAT is a rather large enumeration, but in many situations only certain formats are allowed. It shouldn't be too surprising that only certain formats are allowed for displaying, whether it's fullscreen or not.
I got the value that I used from the docs (as usual), specifically the list in the DXGI_MODE_DESC description. I don't actually know whether I'm creating a blt-block transfer swapchain, but decided that these values are as good as any to start with, and even though I don't care about feature level 9 it seemed pretty safe :-)
I have no idea why your code seemed to work wit a null-adapter; I think that's confusing. Maybe the debug runtime would have caught it?
Switching to that color mode [DXGI_FORMAT_R8G8B8A8_UNORM] worked. I get S_OK now. Why do the other color modes exist if they dont work?