Is there a way to receive as a string, the errors from DX12? - directx-12

Example: Here's the debug log for CreateGraphicsPipelineState, it tells me what went wrong:
D3D12 ERROR: ID3D12Device::CreateGraphicsPipelineState: Root Signature doesn't match Vertex Shader: Shader CBV descriptor range (RegisterSpace=0, NumDescriptors=1, BaseShaderRegister=0) is not fully bound in root signature
However, a call to windows FormatMessage(MESSAGE_FROM_SYSTEM...) will return this for the exact same error:
The parameter is incorrect.
The first is obviously far more useful...
We used to have dxerr.lib, and we have source for dxerr.cpp in DXUT. But this doesn't cover DX12. I can't see any way for a shader-tool to retrieve the error and present it to the user from the API.

This can be done with the ID3D12InfoQueue interface, as documented here:
https://learn.microsoft.com/en-us/windows/win32/api/d3d12sdklayers/nn-d3d12sdklayers-id3d12infoqueue
As far as I can tell it's currently not possible to set a callback, which means that you'll need to explicitly query for feedback.

There are two different sources of error/status information involved here. The error code you have returned from the API call is E_INVALIDARG and you obtained a good string for it. This is the status code from the API.
The descriptive message you see in debug output is emitted by Direct3D 12 debug layer, which you loaded during API initialization. It is, generally speaking, an optional component and might be not available in the system while the API itself is available.
To intercept debug output programmatically you can either
utilize this trick: Capture OutputDebugString output
or, attach as a debugger to your application and process debug output event recording the contents

Related

DirectInput console application

I'm working in C++ in Windows and I need to deal with an input device with force feedback. I found out that one solution could be to use DirectInput and so I start looking at that.
FIRST QUESTION: any suggestions on other ways for dealing with force feedback devices? (Win32 app, not UWP)
Coming back to DirectInput
The reference starting point I have got in my mind is the DirectInput Samples, in particular the FFconst example where a constant feedback force is applied to the first device axis according to a value grabbed from a simple GUI. In my case what I want to achieve is having a simple console application where I set a constant force according to a value grabbed from the standard input.
The basic steps for using the DirectInput API, according to the samples and the documentation, are:
create direct input device calling DirectInput8Create;
look for devices calling EnumDevices filtering devices and limiting scope to the enumeration according to what you are looking for (in my case I'm filtering for looking only in DI8DEVCLASS_GAMECTRL devices and limiting the scope to DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK);
set data format for the selected device(s) calling SetDataFormat in order to be able to acquire the device;
set the cooperative level for the device(s) calling SetCooperativeLevel once again in order to acquire the device;
use the device...
Now, all goes well until we encounter the SetCooperativeLevel mehtod since it needs as input a HWND window handle "to be associate to the device" and which "must be a valid top-level window handle that belongs to the process". Since I'm writing a console application I need to find a valid HWND pointer: I sorted the problem out following this suggestion. Anyway, the HWND pointer I get in that way seems not to be a valid window handle since I get a E_HANDLE error, as I would specify nullptr as argument. I found out that specifying the argument through the call of GetTopWindow allows not to get the invalid handle error. However I'm not able to acquire the device and I get the DIERR_OTHERAPPHASPRIO error, which is nothing more than E_ACCESSDENIED. I found that it seems someone use to treat that error in the same way the DIERR_INPUTLOST error is treated, i.e. re-acquiring the device in a while loop as shown in the Joystick direct input sample in the UpdateInputState function. Anyway trying this I'm not able to exit that loop, i.e. the device device keep being denied.
That said I end up with the
SECOND QUESTION: how to use the DirectInput API in a console application or inside a DLL? (Win32) In case of a console application I'd like to understand why the steps I've done don't work, and in case of a DLL I'd like to know if anyone has an idea on which HWND pointer could be used.
Microsoft provides a function to get a console application's window for uses like this.
HWND WINAPI GetConsoleWindow(void);

Handling WinAPI error return values

I am currently learning C++ in connection with WinAPI. I am struggling to come up with meaningful error handling strategy for WinAPI functions.
PROBLEM:
Most of WinAPI functions can return 0 in case of error, but in many cases I don't see any information on MSDN as to what could cause such error and how to address / resolve it. Taking GetCursorPos as an example:
Returns nonzero if successful or zero otherwise. To get extended error information, call GetLastError.
(...)
The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with the HDESK returned by OpenInputDesktop to switch to that desktop.
If I follow the route of GetLastError I am interested in what errors could be returned by that specific function so that I can inspect what can be done about them. But error codes are organized on this MSDN page into 10 groups based on just error number and without any specification of what errors are listed in which group.
When I tried to discover how would OpenInputDesktop help me make my code more bulletproof I discovered that again:
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
To sum it up: almost every function in WinAPI can return value determining occurrence of error and I can get information on the error when it happens using GetLastError function. But no information whatsoever on what kinds of errors I can expect and what steps to make to resolve them.
The examples are many, GetWindowRect is also widely used and MSDN delivers the very same limited information as for GetCursorPos.
QUESTION:
Please are there any standards on how to approach WinAPI function error return values that would retain error handling from becoming just showing a message box and exiting the application? Thank you!
As far as knowing ahead of time what possible error codes can be returned by a particular function, I'm afraid that Microsoft decided long time ago that maintaining such documentation for all functions would be too cumbersome and costly, as an API function may call any number of other API functions, which in turn may call others and so on. Sometimes you get lucky and the MSDN doc calls out error codes specific to that function, as is the case with ReadFile but this is not the case with all functions as you have noticed.
That being said, the standard way of dealing with the error codes returned by GetLastError() is to format them with FormatMessage.
If you passed LANG_USER_DEFAULT for lang ID, this will return the sometimes helpful, sometimes not so helpful error message formatted in the user's chosen locale from the error code. You can show this message to the user. If you wanted to format it in your own language for logging purposes, assuming it's English, you would pass MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) for lang ID.
And this is the best you can do if the error codes are not documented and you haven't come across them in testing: log them and get the log with other debug info attached to the issue report.

