GetRawInputData returns nothing but nulls when using ICC

GetRawInputData returns nothing but nulls when using ICC

Chakmeshma's picture

I switched today to Intel C++ Compiler in hope for better performance and less dependency (although not sure about dependency!).

I used to code in Visual Studio and compile my code with it's native compiler.

When i compile my code (which is a Win32 Application that uses OpenGL, i.e. a game), ICC does it fine and issues no errors. However some part of the application doesn't seemingly work. I use RawInput ( to work with mouse and fetch data from it, which is necessary for any FPS-style game. The problem is that, part of the code that is responsible for getting data from mouse and process it behave rather strangely. The function GetRawInputData which returns the mouse data as its third parameter only gets me an array of nulls (x00). I've had no problem when i compiled my code with VC.

The function is inside the Window Callback Procedure (registered in the Window's class structure (WNDCLASS)) and will be called everytime a WM_INPUT is issued.

13 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Sergey Kostrov's picture

>>The problem is that, part of the code that is responsible for getting data from mouse and process it behave rather strangely.
>>The function GetRawInputData which returns the mouse data as its third parameter only gets me an array of nulls (x00).

You need to provide more technical details about compiler version, optimization options, configuration ( Debug or Release ) and internals of the function.

As a starting point in the investigation I would disable all optimizations in order to check that the function is working in that case. Take into account that Intel C++ compiler options /O2 and /O3 could "optimize-out" some for or while loops ( still Not proven if this is applicable in your case ).

jimdempseyatthecove's picture

Follow Sergey's advice. If Debug build fails then you may have a bug in your code in that it relies on undefined behavior. Example:

One compiler, no mouse data, output status== no data or 0 data, output not modified (garbage-in, garbage-out OR prior mouse state in - prior mouse state out).

Other compiler no mouse data, output status== no data or 0 data, output buffer wiped. (no data == wipe output buffer)

If you are relying on undocumented behavior then this is your problem. This may require you to fix your code to read into alternate buffer, if no error, then copy to desired buffer (as opposed to assuming buffer not modified when no input).

Are you testing for error return?

Jim Dempsey

www.quickthreadprogramming.com
Chakmeshma's picture

MessageBuildingWithCompiler: Building with Intel(R) C++ Compiler XE 13.1

IDE: Microsoft Visual Studio 2012

Configuration: Release

Intel Options:

Intel Debugging:
Number of Intel Cilk Plus Threads: [n/a]

Intel Performance Libraries:
Use IPP: No
Use MKL: No
Use TBB: No
Instrument for use with Intel Threading Analysis Tools: No

C/C++:
Enable Expanded Line Number Information: No
Interprocedural Optimization: No
Optimize For Windows Application: No
Flush Denormal Results To Zero: No
Enable Matrix Multiply Library Call: Default
Loop Unrolling: [n/a]
Parallelization: No
Use Intel Optimized Headers: No
Unmask Floating Point Exceptions: No
Floating Point Expression Evaluation: Default
Disable Function Splitting: No
Add Processor-Optimized Code Path: None
Intel Processor-Specific Optimization: None
Check Pointers: None
Turn off Checking for Undimensioned Arrays: No
Check Dangling Pointers: None
Replace Intel Cilk Plus Keywords With Serial Equivalents: No
Disable All Intel Language Extensions: No
OpenMP Support: No
Enable C99 support: Yes (/Qstd=c99)
Enable C++0x Support: Yes (/Qstd=c++0x)
Recognize The Restrict Keyword: No
Enable Use of ANSI Aliasing Rules in Optimizations: No
Disable Precompiled Header Messages: [n/a]
Error Limit: [n/a]
Disable Specific Diagnostics: [n/a]
Emit Diagnostics to File: No
Diagnostics File: $(IntDir)$(TargetName).diag
Vectorizer Diagnostic Level: Default
Optimization Diagnostic Level: Disable
Emit Optimization Diagnostics to File: No
Optimization Diagnostics File: $(IntDir)$(TargetName).rep
Optimization Diagnostic Phase: All optimizer phases
Optimization Diagnostic Routine: [n/a]
Level of Static Analysis: None
Mode of Static Analysis: None
Analyze Files Individually: No
Treat Enumerations As Known Ranges: No
Static Analysis Results Directory: My Inspector XE Results - $(ProjectName)
Analyze Include Files: No
Guided Auto Parallelism Analysis: Disable
Emit Guided Auto Parallelism Diagnostics to File: No
Guided Auto Parallelism Diagnostics File: $(IntDir)$(TargetName).gap
Guided Auto Parallelism Code Selection Options: [n/a]
All Options:
/GS /W3 /Gy /Zc:wchar_t /Zi /O2 /Fd"Release\vc110.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Qstd=c++0x /Zc:forScope /Gd /Oi /MT /Fa"Release\" /EHsc /nologo /Fo"Release\" /Qstd=c99 /Fp"Release\BrainLab.pch"

Linker:
Interprocedural Optimization: Yes
Assembler Output: No Listing
ASM List Location: [n/a]
Object File Name: [n/a]
All Options:
/OUT:"C:\Users\Matrix\documents\visual studio 2012\Projects\EvolveMe\Release\BrainLab.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Users\Matrix\documents\visual studio 2012\Projects\EvolveMe\Release\BrainLab.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG /MACHINE:X86 /OPT:REF /SAFESEH / /INCREMENTAL:NO /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release\BrainLab.exe.intermediate.manifest" /OPT:ICF /NOLOGO /TLBID:1

Codes that relate to GetRawInput (documentation)

...

#ifndef HID_USAGE_PAGE_GENERIC
     #define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
     #define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif

...

int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nShowCmd)
{
...
     RAWINPUTDEVICE Rid[1];
     Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
     Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
     Rid[0].dwFlags = RIDEV_INPUTSINK;
     Rid[0].hwndTarget = hwnd;
     RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
...
}

