Commit d9d02261 authored by chili's avatar chili
Browse files

dxgi debug info added

parent 4a2e05f8
#include "DxgiInfoManager.h"
#include "Window.h"
#include "Graphics.h"
#include <dxgidebug.h>
#include <memory>
#pragma comment(lib, "dxguid.lib")
#define GFX_THROW_NOINFO(hrcall) if( FAILED( hr = (hrcall) ) ) throw Graphics::HrException( __LINE__,__FILE__,hr )
DxgiInfoManager::DxgiInfoManager()
{
// define function signature of DXGIGetDebugInterface
typedef HRESULT (WINAPI* DXGIGetDebugInterface)(REFIID,void **);
// load the dll that contains the function DXGIGetDebugInterface
const auto hModDxgiDebug = LoadLibraryEx( "dxgidebug.dll",nullptr,LOAD_LIBRARY_SEARCH_SYSTEM32 );
if( hModDxgiDebug == nullptr )
{
throw CHWND_LAST_EXCEPT();
}
// get address of DXGIGetDebugInterface in dll
const auto DxgiGetDebugInterface = reinterpret_cast<DXGIGetDebugInterface>(
reinterpret_cast<void*>(GetProcAddress( hModDxgiDebug,"DXGIGetDebugInterface" ))
);
if( DxgiGetDebugInterface == nullptr )
{
throw CHWND_LAST_EXCEPT();
}
HRESULT hr;
GFX_THROW_NOINFO( DxgiGetDebugInterface( __uuidof(IDXGIInfoQueue),reinterpret_cast<void**>(&pDxgiInfoQueue) ) );
}
DxgiInfoManager::~DxgiInfoManager()
{
if( pDxgiInfoQueue != nullptr )
{
pDxgiInfoQueue->Release();
}
}
void DxgiInfoManager::Set() noexcept
{
// set the index (next) so that the next all to GetMessages()
// will only get errors generated after this call
next = pDxgiInfoQueue->GetNumStoredMessages( DXGI_DEBUG_ALL );
}
std::vector<std::string> DxgiInfoManager::GetMessages() const
{
std::vector<std::string> messages;
const auto end = pDxgiInfoQueue->GetNumStoredMessages( DXGI_DEBUG_ALL );
for( auto i = next; i < end; i++ )
{
HRESULT hr;
SIZE_T messageLength;
// get the size of message i in bytes
GFX_THROW_NOINFO( pDxgiInfoQueue->GetMessage( DXGI_DEBUG_ALL,i,nullptr,&messageLength ) );
// allocate memory for message
auto bytes = std::make_unique<byte[]>( messageLength );
auto pMessage = reinterpret_cast<DXGI_INFO_QUEUE_MESSAGE*>(bytes.get());
// get the message and push its description into the vector
GFX_THROW_NOINFO( pDxgiInfoQueue->GetMessage( DXGI_DEBUG_ALL,i,pMessage,&messageLength ) );
messages.emplace_back( pMessage->pDescription );
}
return messages;
}
#pragma once
#include "ChiliWin.h"
#include <vector>
class DxgiInfoManager
{
public:
DxgiInfoManager();
~DxgiInfoManager();
DxgiInfoManager( const DxgiInfoManager& ) = delete;
DxgiInfoManager& operator=( const DxgiInfoManager& ) = delete;
void Set() noexcept;
std::vector<std::string> GetMessages() const;
private:
unsigned long long next = 0u;
struct IDXGIInfoQueue* pDxgiInfoQueue = nullptr;
};
\ No newline at end of file
...@@ -4,8 +4,20 @@ ...@@ -4,8 +4,20 @@
#pragma comment(lib,"d3d11.lib") #pragma comment(lib,"d3d11.lib")
#define GFX_THROW_FAILED(hrcall) if( FAILED( hr = (hrcall) ) ) throw Graphics::HrException( __LINE__,__FILE__,hr ) // graphics exception checking/throwing macros (some with dxgi infos)
#define GFX_EXCEPT_NOINFO(hr) Graphics::HrException( __LINE__,__FILE__,(hr) )
#define GFX_THROW_NOINFO(hrcall) if( FAILED( hr = (hrcall) ) ) throw Graphics::HrException( __LINE__,__FILE__,hr )
#ifndef NDEBUG
#define GFX_EXCEPT(hr) Graphics::HrException( __LINE__,__FILE__,(hr),infoManager.GetMessages() )
#define GFX_THROW_INFO(hrcall) infoManager.Set(); if( FAILED( hr = (hrcall) ) ) throw GFX_EXCEPT(hr)
#define GFX_DEVICE_REMOVED_EXCEPT(hr) Graphics::DeviceRemovedException( __LINE__,__FILE__,(hr),infoManager.GetMessages() )
#else
#define GFX_EXCEPT(hr) Graphics::HrException( __LINE__,__FILE__,(hr) )
#define GFX_THROW_INFO(hrcall) GFX_THROW_NOINFO(hrcall)
#define GFX_DEVICE_REMOVED_EXCEPT(hr) Graphics::DeviceRemovedException( __LINE__,__FILE__,(hr) ) #define GFX_DEVICE_REMOVED_EXCEPT(hr) Graphics::DeviceRemovedException( __LINE__,__FILE__,(hr) )
#endif
Graphics::Graphics( HWND hWnd ) Graphics::Graphics( HWND hWnd )
{ {
...@@ -26,15 +38,20 @@ Graphics::Graphics( HWND hWnd ) ...@@ -26,15 +38,20 @@ Graphics::Graphics( HWND hWnd )
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0; sd.Flags = 0;
UINT swapCreateFlags = 0u;
#ifndef NDEBUG
swapCreateFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// for checking results of d3d functions // for checking results of d3d functions
HRESULT hr; HRESULT hr;
// create device and front/back buffers, and swap chain and rendering context // create device and front/back buffers, and swap chain and rendering context
GFX_THROW_FAILED( D3D11CreateDeviceAndSwapChain( GFX_THROW_INFO( D3D11CreateDeviceAndSwapChain(
nullptr, nullptr,
D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_HARDWARE,
nullptr, nullptr,
0, swapCreateFlags,
nullptr, nullptr,
0, 0,
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
...@@ -46,8 +63,8 @@ Graphics::Graphics( HWND hWnd ) ...@@ -46,8 +63,8 @@ Graphics::Graphics( HWND hWnd )
) ); ) );
// gain access to texture subresource in swap chain (back buffer) // gain access to texture subresource in swap chain (back buffer)
ID3D11Resource* pBackBuffer = nullptr; ID3D11Resource* pBackBuffer = nullptr;
GFX_THROW_FAILED( pSwap->GetBuffer( 0,__uuidof(ID3D11Texture2D),reinterpret_cast<void**>(&pBackBuffer) ) ); GFX_THROW_INFO( pSwap->GetBuffer( 0,__uuidof(ID3D11Resource),reinterpret_cast<void**>(&pBackBuffer) ) );
GFX_THROW_FAILED( pDevice->CreateRenderTargetView( pBackBuffer,nullptr,&pTarget ) ); GFX_THROW_INFO( pDevice->CreateRenderTargetView( pBackBuffer,nullptr,&pTarget ) );
pBackBuffer->Release(); pBackBuffer->Release();
} }
...@@ -74,6 +91,9 @@ Graphics::~Graphics() ...@@ -74,6 +91,9 @@ Graphics::~Graphics()
void Graphics::EndFrame() void Graphics::EndFrame()
{ {
HRESULT hr; HRESULT hr;
#ifndef NDEBUG
infoManager.Set();
#endif
if( FAILED( hr = pSwap->Present( 1u,0u ) ) ) if( FAILED( hr = pSwap->Present( 1u,0u ) ) )
{ {
if( hr == DXGI_ERROR_DEVICE_REMOVED ) if( hr == DXGI_ERROR_DEVICE_REMOVED )
...@@ -82,7 +102,7 @@ void Graphics::EndFrame() ...@@ -82,7 +102,7 @@ void Graphics::EndFrame()
} }
else else
{ {
GFX_THROW_FAILED( hr ); throw GFX_EXCEPT( hr );
} }
} }
} }
...@@ -95,11 +115,23 @@ void Graphics::ClearBuffer( float red,float green,float blue ) noexcept ...@@ -95,11 +115,23 @@ void Graphics::ClearBuffer( float red,float green,float blue ) noexcept
// Graphics exception stuff // Graphics exception stuff
Graphics::HrException::HrException( int line,const char * file,HRESULT hr ) noexcept Graphics::HrException::HrException( int line,const char * file,HRESULT hr,std::vector<std::string> infoMsgs ) noexcept
: :
Exception( line,file ), Exception( line,file ),
hr( hr ) hr( hr )
{} {
// join all info messages with newlines into single string
for( const auto& m : infoMsgs )
{
info += m;
info.push_back( '\n' );
}
// remove final newline if exists
if( !info.empty() )
{
info.pop_back();
}
}
const char* Graphics::HrException::what() const noexcept const char* Graphics::HrException::what() const noexcept
{ {
...@@ -108,8 +140,12 @@ const char* Graphics::HrException::what() const noexcept ...@@ -108,8 +140,12 @@ const char* Graphics::HrException::what() const noexcept
<< "[Error Code] 0x" << std::hex << std::uppercase << GetErrorCode() << "[Error Code] 0x" << std::hex << std::uppercase << GetErrorCode()
<< std::dec << " (" << (unsigned long)GetErrorCode() << ")" << std::endl << std::dec << " (" << (unsigned long)GetErrorCode() << ")" << std::endl
<< "[Error String] " << GetErrorString() << std::endl << "[Error String] " << GetErrorString() << std::endl
<< "[Description] " << GetErrorDescription() << std::endl << "[Description] " << GetErrorDescription() << std::endl;
<< GetOriginString(); if( !info.empty() )
{
oss << "\n[Error Info]\n" << GetErrorInfo() << std::endl << std::endl;
}
oss << GetOriginString();
whatBuffer = oss.str(); whatBuffer = oss.str();
return whatBuffer.c_str(); return whatBuffer.c_str();
} }
...@@ -136,6 +172,11 @@ std::string Graphics::HrException::GetErrorDescription() const noexcept ...@@ -136,6 +172,11 @@ std::string Graphics::HrException::GetErrorDescription() const noexcept
return buf; return buf;
} }
std::string Graphics::HrException::GetErrorInfo() const noexcept
{
return info;
}
const char* Graphics::DeviceRemovedException::GetType() const noexcept const char* Graphics::DeviceRemovedException::GetType() const noexcept
{ {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include "ChiliWin.h" #include "ChiliWin.h"
#include "ChiliException.h" #include "ChiliException.h"
#include <d3d11.h> #include <d3d11.h>
#include <vector>
#include "DxgiInfoManager.h"
class Graphics class Graphics
{ {
...@@ -13,20 +15,24 @@ public: ...@@ -13,20 +15,24 @@ public:
class HrException : public Exception class HrException : public Exception
{ {
public: public:
HrException( int line,const char* file,HRESULT hr ) noexcept; HrException( int line,const char* file,HRESULT hr,std::vector<std::string> infoMsgs = {} ) noexcept;
const char* what() const noexcept override; const char* what() const noexcept override;
const char* GetType() const noexcept override; const char* GetType() const noexcept override;
HRESULT GetErrorCode() const noexcept; HRESULT GetErrorCode() const noexcept;
std::string GetErrorString() const noexcept; std::string GetErrorString() const noexcept;
std::string GetErrorDescription() const noexcept; std::string GetErrorDescription() const noexcept;
std::string GetErrorInfo() const noexcept;
private: private:
HRESULT hr; HRESULT hr;
std::string info;
}; };
class DeviceRemovedException : public HrException class DeviceRemovedException : public HrException
{ {
using HrException::HrException; using HrException::HrException;
public: public:
const char* GetType() const noexcept override; const char* GetType() const noexcept override;
private:
std::string reason;
}; };
public: public:
Graphics( HWND hWnd ); Graphics( HWND hWnd );
...@@ -36,6 +42,9 @@ public: ...@@ -36,6 +42,9 @@ public:
void EndFrame(); void EndFrame();
void ClearBuffer( float red,float green,float blue ) noexcept; void ClearBuffer( float red,float green,float blue ) noexcept;
private: private:
#ifndef NDEBUG
DxgiInfoManager infoManager;
#endif
ID3D11Device* pDevice = nullptr; ID3D11Device* pDevice = nullptr;
IDXGISwapChain* pSwap = nullptr; IDXGISwapChain* pSwap = nullptr;
ID3D11DeviceContext* pContext = nullptr; ID3D11DeviceContext* pContext = nullptr;
......
...@@ -149,6 +149,7 @@ ...@@ -149,6 +149,7 @@
<ClCompile Include="ChiliException.cpp" /> <ClCompile Include="ChiliException.cpp" />
<ClCompile Include="ChiliTimer.cpp" /> <ClCompile Include="ChiliTimer.cpp" />
<ClCompile Include="dxerr.cpp" /> <ClCompile Include="dxerr.cpp" />
<ClCompile Include="DxgiInfoManager.cpp" />
<ClCompile Include="Graphics.cpp" /> <ClCompile Include="Graphics.cpp" />
<ClCompile Include="Keyboard.cpp" /> <ClCompile Include="Keyboard.cpp" />
<ClCompile Include="Mouse.cpp" /> <ClCompile Include="Mouse.cpp" />
...@@ -162,6 +163,7 @@ ...@@ -162,6 +163,7 @@
<ClInclude Include="ChiliTimer.h" /> <ClInclude Include="ChiliTimer.h" />
<ClInclude Include="ChiliWin.h" /> <ClInclude Include="ChiliWin.h" />
<ClInclude Include="dxerr.h" /> <ClInclude Include="dxerr.h" />
<ClInclude Include="DxgiInfoManager.h" />
<ClInclude Include="Graphics.h" /> <ClInclude Include="Graphics.h" />
<ClInclude Include="Keyboard.h" /> <ClInclude Include="Keyboard.h" />
<ClInclude Include="Mouse.h" /> <ClInclude Include="Mouse.h" />
......
...@@ -48,6 +48,9 @@ ...@@ -48,6 +48,9 @@
<ClCompile Include="dxerr.cpp"> <ClCompile Include="dxerr.cpp">
<Filter>Dxerr</Filter> <Filter>Dxerr</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="DxgiInfoManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="WindowsMessageMap.h"> <ClInclude Include="WindowsMessageMap.h">
...@@ -83,6 +86,9 @@ ...@@ -83,6 +86,9 @@
<ClInclude Include="dxerr.h"> <ClInclude Include="dxerr.h">
<Filter>Dxerr</Filter> <Filter>Dxerr</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="DxgiInfoManager.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="hw3d.rc"> <ResourceCompile Include="hw3d.rc">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment