Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 02 Feb 2004
Offline Last Active Sep 04 2013 10:12 PM

Posts I've Made

In Topic: questions about singletons

28 August 2013 - 02:21 PM


 Sometimes you truly only want one instancing of something running around (assert tracker, GPU wrapper etc)


This is misleading -- You may "want" only one, but it's very, very seldom that one cannot imagine a scenario where, in fact, you actually need more than one, and even more seldom when having more than one would actually be incorrect. Usually when a programmer says "I'll use a singleton because I only want one of these." what he's really saying is "I'll use a singleton because I don't want to bother making my code robust enough to handle more than one of these."


If you can justify choosing convenience over correctness you're free to do so, but you've made your bed once you've chosen a Singleton and you alone will have to lay in it.



...yeah, 'correctness' in software design; something that's largely considered undefinable.  We are not scientist doing good science or bad science; we are craftsman and what one paradigm holds over the other is simply the kinds of coding decisions that are discouraged vs encouraged.  The idea is to use designs that encourage use cases that pay productivity dividends down the road and discourage use cases that become time sinks.  In this sense Singletons are ALL BAD but making your life easier down the road shouldn't be a directive that is pathologically perused such that the productivity of the moment is drawn to a crawl.  I guess the point I'm trying to make is that a tipping point exists between writing infinitely sustainable code and getting the job done.  Here are some examples:


Singletons make sense for something like a GPU; it is a piece of hardware, there is only one of them and it has an internal state.  Of course you can write code such that the GPU appears virtualized and your application can instantiate any number of GPU objects and use them at will.  Indeed I would consider this good practice as it will force the code that relies on the GPU to be written better and should extend nicely to multi GPU platforms.  The flip side is that implementing all this properly comes at a cost in productivity at the moment and that cost needs to be considered over the probability of seeing the benefit.


Another example is collecting telemetry or profiling data.  It's nice to have something in place that tells everyone on the team: "Hey, telemetry data and performance measurements should be coalesced through these systems for the purposes of generating comprehensive reports."  A Singleton does this while a class declaration called Profiler and Telemetry does not.  Again, you can put the burden of managing and using instances of Profiler and Telemetry onto the various subsystem of your application and once again this may lead to better code but if the project never lives long enough to see that 'better code' pay productivity gains then what was the point?


I don't implement Singletons either personally or professionally (for the reasons outlined by Ravyne and SiCrane unless explicitly directed to do so) but I have worked on projects that did use them and overall I was glad they existed as they made me more productive on the whole.  In these instances the dangers of using other people's singletons in already singleton dependent systems never came to fruition and the time sink I made writing beautiful, self contained, stateless and singleton free code never paid off.  Academic excellence vs. pragmatism:  it's a tradeoff worth considering.  Mostly I'm playing devils advocate here as I find blanket statements about a design paradigm being all good or all bad misleading.  Anyway, this is likely to get flamey...it already is and people aren't even disagreeing yet. :)  I'm out.

In Topic: questions about singletons

28 August 2013 - 12:25 PM

1. the code that makes it so you can only create one singleton is just to prevent you from doing something stupid like creating two entity lists by accident, correct?


Yep along with the Global Access property SiCrane mentioned.  The third property of the Singleton paradigm is control over the relative order of construction of singleton objects, something that's not possible with object instances that are declared as globals.  As with most design paradigms Singletons are mostly used to show intent to would be modifiers of the system rather than to prevent bonehead mistakes by making them syntactically illegal. 


As a whole singletons seem to be regarded as a bad pattern due to the global access part. Global state is bad because it complicates multi-threaded code, makes testing and debugging more difficult and frequently makes code maintenance and refactoring a pain. The single instance of  a class part is largely regarded as usually pointless but not harmful in and of itself.


Mostly agree in the academic sense but in practice I would say they have their uses stemming primarily from convenience.  Sometimes you truly only want one instancing of something running around (assert tracker, GPU wrapper etc) in which case having a single point of access keeps things simple.  Avoiding the threading pit-falls can be done by proper constructing the singleton to deal with multi-threaded access and being vigilant about keeping singleton access out of code that doesn't absolutely need it.

In Topic: a map<T,T> as a default parameter...

28 August 2013 - 12:18 AM

You would need to do this:

bool createWindowImp(DemString		winName,	// window name
		     DemString		winTitle,	// window title
		     DemUInt		winWidth,	// window width.
		     DemUInt		winHeight,
		     ExtraParameters	params = ExtraParameters());

Which will push an instance of ExtraParameters (which will be empty) onto the stack and pass it on to the function.  The instance will get pushed off the stack after the function's scope terminates.  A more efficient approach would look like this:

bool createWindowImp(DemString		winName,	// window name
		     DemString		winTitle,	// window title
		     DemUInt		winWidth,	// window width.
		     DemUInt		winHeight,
		     ExtraParameters*	params = 0);

Inside createWindowImp you will need to check to see if param is non-null and proceed to dereference it and extract values if so.




I see ExtraParameters is an std::map, in that case IF you want to go with the fist option you will definitely want to tweak it a bit:

bool createWindowImp(DemString			winName,	// window name
		     DemString			winTitle,	// window title
		     DemUInt			winWidth,	// window width.
		     DemUInt			winHeight,
		     const ExtraParameters&	params = ExtraParameters());

If you don't pass by reference then each time the function is called a temporary std::map will be created for the params varaible and a deep copy will be preformed between it and whatever you happen to be passing in; that equates to a lot of memory that gets newed only to be prompty deleted.  It's good practice to toss the 'const' in there too unless you want to pass info out of createWindowImp via params (usually forwned upon).

In Topic: skeletal animation on peices of a model

27 August 2013 - 11:53 PM

Are you talking about packing the matrices in a texture rather than sending it as a uniform?


Not necessarily but as DigitalFragment pointed out there are many advantages to doing so; either way the concept is the same.  If your hardward supports texture fetches in the vertex shader and floating point texture formats it's generally a good idea (such features are common these days).

In Topic: skeletal animation on peices of a model

27 August 2013 - 08:31 PM

Now when I animate the character in the vertex shader I need to send the bone transforms which is a lot of data. I may need to make multiple draw calls for all the different pieces and I want to avoid sending all bones every time if I only need to send maybe the fingers for the characters glove.



The skeleton is just a big list of matrices or quaternion-translation pairs that are usually stored in a constant buffer.  "Sending the bone transforms" is just a matter of updating a GPU resource; this only needs to happen oncer per frame.  To use that data you simply bind it to the GPU, this isn't free but it's generally very cheap as it doesn't involve moving data from the CPU to the GPU.  After binding the resource the shaders evoked by subsequent draw calls will have access to the skeleton data.


Generally speaking you should pack your entire skeleton into a single resource and update it once per frame regardless of how many draw calls it will take to render the skinned mesh.