DirectX 11 CreateSwapChain() fails with error DXGI_ERROR_INVALID_CALL - c++

Everytime I try to create the swapChain it throws this error.
After hours searching for a fix for this I found nothing that worked for me.
Here's the important part of the code:
bool Direct3D::Initialize(HWND hWnd)
{
HRESULT hResult;
ID3D11Device* pDevice = NULL;
ID3D11DeviceContext* pDeviceContext = NULL;
IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pAdapter = NULL;
IDXGIFactory* pFactory = NULL;
IDXGISwapChain* pSwapChain = NULL;
D3D_FEATURE_LEVEL featureLevels[] = { //Add feature levels to support here
D3D_FEATURE_LEVEL_11_0
};
#ifdef _DEBUG
UINT deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG;
#else
UINT deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#endif
//Create the device and deviceContext
hResult = D3D11CreateDevice(NULL, //needs to be NULL if D3D_DRIVER_TYPE_HARDWARE is used; NULL takes the default adapter
D3D_DRIVER_TYPE_HARDWARE,
NULL, //needs to be not NULL if D3D_DRIVER_TYPE_SOFTWARE is used
deviceFlags,
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&pDevice,
NULL,
&pDeviceContext);
if (FAILED(hResult))
{
return false;
}
hResult = pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
if (FAILED(hResult))
{
return false;
}
hResult = pDXGIDevice->GetAdapter(&pAdapter);
if (FAILED(hResult))
{
return false;
}
hResult = pAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&pFactory);
if (FAILED(hResult))
{
return false;
}
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = 0; //Zero for evaluating it from the output window
bufferDesc.Height = 0; //Zero for evaluating it from the output window
bufferDesc.RefreshRate.Numerator = config.refreshRate;
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 = config.fullscreen;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG_DISPLAY_ONLY;
hResult = pFactory->CreateSwapChain(pDevice, &swapChainDesc, &pSwapChain);
CGE_SAFE_RELEASE(pDXGIDevice);
CGE_SAFE_RELEASE(pAdapter);
CGE_SAFE_RELEASE(pFactory);
if (FAILED(hResult))
{
return false;
}
return true;
}
Looking at the documentation for CreateSwapChain() it seems to be that pSwapChain has to be not NULL, but that doesn't make sense in my opinion because I want to specify pSwapChain with CreateSwapChain().
Does anyone know a solution for this problem?

Your IDXGISwapChain should be associated with SwapChainPanel XAML control(or HWND if you are running Win32 application). You can do initialization like this:
hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 );
if (SUCCEEDED(hr))
{
hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) );
}
This code is from microsoft Win32 DirectX sample.
https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef/view/Discussions#content
If you are running WinRT application you can look trough DirectX and XAML application template.

You are passing in the address of your Swap Chain Pointer. This is so the Create device and swap chain function can fill that pointer out with information. Here is a example.
//loop through our driver types till we find the one we will be using
for (unsigned int i = 0; i < DriverCount; i++)
{
//Create our device and swap chain
DXERROR = D3D11CreateDeviceAndSwapChain(nullptr, drivers[i], nullptr,
Flag, levels, LevelsCount, D3D11_SDK_VERSION, &SwapDesc, &DX.pSwapChain,
&DX.pDevice, &DX.FeatureLevel, &DX.pImmediateContext);
if (SUCCEEDED(DXERROR))
{
DX.DriverType = drivers[i];
break;
}
}

Related

D3D11CreateDeviceAndSwapChain fails with 887a0001

When I attempt to create a device and swapchain D3D11CreateDeviceAndSwapChain fails with 887a0001. I am trying to call this from my dll.
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = FALSE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
UINT createDeviceFlags = 0;
D3D_FEATURE_LEVEL featureLevel;
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
HRESULT res = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &swapchain, &device, &featureLevel, &devicecontext);
if (res != S_OK) {
printf("failed to create device and swap %llx\n", res);
return false;
}
Ive seen a few issue resolved by threading it differently but I havent had any luck in doing so.
__int32 __stdcall DllMain(void* baseaddress)
{
Start();
return 1;
}
The function start is where I create my window, attempt to create my device and thread the message dispatcher
If you debug your program, you should see this in the output:
DXGI ERROR: CreateDXGIFactory cannot be called from DllMain. [ MISCELLANEOUS ERROR #76: ]
This is expected as explained here: DXGI responses from DLLMain (D3D11CreateDeviceAndSwapChain will implicitly create a DXGI factory)
If your app's DllMain function creates a DXGI factory, DXGI returns an
error code.
So, you must not call this from DllMain (this is anynay a very special place where some black magic voodoo happens.)

C++ Capture Full screen in real time

I'm developing a software that should capture what is happening on the screen to make some processing. One of the requirements is that the software has to run at least 30FPS.
I've tried several options and I'm going to shopw you two, But none of them fully works to my needs:
(1) Using Direct X - The problem with this approach is that I cannot run it at 30 FPS (I get between 15 and 20):
DirectXScreenCapturer.h:
#include "IScreenCapturer.h"
#include <Wincodec.h> // we use WIC for saving images
#include <d3d9.h> // DirectX 9 header
#pragma comment(lib, "d3d9.lib") // link to DirectX 9 library
class DirectXScreenCapturer : public IScreenCapturer
{
public:
DirectXScreenCapturer();
~DirectXScreenCapturer();
virtual bool CaptureScreen(cv::Mat&) override;
private:
IDirect3D9* _d3d;
IDirect3DDevice9* _device;
IDirect3DSurface9* _surface;
cv::Mat _screen;
};
DirectXScreenCapturer.cpp:
#include "DirectXScreenCapturer.h"
DirectXScreenCapturer::DirectXScreenCapturer() : _d3d(NULL), _device(NULL), _surface(NULL)
{
HRESULT hr = S_OK;
D3DPRESENT_PARAMETERS parameters = { 0 };
D3DDISPLAYMODE mode;
D3DLOCKED_RECT rc;
LPBYTE *shots = nullptr;
// init D3D and get screen size
_d3d = Direct3DCreate9(D3D_SDK_VERSION);
_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
parameters.Windowed = TRUE;
parameters.BackBufferCount = 1;
parameters.BackBufferHeight = mode.Height;
parameters.BackBufferWidth = mode.Width;
parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
parameters.hDeviceWindow = NULL;
// create device & capture surface
hr = _d3d->CreateDevice(D3DADAPTER_DEFAULT, _D3DDEVTYPE::D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_PSGP_THREADING | D3DCREATE_PUREDEVICE, &parameters, &_device);
hr = _device->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &_surface, nullptr);
// compute the required buffer size
hr = _surface->LockRect(&rc, NULL, 0);
hr = _surface->UnlockRect();
// allocate screenshots buffers
_screen = cv::Mat(mode.Height, mode.Width, CV_8UC4, rc.pBits);
}
DirectXScreenCapturer::~DirectXScreenCapturer()
{
}
bool DirectXScreenCapturer::CaptureScreen(cv::Mat& result)
{
_device->GetFrontBufferData(0, _surface);
result = _screen;
return true;
}
(2) I've tried DXGI with Direct X. This solution works really well in Real Time, but fails to capture the screen when another application is running in full screen, so the software doesn't work if I'm watching movies, playign games, etc:
DXGIScreenCapturer.h
#include "IScreenCapturer.h"
#include <DXGI1_2.h>
#pragma comment(lib, "Dxgi.lib")
#include <D3D11.h>
#pragma comment(lib, "D3D11.lib")
class DXGIScreenCapturer : public IScreenCapturer
{
public:
DXGIScreenCapturer();
~DXGIScreenCapturer();
bool Init();
virtual bool CaptureScreen(cv::Mat&) override;
private:
ID3D11Device* _lDevice;
ID3D11DeviceContext* _lImmediateContext;
IDXGIOutputDuplication* _lDeskDupl;
ID3D11Texture2D* _lAcquiredDesktopImage;
DXGI_OUTPUT_DESC _lOutputDesc;
DXGI_OUTDUPL_DESC _lOutputDuplDesc;
D3D11_MAPPED_SUBRESOURCE _resource;
ID3D11Texture2D* currTexture;
cv::Mat _result;
};
DXGIScreenCapturer.cpp
#include "DXGIScreenCapturer.h"
DXGIScreenCapturer::DXGIScreenCapturer()
{
Init();
}
DXGIScreenCapturer::~DXGIScreenCapturer()
{
}
bool DXGIScreenCapturer::Init() {
// Feature levels supported
D3D_FEATURE_LEVEL gFeatureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT gNumFeatureLevels = ARRAYSIZE(gFeatureLevels);
D3D_FEATURE_LEVEL lFeatureLevel;
HRESULT hr(E_FAIL);
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_SINGLETHREADED, gFeatureLevels, gNumFeatureLevels, D3D11_SDK_VERSION, &_lDevice, &lFeatureLevel, &_lImmediateContext);
if (FAILED(hr))
return false;
if (!_lDevice)
return false;
// Get DXGI device
IDXGIDevice* lDxgiDevice;
hr = _lDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&lDxgiDevice));
if (FAILED(hr))
return false;
// Get DXGI adapter
IDXGIAdapter* lDxgiAdapter;
hr = lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&lDxgiAdapter));
lDxgiDevice->Release();
lDxgiDevice = nullptr;
if (FAILED(hr))
return false;
UINT Output = 0;
// Get output
IDXGIOutput* lDxgiOutput;
hr = lDxgiAdapter->EnumOutputs(Output, &lDxgiOutput);
if (FAILED(hr))
return false;
lDxgiAdapter->Release();
lDxgiAdapter = nullptr;
hr = lDxgiOutput->GetDesc(&_lOutputDesc);
if (FAILED(hr))
return false;
// QI for Output 1
IDXGIOutput1* lDxgiOutput1;
hr = lDxgiOutput->QueryInterface(__uuidof(lDxgiOutput1), reinterpret_cast<void**>(&lDxgiOutput1));
lDxgiOutput->Release();
lDxgiOutput = nullptr;
if (FAILED(hr))
return false;
// Create desktop duplication
hr = lDxgiOutput1->DuplicateOutput(_lDevice, &_lDeskDupl);
if (FAILED(hr))
return false;
lDxgiOutput1->Release();
lDxgiOutput1 = nullptr;
// Create GUI drawing texture
_lDeskDupl->GetDesc(&_lOutputDuplDesc);
// Create CPU access texture
D3D11_TEXTURE2D_DESC desc;
desc.Width = _lOutputDuplDesc.ModeDesc.Width;
desc.Height = _lOutputDuplDesc.ModeDesc.Height;
desc.Format = _lOutputDuplDesc.ModeDesc.Format;
desc.ArraySize = 1;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_FLAG::D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE::D3D11_USAGE_STAGING;
hr = _lDevice->CreateTexture2D(&desc, NULL, &currTexture);
if (!currTexture)
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
while (!CaptureScreen(_result));
_result = cv::Mat(desc.Height, desc.Width, CV_8UC4, _resource.pData);
return true;
}
bool DXGIScreenCapturer::CaptureScreen(cv::Mat& output)
{
HRESULT hr(E_FAIL);
IDXGIResource* lDesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO lFrameInfo;
hr = _lDeskDupl->AcquireNextFrame(999, &lFrameInfo, &lDesktopResource);
if (FAILED(hr))
return false;
if (lFrameInfo.LastPresentTime.HighPart == 0) // not interested in just mouse updates, which can happen much faster than 60fps if you really shake the mouse
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
// QI for ID3D11Texture2D
hr = lDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&_lAcquiredDesktopImage));
lDesktopResource->Release();
lDesktopResource = nullptr;
if (FAILED(hr))
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
_lImmediateContext->CopyResource(currTexture, _lAcquiredDesktopImage);
UINT subresource = D3D11CalcSubresource(0, 0, 0);
_lImmediateContext->Map(currTexture, subresource, D3D11_MAP_READ, 0, &_resource);
_lImmediateContext->Unmap(currTexture, 0);
hr = _lDeskDupl->ReleaseFrame();
output = _result;
return true;
}
Please note that IScreenCapturer is just and interface to quickly swap implementations and also note that the return result is a cv::Mat object (OpenCV to do the rest of processing).
Any help on this issue? I'm still trying to figure out a solution that can capture the screen at least 30 FPS and that can capture the whole screen even when an app is running at full screen.

