РЕЖИМ ОТЛАДКИ Direct3D11 завершает работу в финальной версии COM, когда SampleDesc.Count & gt; 1

Помните: FRAPS + D3D11_CREATE_DEVICE_DEBUG + SampleDesc.Count > 1 не смешивай

Я действительно новичок в DX … как в недельном возрасте. Но проблему очень легко описать, даже с моим ограниченным языком и пониманием. Я держу DEBUG слой, поскольку он обеспечивает ценную обратную связь. Но в свою очередь это создает проблему, которую я не могу преодолеть. Я потратил 1 день, потянув за волосы.

ЭТА ПРОБЛЕМА

Если я создам D3D11 устройство с:

vSwapChainDesc.SampleDesc.Count = 4;
vSwapChainDesc.SampleDesc.Quality = 3;

… он падает в финале ->Release()независимо от того, какой это объект. Точно такой же ЧЕРТ с:

vSwapChainDesc.SampleDesc.Count = 1;
vSwapChainDesc.SampleDesc.Quality = 0;

… очищает ссылки COM плавно. Не говоря уже о том, что оба варианта работать нормально в Release без DEBUG флаг.

в OutputЯ получаю загадочную ошибку, говоря live children without parents, Но у меня есть только 5 объектов COM, которые я использую с оболочкой COM.

Поэтому я удалил обертку COM, делая ->Release() а также = nullptr вручную для каждого из них. это НЕВОЗМОЖНО чтобы выпустить что-то по ошибке, ИМО. И в финале ->Release() он говорит, что достиг точки останова.

Так … кто-нибудь еще сталкивался с таким поведением? Я не думаю, что смогу получить ответ, если кто-то еще не прошел через то же самое. Это так странно …

Код

// Uncomment this and it all works... like magic!
// #undef _DEBUG

#pragma region Includes
#include <stdio.h>
#include <conio.h>
#include <map>
#include <windows.h>
#include <d3d11.h>

#pragma comment (lib, "dxgi.lib")
#pragma comment (lib, "d3d11.lib")
#pragma endregion

#pragma region Com Helpers
// track the refcounts on ->Release() :)
std::map<std::string, int> g_ComCounter;

template <typename Interface_t>
Interface_t** ComRelease(Interface_t** aPointer, LPCSTR aName) {
if(!aPointer) {
DebugBreak();
}

if(*aPointer) {
// save refcount for debug
g_ComCounter[aName] = (*aPointer)->Release();
*aPointer = nullptr;
}
printf("Destroyed %p (%s:%d).\r\n", *aPointer, aName, g_ComCounter[aName]);

return aPointer;
}

#define COM_RELEASE(Pointer) ComRelease(&Pointer, #Pointer)

template <typename Interface_t>
Interface_t** ComPointer(Interface_t** aPointer, LPCSTR aName) {
if(!aPointer) {
DebugBreak();
}

if(*aPointer) {
// save refcount for debug
g_ComCounter[aName] = (*aPointer)->Release();
*aPointer = nullptr;
}
printf("Prepared %p (%s:%d).\r\n", *aPointer, aName, g_ComCounter[aName]);

// Object is being Acquired

return aPointer;
}

#define COM_POINTER(Pointer) ComPointer(&Pointer, #Pointer)
#pragma endregion

#pragma region Window Proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT vPainStruct = { 0 };
HDC vDc(nullptr);

switch(uMessage) {
case WM_PAINT:
vDc = BeginPaint(hWnd, &vPainStruct);
EndPaint(hWnd, &vPainStruct);
return FALSE;
break;
case WM_ERASEBKGND:
// Don't erase background!
return TRUE;
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}

return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
#pragma endregion

#ifdef _CONSOLE
int wmain(int aArgc, const WCHAR* aArgv[]) {
#else
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
#endif
#pragma region Variables
HINSTANCE                   vInstance = GetModuleHandle(nullptr);
HWND                        vHwnd = nullptr;
D3D_DRIVER_TYPE             vDriverType = D3D_DRIVER_TYPE_UNKNOWN;
D3D_FEATURE_LEVEL           vFeatureLevel = D3D_FEATURE_LEVEL_11_0;
IDXGIFactory                *vDxgiFactory = nullptr;
IDXGIAdapter                *vDxgiAdapter = nullptr;
ID3D11Device                *vD3dDevice = nullptr;
ID3D11DeviceContext         *vD3dContext = nullptr;
IDXGISwapChain              *vSwapChain = nullptr;
ID3D11Texture2D             *vBackBuffer(nullptr);
ID3D11RenderTargetView      *vRenderTargetView = nullptr;
#ifdef _DEBUG
ID3D11Debug                 *vDebugger = nullptr;
ID3D11InfoQueue             *vInfoQueue = nullptr;
#endif
#pragma endregion

#pragma region Init Window
// Register class
WNDCLASSEX vWndClass;
ZeroMemory(&vWndClass, sizeof(vWndClass));
vWndClass.cbSize = sizeof(WNDCLASSEX);
vWndClass.style = 0; // CS_HREDRAW | CS_VREDRAW (draw in loop, no need for WM_PAINT)
vWndClass.lpfnWndProc = WndProc;
vWndClass.cbClsExtra = 0;
vWndClass.cbWndExtra = 0;
vWndClass.hInstance = vInstance;
vWndClass.hIcon = 0;
vWndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
vWndClass.hbrBackground = nullptr;
vWndClass.lpszMenuName = nullptr;
vWndClass.lpszClassName = L"D3d11Window";
vWndClass.hIconSm = 0;
if(!RegisterClassEx(&vWndClass)) {
DebugBreak();
return 0;
}

// Create window
RECT vWindowRect = { 0, 0, 640, 480 };
AdjustWindowRect(&vWindowRect, WS_OVERLAPPEDWINDOW, FALSE);
vHwnd = CreateWindowEx(
0, vWndClass.lpszClassName, L"D3D11", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
vWindowRect.right - vWindowRect.left, vWindowRect.bottom - vWindowRect.top,
nullptr, nullptr, vInstance,
nullptr);
if(!vHwnd) {
DebugBreak();
return 0;
}

ShowWindow(vHwnd, SW_SHOWDEFAULT);
#pragma endregion

#pragma region Initialization
RECT vClientRect = { 0 };
GetClientRect(vHwnd, &vClientRect);
UINT vWidth = vClientRect.right - vClientRect.left;
UINT vHeight = vClientRect.bottom - vClientRect.top;

if(FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)COM_POINTER(vDxgiFactory)))) {
DebugBreak();
return 0;
}

if(FAILED(vDxgiFactory->EnumAdapters(0, COM_POINTER(vDxgiAdapter)))) {
DebugBreak();
return 0;
}

D3D_FEATURE_LEVEL vRequestedFeatureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
// D3D_FEATURE_LEVEL_10_1,
// D3D_FEATURE_LEVEL_10_0
};

UINT vNumFeatureLevels = ARRAYSIZE(vRequestedFeatureLevels);

UINT vDeviceFlags = 0;
#ifdef _DEBUG
vDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

if(FAILED(D3D11CreateDevice(
vDxgiAdapter,
vDriverType,
nullptr,
vDeviceFlags,
vRequestedFeatureLevels,
vNumFeatureLevels,
D3D11_SDK_VERSION,
COM_POINTER(vD3dDevice),
&vFeatureLevel,
COM_POINTER(vD3dContext)))) {
return 0;
}

#ifdef _DEBUG
if(FAILED(vD3dDevice->QueryInterface(__uuidof(ID3D11Debug), (LPVOID*)COM_POINTER(vDebugger)))) {
return 0;
}
if(FAILED(vDebugger->QueryInterface(__uuidof(ID3D11InfoQueue), (LPVOID*)COM_POINTER(vInfoQueue)))) {
return 0;
}
vInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
vInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
vDebugger->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY | D3D11_RLDO_DETAIL);
#endif

UINT vMsaaQuality = 0;
if(FAILED(vD3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &vMsaaQuality)) || (vMsaaQuality < 1)) {
return 0;
}
printf("MsaaQuality: %d for 4\r\n", vMsaaQuality);

DXGI_SWAP_CHAIN_DESC vSwapChainDesc;
ZeroMemory(&vSwapChainDesc, sizeof(vSwapChainDesc));
vSwapChainDesc.BufferCount = 2;
vSwapChainDesc.BufferDesc.Width = vWidth;
vSwapChainDesc.BufferDesc.Height = vHeight;
vSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
vSwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
vSwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
vSwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
vSwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
vSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
vSwapChainDesc.SampleDesc.Count = 4; // set 1 for the code to work              vSwapChainDesc.SampleDesc.Quality = vMsaaQuality - 1;
vSwapChainDesc.OutputWindow = vHwnd;
vSwapChainDesc.Windowed = true;
vSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
vSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

if(FAILED(vDxgiFactory->CreateSwapChain(vD3dDevice, &vSwapChainDesc, COM_POINTER(vSwapChain)))) {
return 0;
}

if(FAILED(vSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)COM_POINTER(vBackBuffer)))) {
return 0;
}

if(FAILED(vD3dDevice->CreateRenderTargetView(vBackBuffer, nullptr, COM_POINTER(vRenderTargetView)))) {
return 0;
}

vD3dContext->OMSetRenderTargets(1, &vRenderTargetView, nullptr);

D3D11_VIEWPORT vViewport = { 0 };
vViewport.Width = static_cast<FLOAT>(vWidth);
vViewport.Height = static_cast<FLOAT>(vHeight);
vViewport.MinDepth = D3D11_MIN_DEPTH;
vViewport.MaxDepth = D3D11_MAX_DEPTH;
vViewport.TopLeftX = 0;
vViewport.TopLeftY = 0;
vD3dContext->RSSetViewports(1, &vViewport);
#pragma endregion

#pragma region Game Loop
MSG vMessage = { 0 };
while(WM_QUIT != vMessage.message) {
while(PeekMessage(&vMessage, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&vMessage);
DispatchMessage(&vMessage);
}

if(WM_QUIT == vMessage.message) {
break;
}

#pragma region Render
float vClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
vD3dContext->ClearRenderTargetView(vRenderTargetView, vClearColor);
vSwapChain->Present(true, 0); // vsync
#pragma endregion
}
#pragma endregion

#pragma region Cleanup
if(vSwapChain) {
vSwapChain->SetFullscreenState(false, nullptr);
}
if(vD3dContext) {
vD3dContext->ClearState();
}

COM_RELEASE(vRenderTargetView);
COM_RELEASE(vBackBuffer);
COM_RELEASE(vSwapChain);
COM_RELEASE(vD3dContext);
COM_RELEASE(vD3dDevice);
COM_RELEASE(vDxgiFactory);
COM_RELEASE(vDxgiAdapter);

#ifdef _DEBUG
COM_RELEASE(vDebugger);
COM_RELEASE(vInfoQueue);
#endif

printf("\r\nREF COUNTS AFTER RELEASE():\r\n");
for(const auto& vComCount : g_ComCounter) {
printf("%s:%d\r\n", vComCount.first.c_str(), vComCount.second);
}

#pragma endregion

_getch();
return (int)vMessage.wParam;
}

ПОМОГИТЕ!

Если вы хотите, чтобы я прокомментировал код, чтобы лучше объяснить логику, я сделаю это. Я получаю комментарии с упоминанием вещей, которые четко объясняют вопрос и код … Может быть, я не достаточно ясен.

Последние мысли

Может быть, есть какая-то функция релиза, внутренняя для определенных объектов, которые я не вызываю. Может быть, я делаю что-то не в порядке или действительно неправильно. Но я получил это от авторитетного сайта. И это соответствует Hello DirectX! код в книгах, которыми я сейчас балуюсь.

Этот фрагмент урезан и минималистичен. Это урезанная версия более сложной, пытающаяся выявить проблему. Кроме того, я удалил все ООП, чтобы в одном блоке кода было легко следить.

Теперь последний вопрос: Есть ли другой способ сгладить линии, кроме этого SampleDesc один?

PS: Это Windows 7 x64, VS 2013 + 2014 CTP. И карта поддерживает это, поскольку это работает (края гладкие) и в режиме отладки и в выпуске. Это только финальная версия, которая не работает в режиме отладки.

