Direct X: How to display an image loaded in a texture? - c++

I'm new to DirectX and have been reading tons of tutorials and samples, however I'm unable to find any documentation on how to directly display an image that is loaded into a Texture2D on the screen. Almost all tutorials I've seen deal with 3D graphics, shaders, etc. However, I just want to display the contents of the texture.
Here's what I have so far:
DeviceResources.cpp:
#include "DeviceResources.h"
#include "Renderer.h"
DeviceResources::DeviceResources()
{
}
HRESULT DeviceResources::CreateDeviceResources(HWND hwnd)
{
D3D_FEATURE_LEVEL levels[] = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_12_1
};
UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
DXGI_SWAP_CHAIN_DESC swap_chain_desc;
ZeroMemory(&swap_chain_desc, sizeof(DXGI_SWAP_CHAIN_DESC));
swap_chain_desc.Windowed = TRUE;
swap_chain_desc.BufferCount = 2;
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swap_chain_desc.OutputWindow = hwnd;
Microsoft::WRL::ComPtr<ID3D11Device> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
flags,
levels,
ARRAYSIZE(levels),
D3D11_SDK_VERSION,
&swap_chain_desc,
swapChain.GetAddressOf(),
device.GetAddressOf(),
&m_feature_level,
context.GetAddressOf()
);
device.As(&m_device);
context.As(&m_context);
swapChain.As(&m_swapChain);
cv::directx::ocl::initializeContextFromD3D11Device(m_device.Get());
auto hdr = Renderer::HDRMetadata();
m_swapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(DXGI_HDR_METADATA_HDR10), &hdr);
m_swapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), static_cast<void**>(& m_backBuffer));
m_backBuffer->GetDesc(&m_bbDesc);
ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));
m_viewport.Height = static_cast<float>(m_bbDesc.Height);
m_viewport.Width = static_cast<float>(m_bbDesc.Width);
m_viewport.MinDepth = 0;
m_viewport.MaxDepth = 1;
m_context->RSSetViewports(1, &m_viewport);
m_device->CreateRenderTargetView(m_backBuffer.Get(), nullptr, m_renderTargetView.GetAddressOf());
return S_OK;
}
HRESULT DeviceResources::ConfigureBackBuffer()
{
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), static_cast<void**>(& m_backBuffer));
m_device->CreateRenderTargetView(m_backBuffer.Get(), nullptr, m_renderTargetView.GetAddressOf());
m_backBuffer->GetDesc(&m_bbDesc);
ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));
m_viewport.Height = static_cast<float>(m_bbDesc.Height);
m_viewport.Width = static_cast<float>(m_bbDesc.Width);
m_viewport.MinDepth = 0;
m_viewport.MaxDepth = 1;
m_context->RSSetViewports(1, &m_viewport);
return S_OK;
}
HRESULT DeviceResources::ReleaseBackBuffer()
{
m_renderTargetView.Reset();
m_backBuffer.Reset();
m_context->Flush();
return S_OK;
}
HRESULT DeviceResources::SetFullscreen(bool fullscreen)
{
m_swapChain->SetFullscreenState(fullscreen, nullptr);
ReleaseBackBuffer();
m_swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
ConfigureBackBuffer();
return S_OK;
}
void DeviceResources::Present()
{
m_swapChain->Present(1, 0);
}
DeviceResources::~DeviceResources()
= default;
Renderer.cpp:
#include "Renderer.h"
#include <utility>
#include <comdef.h>
#include <vector>
Renderer::Renderer(std::shared_ptr<DeviceResources> resources) : m_resources(std::move(resources)), m_frameCount(0)
{
m_frameCount = 0;
}
HRESULT Renderer::CreateDeviceDependentResources()
{
return S_OK;
}
HRESULT Renderer::CreateWindowSizeDependentResources()
{
return S_OK;
}
void Renderer::Update()
{
//
}
void Renderer::Render()
{
cv::Mat mat = cv::imread("C:/Users/Richard/Downloads/orig_cave_L.ppm", cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
cv::Mat as4channelMat(mat.size(), CV_MAKE_TYPE(mat.depth(), 4));
int conversion[] = { 0, 0, 1, 1, 2, 2, -1, 3 };
cv::mixChannels(&mat, 1, &as4channelMat, 1, conversion, 4);
D3D11_TEXTURE2D_DESC desc;
desc.Width = 3840;
desc.Height = 2160;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R16G16B16A16_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
ID3D11Texture2D* tex = nullptr;
auto hr = m_resources->GetDevice()->CreateTexture2D(&desc, nullptr, &tex);
if FAILED(hr)
{
_com_error err(hr);
auto errMsg = err.ErrorMessage();
}
try {
cv::directx::convertToD3D11Texture2D(as4channelMat, tex);
} catch (cv::Exception& e)
{
std::cerr << "ERROR: " << e.msg << std::endl;
throw e;
}
auto hr3 = m_resources->m_device->CreateShaderResourceView(tex.Get(), nullptr, m_texture.GetAddressOf());
if FAILED(hr3)
{
_com_error err(hr3);
auto errMsg = err.ErrorMessage();
}
std::unique_ptr<DirectX::SpriteBatch> m_spriteBatch;
DirectX::SimpleMath::Vector2 m_screenPos, m_origin;
m_spriteBatch = std::make_unique<DirectX::SpriteBatch>(m_resources->m_context.Get());
CD3D11_TEXTURE2D_DESC catDesc;
tex->GetDesc(&catDesc);
m_origin.x = float(catDesc.Width / 2);
m_origin.y = float(catDesc.Height / 2);
m_screenPos.x = m_resources->m_bbDesc.Width / 2.f;
m_screenPos.y = m_resources->m_bbDesc.Height / 2.f;
m_spriteBatch->Begin();
m_spriteBatch->Draw(
m_texture.Get(),
m_screenPos,
nullptr,
DirectX::Colors::White,
0.0f,
m_origin
);
m_spriteBatch->End();
}
DXGI_HDR_METADATA_HDR10 Renderer::HDRMetadata()
{
//
}
Renderer::~Renderer()
{
}
From my understand, I have to somehow create a "Quad", apply the texture to it, and then display the quad itself. However,I am unsure how to do any of this and can't find any resources to help.
Edit: Given the recommendations, I have tried using DirectXTK, specifically SpriteBatch. I followed the relevant instructions in the documentation, however Draw doesn't seem to do / display anything. (In Renderer.cpp)

Related

Error passing CoreWindow as function parameter

I am new to UWP and WinRT, I already knew DirectX11 and Win32 and I am quite interested in learning UWP and WinRT.
DXMainResources is a class to use Diret3D and Direct2D, and the most important thing when creating resources is the window (CoreWindow), however, when passing the window as a function parameter, many errors appear such as:
C2065 error 'bEnableDepthStencilBuffer': undeclared identifier
Error C2065 'window': undeclared identifier
Error C2065 'window_': undeclared identifier
Faced with these errors, remove the CoreWindow window parameter and the program compiles, but the window as a parameter is necessary, since I need its height and width to create the swap chain and the texture for the depth stencil view.
Is there a way to pass the window as a parameter?
I'm using DirectX 11.3 interfaces and the WinRT version I'm using is 2.0.201026.4
#pragma once
#include "pch.h"
#include <d3d11_3.h>
#include <d2d1_3.h>
#include <dxgi1_4.h>
#include <dwrite_3.h>
#include <array>
using namespace D2D1;
template<class Interface> void TSafeRelease(Interface** ppInterface)
{
if (*ppInterface)
{
(*ppInterface)->Release();
(*ppInterface) = nullptr;
}
}
class DXMainResources
{
public:
DXMainResources()
{
d3dDev = nullptr;
d3dDevContext = nullptr;
d3dRTView = nullptr;
d3dDSView = nullptr;
d2dDev = nullptr;
d2dDevContext = nullptr;
d2dTargetBitmap = nullptr;
dxgiFactory = nullptr;
dxgiDev = nullptr;
dxgiDefaultAdapter = nullptr;
dxgiSwapChain = nullptr;
dwriteFactory = nullptr;
dwriteTextFmt = nullptr;
featureLevel = static_cast<D3D_FEATURE_LEVEL>(0);
dxgiSwapChainFmt = DXGI_FORMAT_UNKNOWN;
dxgiDepthStencilFmt = DXGI_FORMAT_UNKNOWN;
viewPort = D3D11_VIEWPORT();
}
~DXMainResources()
{
}
void CreateResources(CoreWindow const& window, bool bOnlyDirect2D = false, bool bEnableDepthStencilBuffer = true
, DXGI_FORMAT dxgiSwapChainFmt_ = DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT dxgiDepthStencilFmt_ = DXGI_FORMAT_D24_UNORM_S8_UINT
, DXGI_SWAP_EFFECT swapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL)
{
dxgiSwapChainFmt = dxgiSwapChainFmt_;
dxgiDepthStencilFmt = dxgiDepthStencilFmt_;
CoreWindow window_ = window;
std::array<D3D_FEATURE_LEVEL, 9> featureLevels =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
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,
};
UINT deviceFlags = D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT;
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, deviceFlags, featureLevels.data(), static_cast<UINT>(std::size(featureLevels))
, D3D11_SDK_VERSION, reinterpret_cast<ID3D11Device**>(&d3dDev), &featureLevel, nullptr);
hr = d3dDev->QueryInterface(__uuidof(IDXGIDevice3), reinterpret_cast<void**>(&dxgiDev));
hr = dxgiDev->GetAdapter(reinterpret_cast<IDXGIAdapter**>(&dxgiDefaultAdapter));
hr = dxgiDefaultAdapter->GetParent(__uuidof(IDXGIFactory4), reinterpret_cast<void**>(&dxgiFactory));
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC1));
swapChainDesc.BufferCount = 2;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Format = dxgiSwapChainFmt_;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SwapEffect = swapEffect;
hr = dxgiFactory->CreateSwapChainForCoreWindow(d3dDev, reinterpret_cast<IUnknown*>(window_)
, &swapChainDesc, nullptr, reinterpret_cast<IDXGISwapChain1**>(&dxgiSwapChain));
if (bOnlyDirect2D)
{
IDXGISurface2* dxgiBackBufferSurface = nullptr;
hr = dxgiSwapChain->GetBuffer(0, __uuidof(IDXGISurface2), reinterpret_cast<void**>(&dxgiBackBufferSurface));
D2D1_CREATION_PROPERTIES creationProps = CreationProperties(D2D1_THREADING_MODE_SINGLE_THREADED, D2D1_DEBUG_LEVEL_INFORMATION, D2D1_DEVICE_CONTEXT_OPTIONS_NONE);
D2D1_BITMAP_PROPERTIES1 bmpProps = BitmapProperties1(D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_TARGET
, PixelFormat(dxgiSwapChainFmt_, D2D1_ALPHA_MODE_IGNORE));
hr = D2D1CreateDevice(dxgiDev, creationProps, reinterpret_cast<ID2D1Device**>(&d2dDev));
hr = d2dDev->CreateDeviceContext(creationProps.options, &d2dDevContext);
hr = d2dDevContext->CreateBitmapFromDxgiSurface(dxgiBackBufferSurface, bmpProps, &d2dTargetBitmap);
d2dDevContext->SetTarget(d2dTargetBitmap);
TSafeRelease(&dxgiBackBufferSurface);
}
else
{
IDXGISurface2* dxgiBackBufferSurface = nullptr;
hr = dxgiSwapChain->GetBuffer(0, __uuidof(IDXGISurface2), reinterpret_cast<void**>(&dxgiBackBufferSurface));
D2D1_CREATION_PROPERTIES creationProps = CreationProperties(D2D1_THREADING_MODE_SINGLE_THREADED, D2D1_DEBUG_LEVEL_INFORMATION, D2D1_DEVICE_CONTEXT_OPTIONS_NONE);
D2D1_BITMAP_PROPERTIES1 bmpProps = BitmapProperties1(D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_TARGET
, PixelFormat(dxgiSwapChainFmt_, D2D1_ALPHA_MODE_IGNORE));
hr = D2D1CreateDevice(dxgiDev, creationProps, reinterpret_cast<ID2D1Device**>(&d2dDev));
hr = d2dDev->CreateDeviceContext(creationProps.options, &d2dDevContext);
hr = d2dDevContext->CreateBitmapFromDxgiSurface(dxgiBackBufferSurface, bmpProps, &d2dTargetBitmap);
d2dDevContext->SetTarget(d2dTargetBitmap);
TSafeRelease(&dxgiBackBufferSurface);
d3dDev->GetImmediateContext3(&d3dDevContext);
ID3D11Texture2D1* d3dBackBufferTex = nullptr;
hr = dxgiSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D1), reinterpret_cast<void**>(&d3dBackBufferTex));
hr = d3dDev->CreateRenderTargetView1(d3dBackBufferTex, nullptr, &d3dRTView);
TSafeRelease(&d3dBackBufferTex);
if (bEnableDepthStencilBuffer)
{
ID3D11Texture2D1* d3dDepthStencilTex = nullptr;
D3D11_TEXTURE2D_DESC1 depthStencilTexDesc;
ZeroMemory(&depthStencilTexDesc, sizeof(D3D11_TEXTURE2D_DESC1));
depthStencilTexDesc.ArraySize = 1;
depthStencilTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilTexDesc.Format = dxgiDepthStencilFmt_;
depthStencilTexDesc.Height = window_.Bounds().Height;
depthStencilTexDesc.MipLevels = 1;
depthStencilTexDesc.SampleDesc.Count = 1;
depthStencilTexDesc.Width = window_.Bounds().Width;
hr = d3dDev->CreateTexture2D1(&depthStencilTexDesc, nullptr, &d3dDepthStencilTex);
hr = d3dDev->CreateDepthStencilView(d3dDepthStencilTex, nullptr, &d3dDSView);
d3dDevContext->OMSetRenderTargets(1, reinterpret_cast<ID3D11RenderTargetView**>(&d3dRTView), d3dDSView);
TSafeRelease(&d3dDepthStencilTex);
}
else
{
d3dDevContext->OMSetRenderTargets(1, reinterpret_cast<ID3D11RenderTargetView**>(&d3dRTView), nullptr);
}
viewPort.Height = window_.Bounds().Height;
viewPort.MaxDepth = 1.0f;
viewPort.Width = window_.Bounds().Width;
d3dDevContext->RSSetViewports(1, &viewPort);
}
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), reinterpret_cast<IUnknown**>(&dwriteFactory));
hr = dwriteFactory->CreateTextFormat(L"Segoe", nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 11.0f
, L"en-US", reinterpret_cast<IDWriteTextFormat**>(&dwriteTextFmt));
}
ID3D11Device3* GetD3D11Device() const { return d3dDev; }
ID3D11DeviceContext3* GetD3D11DeviceContext() const { return d3dDevContext; }
ID3D11RenderTargetView1* GetD3D11RenderTargetView() const { return d3dRTView; }
ID3D11DepthStencilView* GetD3D11DepthStencilView() const { return d3dDSView; }
ID2D1Device2* GetD2DDevice() const { return d2dDev; }
ID2D1DeviceContext2* GetD2DDeviceContext() const { return d2dDevContext; }
ID2D1Bitmap1* GetD2DTargetBitmap() const { return d2dTargetBitmap; }
IDXGIFactory4* GetDXGIFactory() const { return dxgiFactory; }
IDXGIDevice3* GetDXGIDevice() const { return dxgiDev; }
IDXGIAdapter3* GetDXGIDefaultAdapter() const { return dxgiDefaultAdapter; }
IDXGISwapChain3* GetDXGISwapChain() const { return dxgiSwapChain; }
IDWriteFactory* GetDWriteFactory() const { return dwriteFactory; }
IDWriteTextFormat3* GetDWriteTextFormat() const { return dwriteTextFmt; }
D3D_FEATURE_LEVEL GetD3DDeviceFeatureLevel() { return featureLevel; }
DXGI_FORMAT GetDXGISwapChainFormat() { return dxgiSwapChainFmt; }
DXGI_FORMAT GetDXGIDepthStencilFormat() { return dxgiDepthStencilFmt; }
D3D11_VIEWPORT GetD3D11ViewPort() { return viewPort; }
private:
ID3D11Device3* d3dDev;
ID3D11DeviceContext3* d3dDevContext;
ID3D11RenderTargetView1* d3dRTView;
ID3D11DepthStencilView* d3dDSView;
ID2D1Device2* d2dDev;
ID2D1DeviceContext2* d2dDevContext;
ID2D1Bitmap1* d2dTargetBitmap;
IDXGIFactory4* dxgiFactory;
IDXGIDevice3* dxgiDev;
IDXGIAdapter3* dxgiDefaultAdapter;
IDXGISwapChain3* dxgiSwapChain;
IDWriteFactory* dwriteFactory;
IDWriteTextFormat3* dwriteTextFmt;
D3D_FEATURE_LEVEL featureLevel;
DXGI_FORMAT dxgiSwapChainFmt;
DXGI_FORMAT dxgiDepthStencilFmt;
D3D11_VIEWPORT viewPort;
};
Refer to the Important in the document, please add the following #include statement and using statement, then try to compile your project.
#include <winrt/Windows.UI.Core.h>
using namespace winrt::Windows::UI::Core;

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.

Extract dirty rects RGB pixel buffer data DirectX

I'm using Desktop Duplication from Windows API.
Here is the code to access next frame and get the rectangle of pixels that have change from previous frame.
//
// Get next frame and write it into Data
//
_Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS)
DUPL_RETURN DUPLICATIONMANAGER::GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout)
{
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
// Get new frame
HRESULT hr = m_DeskDupl->AcquireNextFrame(10000, &FrameInfo, &DesktopResource);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
*Timeout = true;
return DUPL_RETURN_SUCCESS;
}
*Timeout = false;
if (FAILED(hr))
{
return ProcessFailure(m_Device, L"Failed to acquire next frame in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors);
}
// If still holding old frame, destroy it
if (m_AcquiredDesktopImage)
{
m_AcquiredDesktopImage->Release();
m_AcquiredDesktopImage = nullptr;
}
// QI for IDXGIResource
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage));
DesktopResource->Release();
DesktopResource = nullptr;
if (FAILED(hr))
{
return ProcessFailure(nullptr, L"Failed to QI for ID3D11Texture2D from acquired IDXGIResource in DUPLICATIONMANAGER", L"Error", hr);
}
// Get metadata
if (FrameInfo.TotalMetadataBufferSize)
{
// Old buffer too small
if (FrameInfo.TotalMetadataBufferSize > m_MetaDataSize)
{
if (m_MetaDataBuffer)
{
delete [] m_MetaDataBuffer;
m_MetaDataBuffer = nullptr;
}
m_MetaDataBuffer = new (std::nothrow) BYTE[FrameInfo.TotalMetadataBufferSize];
if (!m_MetaDataBuffer)
{
m_MetaDataSize = 0;
Data->MoveCount = 0;
Data->DirtyCount = 0;
return ProcessFailure(nullptr, L"Failed to allocate memory for metadata in DUPLICATIONMANAGER", L"Error", E_OUTOFMEMORY);
}
m_MetaDataSize = FrameInfo.TotalMetadataBufferSize;
}
UINT BufSize = FrameInfo.TotalMetadataBufferSize;
// Get move rectangles
hr = m_DeskDupl->GetFrameMoveRects(BufSize, reinterpret_cast<DXGI_OUTDUPL_MOVE_RECT*>(m_MetaDataBuffer), &BufSize);
if (FAILED(hr))
{
Data->MoveCount = 0;
Data->DirtyCount = 0;
return ProcessFailure(nullptr, L"Failed to get frame move rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors);
}
Data->MoveCount = BufSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
BYTE* DirtyRects = m_MetaDataBuffer + BufSize;
BufSize = FrameInfo.TotalMetadataBufferSize - BufSize;
// Get dirty rectangles
hr = m_DeskDupl->GetFrameDirtyRects(BufSize, reinterpret_cast<RECT*>(DirtyRects), &BufSize);
if (FAILED(hr))
{
Data->MoveCount = 0;
Data->DirtyCount = 0;
return ProcessFailure(nullptr, L"Failed to get frame dirty rects in DUPLICATIONMANAGER", L"Error", hr, FrameInfoExpectedErrors);
}
Data->DirtyCount = BufSize / sizeof(RECT);
Data->MetaData = m_MetaDataBuffer;
}
Data->Frame = m_AcquiredDesktopImage;
Data->FrameInfo = FrameInfo;
//Here I would like to access pixel data from Data->Frame. A buffer of RGBA pixel
return DUPL_RETURN_SUCCESS;
}
Here is Frame_Data structure
typedef struct _FRAME_DATA
{
ID3D11Texture2D* Frame;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
_Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData;
UINT DirtyCount;
UINT MoveCount;
} FRAME_DATA;
Is it possible to access pixel buffer data that have been modified from Data->Frame
Here is my code to access data :
BYTE* DISPLAYMANAGER::GetImageData(ID3D11Texture2D* texture2D, D3D11_TEXTURE2D_DESC Desc)
{
if (texture2D != NULL)
{
D3D11_TEXTURE2D_DESC description;
texture2D->GetDesc(&description);
description.BindFlags = 0;
description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
description.Usage = D3D11_USAGE_STAGING;
description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
ID3D11Texture2D* texTemp = NULL;
HRESULT hr = m_Device->CreateTexture2D(&description, NULL, &texTemp);
if (FAILED(hr))
{
if (texTemp)
{
texTemp->Release();
texTemp = NULL;
}
return NULL;
}
m_DeviceContext->CopyResource(texTemp, texture2D);
D3D11_MAPPED_SUBRESOURCE mapped;
unsigned int subresource = D3D11CalcSubresource(0, 0, 0);
hr = m_DeviceContext->Map(texTemp, subresource, D3D11_MAP_READ_WRITE, 0, &mapped);
if (FAILED(hr))
{
texTemp->Release();
texTemp = NULL;
return NULL;
}
unsigned char *captureData = new unsigned char[Desc.Width * Desc.Height * 4];
RtlZeroMemory(captureData, Desc.Width * Desc.Height * 4);
const int pitch = mapped.RowPitch;
unsigned char *source = static_cast<unsigned char*>(mapped.pData);
unsigned char *dest = captureData;
for (int i = 0; i < Desc.Height; i++) {
memcpy(captureData, source, Desc.Width * 4);
source += pitch;
captureData += Desc.Width * 4;
}
for (int i = 0; i < Desc.Width * Desc.Height * 4; i++) {
//trace(L"Pixel[%d] = %x\n", i, dest[i]);
}
m_DeviceContext->Unmap(texTemp, 0);
return dest;
}
else
return NULL;
}
Thank you for your help!
The textures you obtain via duplication API are not necessarily accessible for CPU, for individual pixel access. To read the texture data, you might need to create a mappable staging texture and copy the obtained texture there. Then doing the mapping you would get a pointer to actual data. Note that this is, in general, not a performance friendly operation.
You will find related information in other answers as well:
How to work with pixels using Direct2D:
For those times when you absolutely have to do CPU pixel manipulation but still want a substantial degree of acceleration, you can manage your own mappable D3D11 textures. For example, you can use staging textures if you want to asynchronously manipulate your texture resources from the CPU.
Transferring textures across adapters in DirectX 11:
... copies it to a staging resource (created on the same device) using ID3D11DeviceContext::CopyResource. I then map that staging resource with Read...

copy color and depthstencil buffer for later use

I'm new to directX and my task is to copy the current depthstencil and color buffer into a texture. Later this textures will be back copied into the color/depthstencil buffer to render on the old scene without rendering the hole scene twice.
This code generates the rendertarget:
bool CGraphicsDriverDX11::CreateRenderTargetTexture(UINT nWidth, UINT nHeight, DXGI_FORMAT Format,
ID3D11Texture2D** ppRenderTargetTexture, ID3D11RenderTargetView** ppRenderTargetView,
ID3D11ShaderResourceView** ppRenderTargetSRV, bool bMultiSample)
{
D3D11_TEXTURE2D_DESC TextureDesc;
ZeroMemory(&TextureDesc, sizeof(TextureDesc));
TextureDesc.Width = nWidth;
TextureDesc.Height = nHeight;
TextureDesc.MipLevels = 1;
TextureDesc.ArraySize = 1;
TextureDesc.Format = Format;
if (bMultiSample)
{
TextureDesc.SampleDesc.Count = m_nMultiSampleCount;
TextureDesc.SampleDesc.Quality = m_nMultiSampleQuality;
}
else
{
TextureDesc.SampleDesc.Count = 1;
TextureDesc.SampleDesc.Quality = 0;
}
TextureDesc.Usage = D3D11_USAGE_DEFAULT;
TextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
TextureDesc.CPUAccessFlags = 0;
TextureDesc.MiscFlags = 0;
HRESULT hr = m_pD3D11Device->CreateTexture2D(&TextureDesc, nullptr, ppRenderTargetTexture);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_RENDER_TARGET_TEXTURE);
return false;
}
hr = m_pD3D11Device->CreateRenderTargetView(*ppRenderTargetTexture, nullptr, ppRenderTargetView);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_RENDER_TARGET_VIEW);
return false;
}
if (ppRenderTargetSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
ZeroMemory(&SRVDesc, sizeof(SRVDesc));
SRVDesc.Format = TextureDesc.Format;
SRVDesc.Texture2D.MipLevels = TextureDesc.MipLevels;
SRVDesc.Texture2D.MostDetailedMip = 0;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
hr = m_pD3D11Device->CreateShaderResourceView(*ppRenderTargetTexture, &SRVDesc, ppRenderTargetSRV);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_SHADER_RESOURCE_VIEW);
return false;
}
}
return true;
}
This code generates the depthbuffer
bool CGraphicsDriverDX11::CreateDepthTexture(UINT nWidth, UINT nHeight, DXGI_FORMAT Format,
ID3D11Texture2D** ppDepthStencilTexture, ID3D11DepthStencilView** ppDepthStencilView,
ID3D11ShaderResourceView** ppDepthStencilSRV, bool bMultiSample)
{
D3D11_TEXTURE2D_DESC TextureDesc;
ZeroMemory(&TextureDesc, sizeof(TextureDesc));
TextureDesc.Width = nWidth;
TextureDesc.Height = nHeight;
TextureDesc.MipLevels = 1;
TextureDesc.ArraySize = 1;
TextureDesc.Format = Format;
if (bMultiSample)
{
TextureDesc.SampleDesc.Count = m_nMultiSampleCount;
TextureDesc.SampleDesc.Quality = m_nMultiSampleQuality;
}
else
{
TextureDesc.SampleDesc.Count = 1;
TextureDesc.SampleDesc.Quality = 0;
}
TextureDesc.Usage = D3D11_USAGE_DEFAULT;
TextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
TextureDesc.CPUAccessFlags = 0;
TextureDesc.MiscFlags = 0;
HRESULT hr = m_pD3D11Device->CreateTexture2D(&TextureDesc, nullptr, ppDepthStencilTexture);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_DEPTHBUFFER_TEXTURE);
return false;
}
m_pD3D11Device->CreateDepthStencilView(*ppDepthStencilTexture, nullptr, ppDepthStencilView);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_DEPTHBUFFER_VIEW);
return false;
}
if (ppDepthStencilSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
ZeroMemory(&SRVDesc, sizeof(SRVDesc));
SRVDesc.Format = TextureDesc.Format;
SRVDesc.Texture2D.MipLevels = TextureDesc.MipLevels;
SRVDesc.Texture2D.MostDetailedMip = 0;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
hr = m_pD3D11Device->CreateShaderResourceView(*ppDepthStencilTexture, &SRVDesc, ppDepthStencilSRV);
if (FAILED(hr))
{
DebugAssertOnce(UNABLE_TO_CREATE_SHADER_RESOURCE_VIEW);
return false;
}
}
return true;
}
now I try to make a copy of it:
ResolveSubresource(GetZBufferCopyTexture(), 0, GetDepthStencilBufferTexture(), 0, DXGI_FORMAT_D24_UNORM_S8_UINT);
ResolveSubresource(GetColorCopyTexture(), 0, GetBackBuffer(), 0, DXGI_FORMAT_R8G8B8A8_UNORM);
and also try to copy the copy back to the rendertarget/depthstencil
ResolveSubresource(GetDepthStencilBufferTexture(), 0, GetZBufferCopyTexture(), 0, DXGI_FORMAT_D24_UNORM_S8_UINT);
ResolveSubresource(GetBackBuffer(), 0, GetColorCopyTexture(), 0, DXGI_FORMAT_R8G8B8A8_UNORM);
but this does not work correctly. I see no changes. Maybe my understanding how directx11 works is completely wrong.
I did this with OpenGL, there I only had to copy the FramebufferObject with the blitframebuffer command and it worked very well. It was the same project, so I'm sure that I call these commands in the right order. But directx11 is completely new to me
EDIT:
I also changed the command "ResolveSubresource" to "CopyResource" but also no changes
I found the mistake:
I used the wrong textures...
Now it works very fine, BTW I use the "CopyResource" command, because the "ResolveSubresource" only copys a multisampled resource into a non-multisampled resource

Why am I getting an information not available, no symbols loaded d3d11.dll Error

I am new to the rendering API and I have been doing okay until now. I have been debugging a while to figure this one out and I just can't figure out why this isn't working. So I need some help.
I believe the source of the problem is here.
m_VertexShader->Release();
Because it doesn't return a HRESULT there isn't much I can't do.
Here is the code.
#include "shader.h"
ShaderProgram::ShaderProgram(Renderer& renderer, const char* vertShader, const char* pixShader)
: m_Renderer(renderer), m_VertexShaderSource(vertShader), m_PixelShaderSource(pixShader)
{
Load();
}
ShaderProgram::~ShaderProgram()
{
m_VertexShader->Release();
m_PixelShader->Release();
m_InputLayout->Release();
}
void ShaderProgram::Load()
{
vector<char> vertSource = FileReader::read_file(m_VertexShaderSource);
vector<char> fragSource = FileReader::read_file(m_PixelShaderSource);
auto resultVert = m_Renderer.getDevice()->CreateVertexShader(vertSource.data(), vertSource.size(), nullptr, &m_VertexShader);
auto resultFrag = m_Renderer.getDevice()->CreatePixelShader(fragSource.data(), fragSource.size(), nullptr, &m_PixelShader);
if (resultVert != S_OK || resultFrag != S_OK)
{
MessageBox(nullptr, "Failed to create shader!", "Error", MB_OK);
exit(0);
}
D3D11_INPUT_ELEMENT_DESC layout[]{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
auto result = m_Renderer.getDevice()->CreateInputLayout(layout, 2, vertSource.data(), vertSource.size(), &m_InputLayout);
if (result != S_OK)
{
MessageBox(nullptr, "Could not create the input layout!", "Error", MB_OK);
exit(0);
}
Here is my rendering class. BTW I have just added stencil and depth testing just now and that could have to do something with the problem.
#include "renderer.h"
Renderer::Renderer(Window& window)
{
createDevice(window);
createRenderTarget();
createDepthStencil();
}
Renderer::~Renderer()
{
m_SwapChain->Release();
m_Device->Release();
m_DeviceContex->Release();
m_RenderTargetView->Release();
m_DepthStencilView->Release();
}
void Renderer::createDevice(Window& window)
{
DXGI_SWAP_CHAIN_DESC swapChain = { 0 };
swapChain.BufferCount = 1;
swapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChain.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChain.OutputWindow = window.getHandle();
swapChain.SampleDesc.Count = 1;
swapChain.Windowed = true;
auto result = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
0, D3D11_SDK_VERSION, &swapChain, &m_SwapChain, &m_Device, nullptr, &m_DeviceContex);
if (result != S_OK)
{
MessageBox(nullptr, "Problem with creating DX11!", "Error", MB_OK);
exit(0);
}
}
void Renderer::createDepthStencil()
{
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Width = m_BackBuffer.Width;
depthStencilDesc.Height = m_BackBuffer.Height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
m_Device->CreateTexture2D(&depthStencilDesc, nullptr, &m_DepthStencilBuffer);
m_Device->CreateDepthStencilView(m_DepthStencilBuffer, nullptr, &m_DepthStencilView);
m_DepthStencilBuffer->Release();
}
void Renderer::createRenderTarget()
{
ID3D11Texture2D* backBuffer;
auto result = m_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBuffer);
if (result != S_OK)
{
MessageBox(nullptr, "Failed to get the swap chain buffer!", "Error", MB_OK);
exit(0);
}
m_Device->CreateRenderTargetView(backBuffer, nullptr, &m_RenderTargetView);
backBuffer->GetDesc(&m_BackBuffer);
backBuffer->Release();
}
void Renderer::beginFrame()
{
m_DeviceContex->OMSetRenderTargets(1, &m_RenderTargetView, m_DepthStencilView);
auto viewport = CD3D11_VIEWPORT(0.0f, 0.0f, (float) m_BackBuffer.Width, (float) m_BackBuffer.Height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
m_DeviceContex->RSSetViewports(1, &viewport);
float clearColor[] = { 0.25f, 0.75f, 0.8f, 1.0f };
m_DeviceContex->ClearRenderTargetView(m_RenderTargetView, clearColor);
m_DeviceContex->ClearDepthStencilView(m_DepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
}
//Swaps the buffer!
void Renderer::endFrame()
{
m_SwapChain->Present(1, 0);
}
}
Do you get the same error when you run it in non-debug mode? With the limited info you've given it looks like your debug symbol table is not being found. If its all fine and dandy in non-debug mode then its off to sift through the docs to find out how to load the symbol table. Not much of an answer but hope it might help a little
You really should move to using Microsoft::WRL::ComPtr. With raw pointers, you are likely to call Release too few or too many times, which is what happened here. See this page.
It would remove silly things like the fact that you keep a dangling pointer to m_DepthStencilView even after you release it. You don't need to make it a member variable at all since you only use it to create m_DepthStencilView.
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
...
ComPtr<ID3D11Texture2D> depthStencil;
m_Device->CreateTexture2D(&depthStencilDesc, nullptr, &depthStencil);
m_Device->CreateDepthStencilView(depthStencil.Get(), nullptr, &m_DepthStencilView);
Take a look at the Direct3D 11 Game Visual Studio templates, in particular the implementation of DeviceResources.h / DeviceResources.cpp.