Imagination PowerVR SDK Blog

SDK 3.4 VFrame/Trace problems on Windows 32-bit

pvrvframe
pvrtrace

#1

I’ve noticed that the base emulation libs (PVRVFrame) in SDK 3.4 for Windows_x86_32 don’t work. They fail early on, with glGetString( GL_VERSION ) returning:



(Host : 4.2.11796 Compatibility Profile Context FireGL)



while the SDK 3.3 PVRVFrame libs work fine (have been running with those for months).



Given that my real goal is to get PVRTrace working on Windows with our PowerVR-targetted application. So I tried running:


  1. SDK 3.4 PVRTrace stub libs with
  2. SDK 3.3 PVRVFrame EGL/GLES libs.



    That partially works, but only EGL calls are listed in the trace (no GL calls).



    Any tips on how I get PVRTrace fully working on Windows? Or if I can provide any additional details that would help, just let me know. --Thanks.

#2

The forum markup munged the glGetString( GL_VERSION ) error. Here it is, protected in a code block:

(Host : 4.2.11796 Compatibility Profile Context FireGL)


#3

Hi Dark_Photon



That isn’t really a showstopping failure. There is a bug in SDK 3.4 where PVRVFrame won’t report the version string correctly, so “Failed to query OpenGL ES version” basically means “OpenGL ES 3.0”. It’s safe to ignore.


#4

Thanks, Chris. Based on your post in OSX EGL Initialization Issues, I had already tried that (i.e. ignoring the failed glGetString( GL_VERSION ) query and assumed 3.0 in this case).



However, I’m still not seeing any GLES library calls emitted in the .pvrt dump – only EGL (using PVRTraceGUI 3.4 to view the trace). This was a test with all SDK 3.4 components (VFrame, Trace, and TraceGUI).



Any other ideas? --Thanks.


#5

Also, in case it may provide clues, attached is my pvrtraceconfig.json.



{

“Host”:

{

“Es2LibraryPath”: “D:…\SYS_LIBS\libGLESv2.dll”,

“Es1LibraryPath”: “D:…\SYS_LIBS\libGLES_CM.dll”,

“EglLibraryPath”: “D:…\SYS_LIBS\libEGL.dll”

},



“Debug”:

{

“Level”:2

},



“Tracing”:

{

“OutputFilename”: “%pname-%pid.pvrt”,

“StartFrame”: 0,

“EndFrame”: 1000,

“ExitOnLastFrame”: true

}

}


#6

I would double check that the libraries you are using to record are definitely the PVRTrace Recorder libraries. Perhaps you have accidentally overwritten GLES_CM/GLESv2 with the emulation libraries instead.



Note that for viewing the trace you don’t need to copy the new emulation libraries anywhere as they are already contained within PVRTraceGUI.


#7

Ok, I just verified that. The correct libs were/are in-place.



The DLLs in the EXE directory are definitely the PVRTrace 3.4 (@3188797) Win 32-bit Recorder libraries:



$ ls -1 -s --block-size=1 *.dll

22016 OpenCL.dll

798208 PVRTrace.dll

20992 libEGL.dll

35840 libGLES_CM.dll

7168 libGLESv1_CM.dll

19968 libGLESv2.dll



$ md5sum *.dll

5f4850d2652bc9cbab1c84f0c1d66a33 *OpenCL.dll

3cdf424be66e937362c88209b940c608 *PVRTrace.dll

b0f35ac31c1d45498745429f6284794c *libEGL.dll

a3871e344ecc384e6739ec12dabd102b *libGLES_CM.dll

880c9160643a5754ad96270d9d359a33 *libGLESv1_CM.dll

c70a3e45389e13962375da2b1013eec0 *libGLESv2.dll




and the DLLs in the “SYS_LIBS” subdirectory (listed above in the json file) are definitely the PVRVFrame 3.4 Win 32-bit libraries:



$ ls -1 -s --block-size=1 *.dll

285184 libEGL.dll

1674752 libGLES_CM.dll

2744320 libGLESv2.dll



$ md5sum *.dll

e80c9d86006ff41714ab0e68245f4828 *libEGL.dll

4ed678533eb4cd28e91438f01ce618a0 *libGLES_CM.dll

3504a688119926f093cd787a7129141d *libGLESv2.dll




Any other ideas? --Thanks for your help!


#8

Hmmm well those definitely look correct. At the moment it sounds like the app is using the correct libEGL recording library but the wrong one for libGLES. This would result in a recording with only the EGL calls.



Where do the recording libraries reside relative to the app being recorded? It’s best to place them alongside the executable so they will always be selected first. If you have them somewhere else then maybe some other libGLESv2.dll is taking precedence.


#9
Hmmm well those definitely look correct. At the moment it sounds like the app is using the correct libEGL recording library but the wrong one for libGLES. This would result in a recording with only the EGL calls.

RIght! Just what I was thinking. However, I'm doing exactly the same thing with the EGL and GLES* libs so I'm puzzled.

It's like the GLESv2 "recording" library that comes with PVRTrace 3.4 has not been compiled properly, or its logging is disabled internally somehow.

Where do the recording libraries reside relative to the app being recorded? It's best to place them alongside the executable so they will always be selected first.

As I mentioned, the PVRTrace "recording" libraries are in the EXE directory (alongside the executable), just as you suggest.

Could you test PVRTrace+PVRVFrame there on a 32-bit Windows app (one that targets GLESv2 or v3, not v1) to see if you get the same results as I'm seeing? Thanks!

#10

I haven’t been able to reproduce the problem here. Could you try recording a simple app such as one of the examples included in the SDK and see if the ES calls are recorded successfully?


#11

Thanks for testing that, Chris! I tried your suggestion with the “Simple Triangle” Chapter 2 example from the “The OpenGL ES 3.0 Programming Guide” example pack, and that did produce a GL trace log with both EGL and GL calls.



However, applying the same procedure to this much larger application (as I’d been doing before) resulted in: 1) A crash half the time in a glDrawArrays call, or 2) on the other runs where it did render properly and apparently work, there again were only EGL calls in the log (no GL calls).



In both cases, all components were pulled from SDK 3.4, and I made to sure rebuild both applications with the LIB import libraries in PVRVFrame. I should also mention (while it doesn’t guarantee no application bugs) that this same application has been completely stable with PVRVFrame 3.3 libraries for months.



Do you have any other suggestions for how to debug this? Are there any “debug tricks” I can use to establish that PVRTrace’s libGLESv2.dll recorder shim is being successfully loaded and is working properly?



Thanks for any tips you can provide!


#12

You could use Process Explorer to view the DLLs running under the application as you record it (View -> Lower Pane View -> DLLs).



There should be two entries each for libEGL.dll and libGLESv2.dll, one for the PVRTrace and a second for PVRVFrame.


#13
...Process Explorer...There should be two entries each for libEGL.dll and libGLESv2.dll, one for the PVRTrace and a second for PVRVFrame.



Thanks! Just tried this, and what I see is:
libEGL.dll c:...MyApplibEGL.dll
libEGL.dll c:...MyAppSYS_LIBSlibEGL.dll
libGLESv2.dll c:...MyAppSYS_LIBSlibGLESv2.dll

As you can see, only the libEGL.dll "PVRTrace" lib is loaded, along with the two "PVRVFrame" libs (in SYS_LIBS).

I've attached the startup log below (at PVRTrace Debug level 2) in case it may provide clues. If you search down for libGLESv2, it's interesting that the dynamic loader "does" load MyApplibGLESv2.dll (PVRVFrame GLESv2 lib) but then turns around and unloads it for some reason (maybe "why" is the crucial question here). Then later, PVRTrace dynamically loads in SYS_LIBSlibGLESv2.dll (PVRVFrame lib).



(Startup log with JSON pointing to SYS_LIBSlibGLESv2.dll)

...
'MyApp.exe' (Win32): Loaded 'c:...MyApplibEGL.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Loaded 'c:...MyAppPVRTrace.dll'. Cannot find or open the PDB file.
...
PVRTrace: DllMain
PVRTrace: DLL_PROCESS_ATTACH.
PVRTrace: DLL_THREAD_ATTACH
...
'MyApp.exe' (Win32): Loaded 'c:...MyApplibGLES_CM.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Unloaded 'c:...MyApplibGLES_CM.dll'
'MyApp.exe' (Win32): Loaded 'c:...MyApplibGLESv2.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Unloaded 'c:...MyApplibGLESv2.dll'
'MyApp.exe' (Win32): Loaded 'c:...MyAppOpenCL.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Unloaded 'c:...MyAppOpenCL.dll'
...
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
...
Config file found: c:...MyApp/pvrtraceconfig.json

Opening trace file 'MyApp.exe-4204.pvrt' for recording.
Recorder Version: 3.4@3188797
Calling function eglGetDisplay
Loading host library 'c:...MyAppSYS_LIBSlibEGL.dll'
'MyApp.exe' (Win32): Loaded 'c:...MyAppSYS_LIBSlibEGL.dll'. Module was built without symbols.
Host library 'c:...MyAppSYS_LIBSlibEGL.dll' loaded
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
PVRTrace: DllMain
The thread 0xdd8 has exited with code 0 (0x0).
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64opengl32.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64glu32.dll'. Cannot find or open the PDB file.
...
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64atiglpxx.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64atioglxx.dll'. Cannot find or open the PDB file.
...
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64atiadlxy.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64userenv.dll'. Cannot find or open the PDB file.
...
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64atigktxx.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64aticfx32.dll'. Cannot find or open the PDB file.
'MyApp.exe' (Win32): Unloaded 'C:WindowsSysWOW64atigktxx.dll'
'MyApp.exe' (Win32): Loaded 'C:WindowsSysWOW64atigktxx.dll'. Cannot find or open the PDB file.
Calling function eglInitialize
Calling function eglBindAPI
Calling function eglQueryString
Calling function eglChooseConfig
Calling function eglGetConfigAttrib
Calling function eglGetConfigAttrib
Calling function eglGetConfigAttrib
Calling function eglGetConfigAttrib
Calling function eglCreateContext
'MyApp.exe' (Win32): Loaded 'c:...MyAppSYS_LIBSlibGLESv2.dll'. Module was built without symbols.
Calling function eglCreateWindowSurface
Calling function eglQuerySurface
Calling function eglQuerySurface
Calling function eglSwapInterval
Calling function eglQuerySurface
Calling function eglQuerySurface
...
Calling function eglMakeCurrent
'MyApp.exe' (Win32): Loaded 'c:...MyAppSYS_LIBSlibEGL.dll'. Module was built without symbols.
'MyApp.exe' (Win32): Unloaded 'c:...MyAppSYS_LIBSlibEGL.dll'
Loading host library 'c:...MyAppSYS_LIBSlibGLESv2.dll'
Host library 'c:...MyAppSYS_LIBSlibGLESv2.dll' loaded
Calling function eglSwapInterval
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
Calling function eglSwapBuffers
PVRTrace: DllMain
PVRTrace: DLL_THREAD_ATTACH
Recording... Current frame: 1
Calling function eglSwapBuffers
Recording... Current frame: 2
...
PVRTrace: DllMain
...
Calling function eglMakeCurrent
Calling function eglDestroySurface
Calling function eglDestroyContext
Calling function eglTerminate
PVRTrace: DllMain
...
The program '[0x106C] MyApp.exe' has exited with code 0 (0x0).

#14
..it's interesting that the dynamic loader "does" load MyApplibGLESv2.dll (PVRVFrame GLESv2 lib)

Sorry, I mis-spoke. MyApplibGLESv2.dll is of course the "PVRTrace" GLESv2 lib.

#15

Hi Dark_Photon!



I managed to reproduce this behaviour by instructing the linker to delay-load libGLESv2.dll. In Visual Studio: Configuration Properties -> Linker -> Input -> Delay Loaded Dlls.



I believe the result of this is that when the application finally makes a GLES call the symbols are already loaded, except they’re the wrong ones, because the emulation library is loaded into the process before the Windows linker tries searching for libGLESv2.dll.



Do you have delay-loading enabled in your build? I think we can add a fix for this to PVRTrace, but for now a workaround would be to disable the delay-loading of libGLESv2.dll


#16

Hey, thanks Chris! That’s a good find! However, I just checked the vcproj “DelayLoadDLLs” setting for the configuration I’m running (and all configs), and it is set to “$(NOINHERIT)” (which if I understand correctly means “”.



I’ll keep looking for the cause, but if you have any further suggestions, please do follow-up. Thanks for the help!


#17

A work-around for this problem (on Win32) seems to be to:

  1. add a hard reference to a gl*() symbol (defined in libGLESv2.dll) in your app’s source code,
  2. link with libGLESv2.dll.



    If an application uses eglGetProcAddress() to fetch all gl* function pointers (instead of hard-linking with them in the GLESv2 library directly), the application does not directly reference any symbols defined in libGLESv2.dll. This causes the linker to throw out the reference to that GLESv2 library (if it is even specified on the link line, which is optional).



    Despite that lack of direct linkage, somehow libGLESv2.dll (PVRVFrame) is still cascade-loaded and its symbols made available to the application when running normally, or when running under PVRTrace (my guess is via dlopen/LoadLibrary* logic going on in libEGL when you call eglGetProcAddress()).



    The long and short of it is: if the app is not hard-linked to libGLESv2.dll, then PVRTrace will not dynamically link in the recorder libraries and function properly.



    It would seem that, at least for one GL symbol, you have to not use the eglGetProcAddress() technique and put a hard-reference in the app code to a GL call, which will force the linker to designate this library as a hard link dependency. Alternatively, use platform-specific techniques to force the linker to pull in this library “even though” the application does not reference any symbols exported by it directly.



#18

Thanks for the help Dark_Photon. It seems this all comes down to the order in which the DLLs are loaded. I should note that using eglGetProcAddress to fetch core GL functions is an EGL 1.5 feature and we currently only support up to EGL 1.4, so you’ll need to use hard links anyway.



The culprit is actually eglCreateContext as PVRVFrame loads libGLESv2 during context creation whereas PVRTrace will not attempt to load it until eglMakeCurrent. We’re looking into adding a hack to PVRTrace to force the recording libraries to be loaded first.


#19

Ok, thanks Chris! I appreciate all your help!