2

Решение

Я не знаю, почему ваш код дает сбой, но я хотел бы поделиться некоторыми своими впечатлениями от программирования DirectX на основе вашего кода 🙂

  1. Используйте приложение win32 вместо консольного приложения
  2. Функция ComRelease была слишком сложной, вам не нужно так много кода, достаточно одной строки.
  3. Не переносите указатели d3d на ComPointer.

Более чистый код, как показано ниже, избавит вас от сложностей, связанных с COM, и сосредоточится на логике кода для проверки сбоя.

#define DEBUG
#pragma region Includes
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <d3d11.h>

#pragma comment (lib, "dxgi.lib")
#pragma comment (lib, "d3d11.lib")
#pragma endregion

// Release COM object
#define SAFE_RELEASE(P) if(P){ P->Release(); P = NULL;}

#pragma region Window Proc
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT vPainStruct = { 0 };
HDC vDc(nullptr);

switch(uMessage) {
case WM_PAINT:
vDc = BeginPaint(hWnd, &vPainStruct);
EndPaint(hWnd, &vPainStruct);
return FALSE;
break;
case WM_ERASEBKGND:
// Don't erase background!
return TRUE;
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}

return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
#pragma endregion

int main() {
#pragma region Variables
HINSTANCE                   vInstance = GetModuleHandle(nullptr);
HWND                        vHwnd = nullptr;
D3D_DRIVER_TYPE             vDriverType = D3D_DRIVER_TYPE_UNKNOWN;
D3D_FEATURE_LEVEL           vFeatureLevel = D3D_FEATURE_LEVEL_11_0;
IDXGIFactory                *vDxgiFactory = NULL;
IDXGIAdapter                *vDxgiAdapter = nullptr;
ID3D11Device                *vD3dDevice = nullptr;
ID3D11DeviceContext         *vD3dContext = nullptr;
IDXGISwapChain              *vSwapChain = nullptr;
ID3D11Texture2D             *vBackBuffer = NULL;
ID3D11RenderTargetView      *vRenderTargetView = nullptr;
#ifdef _DEBUG
ID3D11Debug                 *vDebugger = nullptr;
ID3D11InfoQueue             *vInfoQueue = nullptr;
#endif
#pragma endregion

#pragma region Init Window
// Register class
WNDCLASSEX vWndClass;
ZeroMemory(&vWndClass, sizeof(vWndClass));
vWndClass.cbSize = sizeof(WNDCLASSEX);
vWndClass.style = 0; // CS_HREDRAW | CS_VREDRAW (draw in loop, no need for WM_PAINT)
vWndClass.lpfnWndProc = WndProc;
vWndClass.cbClsExtra = 0;
vWndClass.cbWndExtra = 0;
vWndClass.hInstance = vInstance;
vWndClass.hIcon = 0;
vWndClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
vWndClass.hbrBackground = nullptr;
vWndClass.lpszMenuName = nullptr;
vWndClass.lpszClassName = L"D3d11Window";
vWndClass.hIconSm = 0;
if(!RegisterClassEx(&vWndClass)) {
DebugBreak();
return 0;
}

// Create window
RECT vWindowRect = { 0, 0, 640, 480 };
vHwnd = CreateWindowEx(
0, vWndClass.lpszClassName, L"D3D11", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
vWindowRect.right - vWindowRect.left, vWindowRect.bottom - vWindowRect.top,
nullptr, nullptr, vInstance,
nullptr);
if(!vHwnd) {
DebugBreak();
return 0;
}

ShowWindow(vHwnd, SW_SHOWDEFAULT);
#pragma endregion

#pragma region Initialization
RECT vClientRect = { 0 };
GetClientRect(vHwnd, &vClientRect);
UINT vWidth = vClientRect.right - vClientRect.left;
UINT vHeight = vClientRect.bottom - vClientRect.top;

if(FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&vDxgiFactory)))) {
DebugBreak();
return 0;
}

if(FAILED(vDxgiFactory->EnumAdapters(0, &vDxgiAdapter))) {
DebugBreak();
return 0;
}