DirectX11 DXGI Capture Screen when in full screen

I'm currently trying to develop a personal project where I will light up LEDs according to what's happening on the screen of my computer.
I've tried several solutions to capture my screen, and DirectX11 with DXGI is the fastest way I found to have a good FPS Rate.
My only issue is the following: When in full screen (for example, watching Netflix trogh Win10 App or playing any game in fullscreen), it seems that nothing is captured. I have two functions (one to set up and another one to capture a frame:
Setup Up Function:
bool DXGIScreenCapturer::Init() {
int lresult(-1);
D3D_FEATURE_LEVEL lFeatureLevel;
HRESULT hr(E_FAIL);
hr = D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
0,
gFeatureLevels,
gNumFeatureLevels,
D3D11_SDK_VERSION,
&_lDevice,
&lFeatureLevel,
&_lImmediateContext);
if (FAILED(hr))
return false;
if (!_lDevice)
return false;
// Get DXGI device
ComPtr<IDXGIDevice> lDxgiDevice;
hr = _lDevice.As(&lDxgiDevice);
if (FAILED(hr))
return false;
// Get DXGI adapter
ComPtr<IDXGIAdapter> lDxgiAdapter;
hr = lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), &lDxgiAdapter);
if (FAILED(hr))
return false;
lDxgiDevice.Reset();
UINT Output = 0;
// Get output
ComPtr<IDXGIOutput> lDxgiOutput;
hr = lDxgiAdapter->EnumOutputs(Output, &lDxgiOutput);
if (FAILED(hr))
return false;
lDxgiAdapter.Reset();
hr = lDxgiOutput->GetDesc(&_lOutputDesc);
if (FAILED(hr))
return false;
// QI for Output 1
ComPtr<IDXGIOutput1> lDxgiOutput1;
hr = lDxgiOutput.As(&lDxgiOutput1);
if (FAILED(hr))
return false;
lDxgiOutput.Reset();
// Create desktop duplication
hr = lDxgiOutput1->DuplicateOutput(_lDevice.Get(), &_lDeskDupl);
if (FAILED(hr))
return false;
lDxgiOutput1.Reset();
// Create GUI drawing texture
_lDeskDupl->GetDesc(&_lOutputDuplDesc);
// Create CPU access texture
_desc.Width = _lOutputDuplDesc.ModeDesc.Width;
_desc.Height = _lOutputDuplDesc.ModeDesc.Height;
_desc.Format = _lOutputDuplDesc.ModeDesc.Format;
std::cout << _desc.Width << "x" << _desc.Height << "\n\n\n";
_desc.ArraySize = 1;
_desc.BindFlags = 0;
_desc.MiscFlags = 0;
_desc.SampleDesc.Count = 1;
_desc.SampleDesc.Quality = 0;
_desc.MipLevels = 1;
_desc.CPUAccessFlags = D3D11_CPU_ACCESS_FLAG::D3D11_CPU_ACCESS_READ;
_desc.Usage = D3D11_USAGE::D3D11_USAGE_STAGING;
while (!CaptureScreen(_result));
_result = cv::Mat(_desc.Height, _desc.Width, CV_8UC4, _resource.pData);
return true;
}
And the capture function:
bool DXGIScreenCapturer::CaptureScreen(cv::Mat& output)
{
HRESULT hr(E_FAIL);
ComPtr<IDXGIResource> lDesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO lFrameInfo;
ID3D11Texture2D* currTexture = NULL;
hr = _lDeskDupl->AcquireNextFrame(999, &lFrameInfo, &lDesktopResource);
if (FAILED(hr))
return false;
if (lFrameInfo.LastPresentTime.HighPart == 0) // not interested in just mouse updates, which can happen much faster than 60fps if you really shake the mouse
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
//int accum_frames = lFrameInfo.AccumulatedFrames;
//if (accum_frames > 1) {// && current_frame != 1) {
// // TOO MANY OF THESE is the problem
// // especially after having to wait >17ms in AcquireNextFrame()
//}
// QI for ID3D11Texture2D
hr = lDesktopResource.As(&_lAcquiredDesktopImage);
// Copy image into a newly created CPU access texture
hr = _lDevice->CreateTexture2D(&_desc, NULL, &currTexture);
if (FAILED(hr))
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
if (!currTexture)
{
hr = _lDeskDupl->ReleaseFrame();
return false;
}
_lImmediateContext->CopyResource(currTexture, _lAcquiredDesktopImage.Get());
UINT subresource = D3D11CalcSubresource(0, 0, 0);
_lImmediateContext->Map(currTexture, subresource, D3D11_MAP_READ, 0, &_resource);
_lImmediateContext->Unmap(currTexture, 0);
currTexture->Release();
hr = _lDeskDupl->ReleaseFrame();
output = _result;
return true;
}

DirectX 11 IDXGISwapChain::GetBuffer failing with DXGI_ERROR_INVALID_CALL

I am creating a device and swap chain in DirectX11, then trying to get the texture of the back-buffer. The creation step appears to work but the GetBuffer call always fails with error DXGI_ERROR_INVALID_CALL (887a0001), regardless of what I do.
Here is the code for creating the device:
D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_1 };
int numFeatureLevels = sizeof(featureLevels) / sizeof(featureLevels[0]);
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ID3D11Device* pDevice;
IDXGISwapChain* pSwapChain;
D3D_FEATURE_LEVEL featureLevel;
ID3D11DeviceContext* pContext;
swapChainDesc.Windowed = TRUE;
swapChainDesc.OutputWindow = (HWND)(void*)pWindowHandle;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.Width = 0;
swapChainDesc.BufferDesc.Height = 0;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferUsage = DXGI_USAGE_SHADER_INPUT|DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Flags = 0;
err = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevels, numFeatureLevels, D3D11_SDK_VERSION,
&swapChainDesc, &pSwapChain, &pDevice, &featureLevel, &pContext);
if (!SUCCEEDED(err))
{
printf("D3D11CreateDeviceAndSwapChain failed with error %08x\n", err);
return false;
}
m_pDevice = pDevice;
m_pSwapChain = pSwapChain;
m_pDeviceContext = pContext;
m_featureLevel = featureLevel;
ID3D11Texture2D* pTex = NULL;
err = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)pTex);
if (!SUCCEEDED(err))
{
printf("GetBuffer failed with error %08x\n", err);
return false;
}
This is Managed C++ which is compiled into a DLL and run from a C# control's OnCreateControl method, which passes Handle into the function as pWindowHandle.
The create device call succeeds, giving me FEATURE_LEVEL_11_0, but the second printf function is always printing error 887a0001. Using the reference device does not help. I'm linking against d3dx11.lib, d3d11.lib, dxgi.lib, dxguid.lib, d3dcompiler.lib, d3d10.lib and d3dx10.lib.
I tried replacing the __uuidof with IID_ID3D11Texture2D and that made no difference.
I am using Visual Studio Express 2013 for Windows Desktop, on Windows 7, and the Microsoft DirectX SDK (June 2010). All x86 and x64, Debug and Release builds suffer from the same problem. My attempts to enable verbose debug output also fail; I have tried to force it on via the DirectX Properties in Control Panel, adding my program to the list of executables, but nothing extra is printed at runtime.
You've just passed the final argument incorrectly. Instead of this:
err = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)pTex);
You should be passing a pointer to the interface pointer, like this:
err = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pTex);
^
|

