| 53 | } |
| 54 | |
| 55 | std::string GetDeviceDebugMessages(ID3D11Device* device, HRESULT originalHr) |
| 56 | { |
| 57 | if (!device) |
| 58 | return {}; |
| 59 | |
| 60 | std::string result; |
| 61 | |
| 62 | // GetDeviceRemovedReason() works in release mode (no debug layer needed). |
| 63 | if (originalHr == DXGI_ERROR_DEVICE_REMOVED) |
| 64 | { |
| 65 | HRESULT reason = device->GetDeviceRemovedReason(); |
| 66 | result += " DeviceRemovedReason: " + GetHResultDescription(reason); |
| 67 | } |
| 68 | |
| 69 | // ID3D11InfoQueue is only available when the device was created with |
| 70 | // D3D11_CREATE_DEVICE_DEBUG. The QueryInterface call will simply fail |
| 71 | // in release builds, so this block is skipped silently. |
| 72 | Microsoft::WRL::ComPtr<ID3D11InfoQueue> infoQueue; |
| 73 | if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11InfoQueue), &infoQueue)) && infoQueue) |
| 74 | { |
| 75 | auto messageCount = infoQueue->GetNumStoredMessages(); |
| 76 | if (messageCount > 0) |
| 77 | { |
| 78 | result += " D3D11 debug messages:"; |
| 79 | auto maxMessages = std::min(messageCount, static_cast<UINT64>(5)); |
| 80 | |
| 81 | for (UINT64 i = messageCount - maxMessages; i < messageCount; i++) |
| 82 | { |
| 83 | SIZE_T messageLength = 0; |
| 84 | infoQueue->GetMessage(i, nullptr, &messageLength); |
| 85 | |
| 86 | std::vector<byte> messageData(messageLength); |
| 87 | auto* message = reinterpret_cast<D3D11_MESSAGE*>(messageData.data()); |
| 88 | infoQueue->GetMessage(i, message, &messageLength); |
| 89 | |
| 90 | result += "\n - " + std::string(message->pDescription, message->DescriptionByteLength - 1); |
| 91 | } |
| 92 | |
| 93 | infoQueue->ClearStoredMessages(); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | return result; |
| 98 | } |
| 99 | |
| 100 | void throwIfFailed(const HRESULT& res) |
| 101 | { |
no test coverage detected