...

LRESULT __stdcall WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
...
     static BYTE lpb[40];
...
     case WM_INPUT:
          GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));

          raw = (RAWINPUT*)lpb;

          if (raw->header.dwType == RIM_TYPEMOUSE) {
               mousePath[0] = raw->data.mouse.lLastX;
               mousePath[1] = -raw->data.mouse.lLastY;
               mousePath[2] = 0.0F;
          }
...
}

...

Description:
I add this code after the "raw = (RAWINPUT*)lpb;" to check whether the array is null or not:
for(int i = 0; i < 40; i++) {
     if(lpb[i] != '\0') exit(EXIT_FAILURE);
}

When i compile the program using the ICC: I move the mouse and nothing happens (the program doesn't exit), meaning the data fetched is an array of nulls.
When i compile the program using VC++: I move the mouse and the program exits, meaning the data fetched is correct (at least, not an array of nulls).

Sergey Kostrov's picture

>>...Configuration: Release

- Please change the Configuration to Debug
- Disable All optimizations ( /O2 in your case / set it to /Od ) in order to verify that processing of raw data is working (!)
- A couple of modifications will also help and they are as follows:
...
case WM_INPUT:
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));

raw = (RAWINPUT*)lpb;
if( raw == NULL )
::MessageBox( GetActiveWindow(), _T("Information"), _T("[ raw is NULL - No Input Data]"), MB_OK );
else
{
::MessageBox( GetActiveWindow(), _T("Information"), _T("[ raw is NOT NULL - Input Data]"), MB_OK );
if ( raw->header.dwType == RIM_TYPEMOUSE )
{
// Save values of raw->data.mouse.lLastX and raw->data.mouse.lLastY in a temporary string for displaying with
// MessageBox Win32 API function

mousePath[0] = raw->data.mouse.lLastX;
mousePath[1] = -raw->data.mouse.lLastY;
mousePath[2] = 0.0F;
}
}
...
- Try to use as many as possible calls to MessageBox function in order to understand where the problems happens.

jimdempseyatthecove's picture

You also might try:

UINT returnBytes = GetRawData(...

And then check the value of returnBytes. If the value is (UINT)-1 then there is an error, if the value is 0 then there is no data, if the value is not== sizeof(RAWINPUT) then something else is happening.

You also might consider comparing _FUNCDNAME_ (decorated name of enclosing function) and _FUNCSIG_ (signature of enclosing function). This might expose a difference in declaration of GetRawData. There should be no difference as this should be declared in the MS VS headers (not in Intel headers). It won't hurt to check.

Also, for each compiler, find out what it uses as sizeof(RAWINPUTHEADER)

Jim Dempsey

www.quickthreadprogramming.com
Sergey Kostrov's picture

>>...There should be no difference as this should be declared in the MS VS headers (not in Intel headers)...

Here is a short quote from MSDN:

...
Topic: GetRawInputData Function
...
Declared in Winuser.h, include Windows.h
...

and it is clear that these two headers are included since there No any compilation errors.

Chakmeshma's picture

Quote:

Sergey Kostrov wrote:

if( raw == NULL )

The Problem isn't that the raw is itself NULL, it's a vaild pointer to an array of NULLs.

BTW, it gets the same result from both compilers ([ raw is NOT NULL - Input Data]) at the first occurance and thereafter.

Quote:

jimdempseyatthecove wrote:

You also might try:

UINT returnBytes = GetRawData(...

>>And then check the value of returnBytes. If the value is (UINT)-1 then there is an error, if the value is 0 then there is no data, if the value is not== sizeof(RAWINPUT) then something else is happening.

>>You also might consider comparing _FUNCDNAME_ (decorated name of enclosing function) and _FUNCSIG_ (signature of enclosing function). This might expose a difference in declaration of GetRawData. There should be no difference as this should be declared in the MS VS headers (not in Intel headers). It won't hurt to check.

>>Also, for each compiler, find out what it uses as sizeof(RAWINPUTHEADER)

The return value of GetRawInputData is -1 in ICC and 40 in VC.

How am i supposed to use the two Macros inside an already compiled library (which contains the GetRawInputData)?

no difference for sizeof(RAWINPUTHEADER) (16).

jimdempseyatthecove's picture

>>The return value of GetRawInputData is -1 in ICC and 40 in VC.

This indicates an argument error. You are using:

 GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));

A guess is you may have declared lParam as a DWORD and you are compiling for 64-bit. Handles are not DWORD on 64-bit.
Note, a header may have done the nasty on you. The cast to (HRAWINPUT) won't fix the missing data.

In the debugger, what is the type of lParam? Is it different between compilers?
Also, flip it around. If lParam is correct for a handle, then see if (HRAWINPUT) is correct type for handle.

Jim Dempsey

www.quickthreadprogramming.com
Sergey Kostrov's picture

>>...The return value of GetRawInputData is -1 in ICC and 40 in VC...

What configuration did you use for that test? Release or Debug? If it was done in Release then switch configuration to Debug and repeat the test, that is, when all optimizations are disabled.

Also, please review the following link on MSDN:
.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645546(v=vs.85).aspx

Chakmeshma's picture

I'm not compling for/in 64-bit environment.

The result is same in Release and Debug.

Everything else in the code works fine except mentioned part.

jimdempseyatthecove's picture

Is there an issue between __stdcall and __cdecl (either implicit or explicit)?

Can you use the Disassembly window to see what is going on (differnece between compilers). The -1 indicates bad arguments.

Jim Dempsey

www.quickthreadprogramming.com
Sergey Kostrov's picture

>>...The result is same in Release and Debug...

In your 2nd post there are lots of technical details for Release configuration. Could you post complete technical details for Debug configuration?

Login to leave a comment.