Creating a DirectX10 Swapchain and Device by passing in a IDXGIAdapter

I am attempting to create a device and swapchain from a IDXGIAdapter. All my code succeeds untill a call to CreateSwapChain which returns DXGI_ERROR_INVALID_CALL.
MSDN says a return of DXGI_ERROR_INVALID_CALL can happen when DXGI_SWAP_CHAIN_DESC is null or the IDXGISwapChain** is null.
Im not really sure what it means by "IDXGISwapChain** is null" seeing as it is the output (im guessing it is when you actually type NULL.
my swapchain is defined as...
IDXGISwapChain* m_pSwapChain;
and my other code is...
IDXGIAdapter * pPrimaryAdapter = m_vAdapters.at(0);
HRESULT hr = D3D10CreateDevice(pPrimaryAdapter,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
NULL,//D3D10_CREATE_DEVICE_SINGLETHREADED
D3D10_SDK_VERSION,
&m_pD3DDevice);
if(hr != S_OK)
{
MessageBox(NULL, L"Error ###: Creation of Direct3D10 Device Failed", 0, 0);
return false;
}
//m_pDXGIFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER );
if(FAILED(m_pDXGIFactory->MakeWindowAssociation(hWnd, 0 )))
{
MessageBox(0, L"Error ###: MakeWindowAssociation Failed", 0,0);
return false;
}
IDXGIDevice * pDXGIDevice;
if(FAILED(m_pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice)))
{
MessageBox(0, L"QueryInterface pDXGIDevice Failed", 0,0);
return false;
}
DXGI_SWAP_CHAIN_DESC SwapChainDesc;
SwapChainDesc.BufferCount = 1;
SwapChainDesc.BufferDesc.Width = 800;
SwapChainDesc.BufferDesc.Height = 600;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.OutputWindow = hWnd;
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Windowed = TRUE;
hr = m_pDXGIFactory->CreateSwapChain(pDXGIDevice, &SwapChainDesc, &m_pSwapChain);
switch(hr)
{
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
{
MessageBox(NULL, L"CreateSwapChainFailure: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE", 0,0);
return false;
}break;
case DXGI_ERROR_INVALID_CALL:
{
MessageBox(NULL, L"CreateSwapChainFailure: DXGI_ERROR_INVALID_CALL", 0, 0);
return false;
}break;
};
have you tried zeroing the memory of SwapChainDesc before assigning values? You didn't specify all the values of the structure, so unless it's zeroed some of the parameters might be invalid.
Try:
DXGI_SWAP_CHAIN_DESC SwapChainDesc;
ZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc));
SwapChainDesc.BufferCount = 1;
....