• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Tispe

Get unique IDs by reading the Instruction Pointer Register

28 posts in this topic

Hi

 

I am currently writing an IMGUI implementation and I need to create an unique ID for each widget. I thought about using the Instruction Pointer (Program Counter) since it will be the same and be unique everytime I get to the same line of code.

 

But I don't know that much about assembly that I can inline and get it read. I googled this but it does not compile in VS2010:

void *ip = 0;
asm("movl %%eip, %0" : "=r"(ip) );

 

Does it seem like a good idea to generate unique IDs like this? And can someone help me get the asm working?

 

Cheers!

Edited by Tispe
0

Share this post


Link to post
Share on other sites

This is IMGUI, the EIP will not be the same for identical widgets because each widget will be called from different parts of the code.

 

DWORD ID = GetEIP();
if(DoButton(ID,Button1,.....))
{
     //code
}

ID=GetEIP();
if(DoButton(ID,Button2.....))
{
     //code
}

0

Share this post


Link to post
Share on other sites
A combination of line number, source file ID and loop index (if you're inside a for loop) would be easier to manage.

I'm sure you will have seen this:

http://sol.gfxile.net/imgui/ch04.html

You can get away with just incrementing (in code), but then you can never change the widget set while one of them is active or the IDs will go out of sync.
0

Share this post


Link to post
Share on other sites

I was hoping that I could macro something that would give me an ID.

 

if(DoButton(GetEIP(),Button1,.....))
{
     //code
}


if(DoButton(GetEIP(),Button2.....))
{
     //code
}

 

This would pass the same unique ID everytime the code goes through that code. I want to avoid hardcoding IDs or even pass the address of a static DummyVariable.

Edited by Tispe
0

Share this post


Link to post
Share on other sites

What I have tried now is

#ifdef IMGUI_SRC_ID
#define GEN_ID ((IMGUI_SRC_ID) + (__LINE__))
#else
#define GEN_ID (__LINE__)
#endif

And then in each cpp file I do this in increments of 10000, this will work since I dont have any source files with more then 10000 Lines of code.

#define IMGUI_SRC_ID 50000

 

But.... When I now call

if(DoButton(GEN_ID,.......))
{
      //code
}

The compiler says: cannot convert parameter 1 from 'long' to 'int &'. GEN_ID is defined as long :/

 

 

So I changed to

#ifdef IMGUI_SRC_ID
#define GEN_ID int(((IMGUI_SRC_ID) + (__LINE__)))
#else
#define GEN_ID int((__LINE__))
#endif

and took out the referencing.

Edited by Tispe
0

Share this post


Link to post
Share on other sites

When I wanted to make such a function for IMGUI I tried to use the __LINE__ makro too, but found out it didnt really work cause if you call some widget from two places it would get the same id again. I also considered mangling the __FILE__ makro but that got same problem and felt too complicated for the little gain. Also just adding to the line number seems to produce less unique numbers.

So I made a custom hash function which started with somehow combining the parentid and the number of needed child ids and then wrote a bunch of unittests to verify uniqueness and that led to a number of additions and bit twiddling tweaks to the function to make it behave as good as possible even on grandchild widgets, bit overflow and wrong inputs. I'm still not convinced its completely done so I'll be looking for more improvedments later.

0

Share this post


Link to post
Share on other sites

The compiler says: cannot convert parameter 1 from 'long' to 'int &'. GEN_ID is defined as long :/


Wait, why does the function take a reference to an int? It provides no benefit over passing the int by value, and will likely result in a penalty for the level of indirection. The only reason I can see for someone to do that is if the function modifies the referred to value.

Just making sure the function isn't now modifying a temporary value, thinking it is making a change to the value passed to the function.
1

Share this post


Link to post
Share on other sites

I still don't understand why you can't just say int id=random()*random()>>random() or something similar if you absolutely must have a totally random and unique ID every time and do checks to make sure you're not getting identical ids every time, and of course you can map the results of your random id assignment to some meaningful array of structs describing the widget or whatever

Edited by darkhaven3
0

Share this post


Link to post
Share on other sites

Because the IDs must be the same everytime I get to the same line of calling code. And I don't want to keep statics, globals or singletons around to keep track of them.

0

Share this post


Link to post
Share on other sites

When I wanted to make such a function for IMGUI I tried to use the __LINE__ makro too, but found out it didnt really work cause if you call some widget from two places it would get the same id again. I also considered mangling the __FILE__ makro but that got same problem and felt too complicated for the little gain. Also just adding to the line number seems to produce less unique numbers.
So I made a custom hash function which started with somehow combining the parentid and the number of needed child ids and then wrote a bunch of unittests to verify uniqueness and that led to a number of additions and bit twiddling tweaks to the function to make it behave as good as possible even on grandchild widgets, bit overflow and wrong inputs. I'm still not convinced its completely done so I'll be looking for more improvedments later.

Why not use name your UI elements and hash that particular name into a uint32 or uint64, the only thing you need to remember is to use unique identifiers and generate them as well. This is easier on you as well no need to remember pesky numbers or ids, just use a proper name like button_1, you could extend this with including the parent id like screen_1.button_1 so you can reuse names.
Because you are using the same hash function it will be guaranteed to return the same value for both the ID on the object and the retrieving id. Edited by NightCreature83
1

Share this post


Link to post
Share on other sites

In IMGUI the UI elements are not stored anywhere, they are just created when called on, for each frame.

0

Share this post


Link to post
Share on other sites

I still don't understand why you can't just say int id=random()*random()>>random() or something similar if you absolutely must have a totally random and unique ID every time and do checks to make sure you're not getting identical ids every time, and of course you can map the results of your random id assignment to some meaningful array of structs describing the widget or whatever


This is IMGUI. The widget isn't defined until it is called. The ID is the only thing that identifies it from one frame to the next.
0

Share this post


Link to post
Share on other sites

I also think that using the IP for IDs is a bad idea but just for reference, here is how to get it (untested):

 

call my_label
my_label:
pop %eax   # IP is now in eax register

 

The problem is that in x86 you can't read the IP, like you can for example in ARM. You have to make a function call which will automatically push the return address onto the stack. Then you can pop it back off.

But again: This is probably a bad idea for IDs.

0

Share this post


Link to post
Share on other sites

You need to use Load effective address instruction instead of a move this is less hassle then jumping to a label and then popping the stack, in masm this looks as following

LEA RAX, [RIP] ;this would load the address of RIP into RAX this only works on a 64-bit CPU
LEA EAX, [EIP] ;32-bit version of the above instructions

 

Still I wouldn't advise you to do it this way as this will be extremely difficult to debug, using a string and a hash function is easier to debug as you can input the string name of the item your interested into the hash function and presto you have your ID.

1

Share this post


Link to post
Share on other sites

I'm really wondering what is insufficient about hashing the combination of __FILE__ and __LINE__. It's worked well enough for my IMGUI needs...
 

#include <iostream>
#include <tr1/unordered_map>
#include <string>

#define _STRINGIFY(X) #X
#define _TOSTRING(X) _STRINGIFY(X)
#define UNIQUE_ID() std::tr1::hash<std::string>()(std::string(__FILE__ ":" _TOSTRING(__LINE__)))

void func() {
	std::cout << UNIQUE_ID() << std::endl;
}

int main() {
	std::cout << UNIQUE_ID() << std::endl;

	for (int i = 0; i < 10; i++)
		func();

	std::cout << UNIQUE_ID() << std::endl;
}
2

Share this post


Link to post
Share on other sites

The thing that fails (with all of the IP/FILE/LINE/etc...) tricks is that it completely prevents the user of the library from saving themselves time, ever. Maybe I find myself making lots of buttons with similar behavior/logic/etc... So I make a helper function to eliminate the boiler-plate parts of the API. Oops, nothing works anymore. It ties an implementation detail of the library to the public interface, in a non-obvious way.

1

Share this post


Link to post
Share on other sites

Maybe I find myself making lots of buttons with similar behavior/logic/etc... So I make a helper function to eliminate the boiler-plate parts of the API.

Is that even a reasonable idea in an IMGUI context? How will you deal with the logic introduced by the immediate result values?

My impression is that if you try to do this, you will end up having to build an entire retained-mode wrapper around your IMGUI, and you'd be better off using an RMGUI in the first place.
0

Share this post


Link to post
Share on other sites

Maybe I find myself making lots of buttons with similar behavior/logic/etc... So I make a helper function to eliminate the boiler-plate parts of the API.

Is that even a reasonable idea in an IMGUI context? How will you deal with the logic introduced by the immediate result values?

My impression is that if you try to do this, you will end up having to build an entire retained-mode wrapper around your IMGUI, and you'd be better off using an RMGUI in the first place.

 

I think so. Maybe I have a game-specific debug menu, with some XML (or, more likely, static table in code) configuration:

 

static DebugButtonData [] =
{
  { "GodMode", toggleGodMode },
  { "NoClip", toggleNoClip },
  { etc... }
} buttons;

for (int i = 0; i < numDebugButtons; ++i)
{
  if (DoButton(buttons[i].label))
  {
    buttons[i].callback();
  }
}

 

I just don't see why you wouldn't want to be able to write code like that... (Which still leads me back to the previous suggestion - pass in a string and use that (or hash it)).

Edited by osmanb
0

Share this post


Link to post
Share on other sites

I think so. Maybe I have a game-specific debug menu, with some XML (or, more likely, static table in code) configuration:

static DebugButtonData [] =
{
  { "GodMode", toggleGodMode },
  { "NoClip", toggleNoClip },
  { etc... }
} buttons;

for (int i = 0; i < numDebugButtons; ++i)
{
  if (DoButton(buttons[i].label))
  {
    buttons[i].callback();
  }
}


Now you want to introduce externally defined callback functions? This just seems like a use-case where IMGUI doesn't fit very well.

What exactly is your fancy IMGUI buying you over a RMGUI at this point? Especially if you are requiring your programmer to manually create unique (and stable) id strings for every single widget?
0

Share this post


Link to post
Share on other sites

I think so. Maybe I have a game-specific debug menu, with some XML (or, more likely, static table in code) configuration:
 

static DebugButtonData [] =
{
  { "GodMode", toggleGodMode },
  { "NoClip", toggleNoClip },
  { etc... }
} buttons;

for (int i = 0; i < numDebugButtons; ++i)
{
  if (DoButton(buttons[i].label))
  {
    buttons[i].callback();
  }
}

 

Now you want to introduce externally defined callback functions? This just seems like a use-case where IMGUI doesn't fit very well.

What exactly is your fancy IMGUI buying you over a RMGUI at this point? Especially if you are requiring your programmer to manually create unique (and stable) id strings for every single widget?

 

No, I just want to be able to use the IMGUI API without restrictions that are based on implementation details. I'm not talking about adding callbacks to the IMGUI API, but being able to write helper code in the client application to reduce boiler-plate kruft. Assuming a simple interface with DoButton, I could write the following code:

if (DoButton("GodMode"))
{
  toggleGodMode();
}
if (DoButton("NoClip"))
{
  toggleNoClip();
}
...

 

... or I could get sick of copy-pasting and write the code I posted above. Except that __LINE__ tricks break with the shorter/easier version. And given that I need to supply a label for the button anyway ... why not use it (or a hash of it) as the ID?

0

Share this post


Link to post
Share on other sites

And given that I need to supply a label for the button anyway ... why not use it (or a hash of it) as the ID?

So there is no possibility of having two different "save" buttons in your GUI?

Labels aren't guaranteed to be unique - you need a fairly strong uniqueness guarantee to keep the GUI intact.
0

Share this post


Link to post
Share on other sites
EWClay's link points out that instead of hashing your file+line string, you just just cast it to a pointer-sized integer.

Regarding macro-generated IDs inhibiting library code / code-reuse, what's stopping you from simply not using the ID-generation macro, and instead passing your own custom IDs for those cases?
If you use a void* for the ID, then the file+line string method works, and you also have the option of using the address of any other object (e.g. An XML node) as a unique ID as well.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0