Is there any way to get more detailed error reports from a windows API call?

I'm working on a pretty large program that makes calls to ChangeDisplaySettingsEx in order to change the layout/resolution around of displays.
I've been running into issues where these calls sometimes work and sometimes they don't, and I can't determine what's causing the failures.
Whenever it fails, I get a return code of -1 which corresponds to DISP_CHANGE_FAILED which clearly is not very descriptive.
I'm wondering if there's any better way to debug the result of the call so I can tell what's causing it to fail?
"I'm wondering if there's any better way to debug the result of the call so I can tell what's causing it to fail?"
You may try to query the actual displays capabilities beforehand, as recommended in the reference documentation:
Remarks
"To ensure that the DEVMODE structure passed to ChangeDisplaySettingsEx is valid and contains only values supported by the display driver, use the DEVMODE returned by the EnumDisplaySettings function."
After doing so you can compare the returned DEVMODE with what you've tried to pass as settings.

AllocConsole error codes

What error codes can a failed call to AllocConsole generate? On the MSDN website it says If the function fails, the return value is zero. To get extended error information, call GetLastError. But I see no place saying what kinds of errors it can generate.
In most system calls, there is a rather long list of "possible failure scenarios", and that means that you get a large number of possible error codes. For example, some resource in the OS may be full (I expect there is a list of consoles in the OS somewhere, and if that list is full and/or can't be grown, there is some error for that). The Console also needs to have memory as a buffer for the text content, as well as a graphical output buffer (to avoid having to draw every character every time the screen is refreshed) - both of these lead to at least two distinct errors (out of memory, out of graphics memory, and possibly "no way to create a handle for the graphics resource").
A different category of possible errors are permission based ones - maybe your process (based on the user being logged in) doesn't have enough permissions to create a console.
I'm pretty sure the list of actually possible errors is much greater than that.
In summary, don't expect that the errors you can get from a function is limited - if you are interested in a particular set of error codes, then check for those, and do something sane if it isn't one of those. Don't expect that you can't get any other error code.

Get the identifier of a Windows error code

In a program I'm developing I need to gather information about runtime errors. Currently, I am able to gather all the information I need, including the message via FormatMessage, but the identifier of the error (for example, ERROR_SUCCESS). I know that when the application is compiled these identifiers are not actually present in the binaries.
Is there a function in the Windows API which can retrieve these identifiers or do I need to store them with my application?
ERROR_SUCCESS itself is just a constant. I haven't found a way to go from number -> constant identifier.
You could scan WinError.h with Clang and create some kind of table for your application.
Here is a nice example of how you can get the ErrorCode and how to translate it to a more readable message on MSDN.
No need to copy that over, its quite plain:
Retrieving the last error code and message