D3D_FEATURE_LEVEL vRequestedFeatureLevels[] = {
D3D_FEATURE_LEVEL_11_0,
// D3D_FEATURE_LEVEL_10_1,
// D3D_FEATURE_LEVEL_10_0
};

UINT vNumFeatureLevels = ARRAYSIZE(vRequestedFeatureLevels);

UINT vDeviceFlags = 0;
#ifdef _DEBUG
vDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

if(FAILED(D3D11CreateDevice(
vDxgiAdapter,
vDriverType,
nullptr,
vDeviceFlags,
vRequestedFeatureLevels,
vNumFeatureLevels,
D3D11_SDK_VERSION,
&vD3dDevice,
&vFeatureLevel,
&vD3dContext))) {
return 0;
}

UINT vMsaaQuality = 0;
if(FAILED(vD3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &vMsaaQuality)) || (vMsaaQuality < 1)) {
return 0;
}
printf("MsaaQuality of max %d supported for count 4\r\n", vMsaaQuality);

DXGI_SWAP_CHAIN_DESC vSwapChainDesc;
ZeroMemory(&vSwapChainDesc, sizeof(vSwapChainDesc));
vSwapChainDesc.BufferCount = 2;
vSwapChainDesc.BufferDesc.Width = vWidth;
vSwapChainDesc.BufferDesc.Height = vHeight;
vSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
vSwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
vSwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
vSwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
vSwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
vSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
vSwapChainDesc.SampleDesc.Count = 4; // set 1 to work
vSwapChainDesc.SampleDesc.Quality = vMsaaQuality - 1;
vSwapChainDesc.OutputWindow = vHwnd;
vSwapChainDesc.Windowed = true;
vSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
vSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

if(FAILED(vDxgiFactory->CreateSwapChain(vD3dDevice, &vSwapChainDesc, &vSwapChain))) {
return 0;
}

if(FAILED(vSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&vBackBuffer))) {
return 0;
}

if(FAILED(vD3dDevice->CreateRenderTargetView(vBackBuffer, nullptr, &vRenderTargetView))) {
return 0;
}

vD3dContext->OMSetRenderTargets(1, &vRenderTargetView, nullptr);

D3D11_VIEWPORT vViewport = { 0 };
vViewport.Width = static_cast<FLOAT>(vWidth);
vViewport.Height = static_cast<FLOAT>(vHeight);
vViewport.MinDepth = D3D11_MIN_DEPTH;
vViewport.MaxDepth = D3D11_MAX_DEPTH;
vViewport.TopLeftX = 0;
vViewport.TopLeftY = 0;
vD3dContext->RSSetViewports(1, &vViewport);
#pragma endregion

#pragma region Game Loop
MSG vMessage = { 0 };
while(WM_QUIT != vMessage.message) {
while(PeekMessage(&vMessage, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&vMessage);
DispatchMessage(&vMessage);
}

if(WM_QUIT == vMessage.message) {
break;
}

#pragma region Render
float vClearColor[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
vD3dContext->ClearRenderTargetView(vRenderTargetView, vClearColor);
vSwapChain->Present(true, 0); // vsync
#pragma endregion
}
#pragma endregion

#pragma region Cleanup
if(vSwapChain) {
vSwapChain->SetFullscreenState(false, nullptr);
}
if(vD3dContext) {
vD3dContext->ClearState();
}

SAFE_RELEASE(vRenderTargetView);
SAFE_RELEASE(vBackBuffer);
SAFE_RELEASE(vSwapChain);
SAFE_RELEASE(vD3dContext);
SAFE_RELEASE(vD3dDevice);
SAFE_RELEASE(vDxgiFactory);
SAFE_RELEASE(vDxgiAdapter);

#ifdef _DEBUG
SAFE_RELEASE(vDebugger);
SAFE_RELEASE(vInfoQueue);
#endif#pragma endregion

_getch();
return (int)vMessage.wParam;
}
1

Другие решения

Проверьте, поддерживает ли ваша карта Quality = 3 с CheckMultisampleQualityLevels. Если это только для строк, я бы посоветовал попробовать альфа-сглаживание D3D11_RASTERIZER_DESC.AntialiasedLineEnable

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector