Thursday, March 7, 2013

GUI for better prototyping of samples and research

Available at https://github.com/tlorach/SvcMFCUI


SvcMFCUI

What is SvcMFCUI

SvcMFCUI is a Windows-only project, for now. However, the interface (API) to drive the UI is C++ and platform agnostic. It could be possible to implement a Linux/Apple version.
This dll is a 'service' that I created to get as fast as possible some User Interface on various tests I made.
But as many noticed, introducing a UI in a project can be a real pain : the UI requires various conditions at linkage stage; many libraries; many include files. All of the things that most of the time turn a UI into a nightmare.
When I looked at the first time to Maya (Autodesk DCC app), I found their approach rather interesting : MEL script used to build the layout; very simple commands to handle the whole... Yes... this is never the most friendly way to work and will never be as good as a good interface builder. But for my needs, the idea was good enough.
What I also noticed in some specific conditions: the UI should never be a stopper for the application to run. In other words, if one decide to remove the UI dll (SvcMFC.dll), the application should still work, but without the UI. This is true for many experiments. It is even more interesting when you might need this UI only when debugging and never later after you released the product (game...).
Finally, I wanted to decouple the implementation of the UI from the way we instanciate it and use it. For example, I implemented the same UI in OpenGL, so that it could be used as a transparent overlay on top of 3D... In any case, no matter if I used OpenGL or Windows MFC: the interface and the code written to use this UI had to be the exact same.
Note on the OpenGL part: this project got so outdated that I can't ship it as it is now. I will have to use another set of widgets, before releasing it...
What is interesting here is that no matter which implementation is used for the UI, the C++ interface is the same.

Rules

Here are the rules that SvcMFCUI had to follow:
  • No linkage with any linrary. Only dynamic loading available
  • very few include files (so far, 2 files)
  • UI build done through methods
  • UI Events do be handled in many flexible ways
  • simple controls to easily reflect some parameters without too much work
  • UI to directly update straighforward variables (float, bool, int, vectors...)
  • UI must work with a Console application (need to provide a message pump)
  • UI must work with a typical Win32 Application (message pump already there)
  • No need to be sexy ^_^... yes, Sorry but don't expect this UI to make your application good looking, like Qt or any. this is not the putpose.
This UI turns out to be useful in many prototypes I develop; it is very convenient to have some buttons, sliders, progress-bar and other things when testing 3D effects. I hope this could help some other developers, too.

What kind of UI to expect

The User interface generated here might not be good enough for those who want to create a serious and good looking application. This was not the intent. Instead, this UI will look more like a bunch of containers that can have other containers and various controls to inspect values, flags, provide buttons.
This kind of UI is largely good enough to add some useful UI while working on various projects. For example, I had to work on a server/client socket system to drive a small graphical demo from a distant server. I found useful to have the console-application server become temporarily visual thanks to this UI, so that I could tweak parameters and take actions for debugging purpose. Then when I had to ship the work, I just needed to remove the UI dll from the project and the server became invisible again !
Here is an example :
UI example

comment about the Quality of the code

Few comments to legitimate some possible issues in the source code: *This project is old and didn't get any improvement or corrections *it is using Windows MFC. I am not good at this and will never be (really not interested more than what I tried). But At this time I found MFC an "okay" solution for what I wanted to do. But between you and me... this is a rather boring area. So I used it in the best possible way of my knowledge at this time. I am sure that anybody who is more experienced in Windows controls/UI will scream when looking at some parts... I expect it. But at least : this is helping me when I need to get a quick UI.
Hopefully, addin this project on GitHub will be a starter to make it become cleaner...

General purpose Graph viewer

available at https://github.com/tlorach/nvGraphy


nvGraphy

nvGraphy is a little tool I developped internally to perform quick (and dirty ;-) overview of coma-separated files (csv).
I never got official time to write this tool. So please don't be surprised if it doesn't look like any regular windowed application.

What can it do

nvGraphy can help to quickly visualize csv files from following sources:
  • Some Graphic API benchmark log. D3D and OpenGL can be dumped in such a way that you could later look at the reports.
  • nvPerfHUD NVPMAPI csv log
  • Fraps
  • generic data (as long as lines start with a 'frame' number...)
The ideas is very simple : the first field will be used to put some values along X-axis : an axis of integers reflecting an array of data
When visualizing a csv file, each column will be considered as a specific kind of data to be displayed in its separated graph. Meaning that one csv file could lead to many graphs. On the left, there is a way to turn them ON/OFF
When visualizing many csv files, the viewer will attempt to put them in parallel : respective columns of each files will share the same graph. The intend is to help to compare one report with another.

How to use it

Simply drop the files onto the exe...
Or invoke it from a cmd line :
nvGraphy.exe file1.csv files2.csv file3.csv file4.csv ...
Some cmd line options are available :
-a  : where annotations will be saved
-n  : when sending a list of folders, this name will be appended to each path. I not used while still sending folder list, incremental_call_time_log.csv will be default
Example:
nvGraphy C:\FolderTest\GPU1 C:\FolderTest\GPU2 -a C:\FolderTest -n incremental_call_time_log.csv
Implicit load of “incremental_call_time_log.csv” (when you drag n drop some folders to nvGraphy, for example):
nvGraphy C:\FolderTest\GPU1 C:\FolderTest\GPU2

Keyboard and Mouse controls

“Help” menu tells a bit about the key shortcuts, but :
  • Left button + mouse move : select a range
  • Right button + mouse move : scroll on X axis
  • Wheel : zoom in/out in X axis. If you zoom a lot, you’ll see points
  • ‘z’ : zoom in the region. If no region, it will zoom out to show all
  • ‘Ctrl’ + wheel : zoom in Y axis ONLY the the graph on which we are
  • ‘Ctrl’ + Right button + drag : Scroll on X and Y
  • ‘Ctrl’ + ‘Shift’ + right button + drag : Scroll on Y ONLY the graph on which we move the mouse
  • Left click on Graph dots : select the graph item
  • ‘del’ on a selected box : delete the box
  • ‘del’ on a selected item of a graph : average the value. Good to remove errors in the graph
  • ‘s’ : save these annotations
  • ‘r’ : highlight Render targets and related textures
  • ‘tight graphs’ : if unchecked, each graph is independent
  • check boxes for graphs : show/hide graphs and graph displays

Display data

When many benchmark files got generated, you can now take them all and drop them to nvGraphy.
Here we have 2 files : one for a GPU1 and one for a GPU2. We can see that some parts show divergences . This would be the place where we want to start our investigations...
Note that if you place your cursor over the curve, you will get a 'tooltip' showing you values.
nvGraphy

Infos on selection

If you want to get more details on a specific section of these competitive curves, you can select this range:
nvGraphy This will show:
  • the average value for each curve
  • the growth of each curve
  • the average gap between them
  • the gradient of the gap : how fast they diverge/converge. Good to get an idea on how important is the section, on a competitive standpoint.

FRAPS saved timing

Just drop Fraps log files and you will see them...
nvGraphynvGraphy

display generic data

nvGraphy can display generic csv files. The only restriction is to have a ''frame#'' at the beginning of each line.
 Frame, Value1, Value2, value3
 1, 15%, 0.5, 3.1
 2, 25%, 1.5, 3.1
 ...
 40, 1%, 0.0, 0.1
(Note that you can use '%'...)
Each column will be displayed on a separate display.
nvGraphy
If you want to compare values in the same display, you can provide many files. For example
nvGraphy Generic.txt Generic2.txt
will display Generic and Generic2 values in the same displays :
nvGraphy

Search

Here is a simple example of searching :
  • type the text (*memcpy* in our example) and press enter
  • items where memcpy exists will be highlighted in yellow
nvGraphy
There is also an option for Regular expressions search.
Note that nvGraphy will search in all the text information available.

Annotations

nvGraphy allows you to create simple annotations : on a specific point or on a range of data.
This is rather useful when for example you want to comment a specific drawcall or highlight a specific range of operations that would for example correspond to a specific pass in the scene.

Annotation on a point

  • Select the point
  • write the comment in the dedicated text control
nvGraphy

Annotation on a range

  • Select a range of data nvGraphy
  • Write the comment in the dedicated text control nvGraphy
You can remove the comment by selecting it and pressing delete key...
There is a button to save these annotation : one file for each graph will be create with the related annotations. Later, nvGraphy will look for this file at load time.
Note: nvGraphy doesn't save automatically. You will have to do it by yourself before quitting.

Remove artifacts in the values

Some data may still contain invalid values : Sampling of time could lead to bad spikes which have no meaning at all on the curve. You may want to remove them from the graph. Select the point press 'delete' nvGraphynvGraphy

nvPerfHUD NVPMAPI csv

nvPerfHUD 5 can output its analysis from the NVPMAPI benchmark report. *F8 menu : this will perform the analysis. *under the ''state buckets'' you can choose to ''export'' data
Note that nvPerfHUD don't export State buckets information : it only exports timing for each Drawcall.
Simply drop the csv file into nvGraphy:
nvGraphy

Fast OpenGL Text rendering in GitHub

I started to use GitHub and CMake so that I could share some tools I made and that could be useful for some of you.

The first small sample I have put is a small class for text rendering: https://github.com/tlorach/OpenGLText


OpenGLText

This pair of cpp and h file provides a very easy way to draw text in OpenGL, using fonts generated from Truetype fonts.
There are many tools and libraries available. But :
  • I needed to have a really simple approach
  • I certainly didn't want to link against any huge monster, such at Freetype library
  • I never got satisfied by any existing tool on their way to batch primitives through OpenGL driver : most are rendering characters one after another (even using immediate mode). Some other might use the deprecated Display List...
  • I did not need the whole flexibility that freetype offers
  • I might want to use this implementation on tablets (Adroid and iOS)
This file proposes a very simple approach based on a texture Atlas containing all the necessary Fonts for a specific type and size. If more than one type or more than one size is needed, the application will have to work with many instances of the class and related resource.
The fonts are in a tga file; a binary file is associated, containing all the necessary offsets to work correctly with the texture-font from tga file.

Example on how to use it.

init time:
        OpenGLText             oglText;
        ...
        if(!oglText.init(font_name, canvas_width, canvas_height))
            return false;
render time:
        oglText.beginString();
        float bbStr[2];
        char *tmpStr = "Hello world";
        oglText.stringSize(tmpStr, bbStr);
        oglText.drawString(posX - bbStr[0]*0.5, posY - bbStr[1], tmpStr, 0,0xF0F0F0F0);
        ...
        oglText.endString(); // will render the whole at once

Baking Fonts

textBaker folder contains few details about this.
For now, I got a bit 'hacky', here: baking Fonts is aschieved with patching GLText 0.3.1 ( http://gltext.sourceforge.net/home.php )
This folder contains the changes I made to finally save the data I needed. Download freetype (I took 2.3.5-1) and download GLText. Then modify it with the data in this folder.
I have put a compiled version of it for Windows. Note this application would require to be better and therefore could crash or not work properly.
bakeFonts.exe < .ttf file > < size >
Example from the demo : Example
Few comments:
  • I found this tool online, but I could have used anything that would use freetype library.
  • One might argue that gltext is exactly doing what I want : display text onscreen with truetype fonts... but:
    • This project is rather big for what it does (isn't it ? :-)
    • the C++ design is overkill... at least to me
    • we must link against Freetype library to have it working. This is flexible, of course (becaude we can directly read any .ttf file...), but this is not appropriate for my goal : one might not want to link against freetype library if he targeted Android or iOS...
    • The rendering loop... is not the efficient way to do. Each font is rendered separately. Our approach is to render almost everything in one single drawcall.
The basic idea behind this patch is to allow me to save a tga file made of the character I need with the right size. a binary file will be created, in which structures of Glyphs are stored.