SFML community forums

Help => General => Topic started by: Neil on December 26, 2014, 06:13:07 pm

Title: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 06:13:07 pm
http://www.sfml-dev.org/documentation/2.0/classsf_1_1Drawable.php

In this function

virtual void    draw (RenderTarget &target, RenderStates states) const

Why is RenderStates passed by value and not (const) reference? On my compiler it is 76 bytes, which is quite big.

I know sometimes draw function may want to alter it. In that case, it can make its own copy from the const reference if required.

Wouldn't this be faster?

Thank you.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Jesper Juhl on December 26, 2014, 06:39:12 pm
I doubt you'd be able to measure a difference. And anyway, you'd then slow down the "wants to make a copy" case.
But I really doubt that it actually matters either way, performance wise.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Hiura on December 26, 2014, 06:41:55 pm
Measure it, with compiler optimisation turned on, of course. The copy is probably elided when not needed so you'll probably see no difference. But that's just a guess... The key is to always measure.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: FRex on December 26, 2014, 06:56:22 pm
It will be copied once per drawing, since the calls usually go:
1. RenderTarget::draw //constructed default or passed here as const&
2. Drawable::draw //copy here
3. RenderTarget::draw //the vertex overload, also takes by const&

Also almost all sf::Drawable classes that come with SFML modify it, I think just VertexArray doesn't. It's also 100% trivial to copy.


In theory and for the sake of C++ trivia: yes, it might be faster or it might be slower, but either way it doesn't matter.
It's not performance issue and will probably never be.
The actual OpenGL draw calls (which are some pretty old/legacy functions of GL) time inside RenderTarget::draw is dominating so heavily that it will completely dwarf this in any profiler.

It just doesn't matter. It's impossible to write a real life program which would be impacted by this change in any way.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 07:22:35 pm
I know sometimes draw function may want to alter it. In that case, it can make its own copy from the const reference if required.

This is stupid for a lot of reasons. As it is stated, a lot of drawables modify the states which means you are making senseless copies which could be avoided if the states were passed by value (Sound familiar?).
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 08:02:03 pm
Ok thanks. I understand now it probably doesn't matter and I shouldn't worry about it.

However I don't understand Gambit's post. Why would passing by const reference result in more copies than passing by value?
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 08:15:12 pm
If RenderState is passed by const ref, you cannot alter the state so you have to copy it if you need to modify it.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 08:32:20 pm
Yes. How is that worse than pass by value, which results in a copy even if it's not modified?
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 08:38:19 pm
Pass by value is a copy even if it is modified. There is no point in passing by reference. Each draw call has the option to change the state if it wants without affecting other draw calls. Most draw calls (Text, Sprite, etc) change the transformation of the state which you cannot do with a const ref. Passing by non-const ref means that changing the state will affect other draw calls as well. As stated earlier, its trivial to pass by value (If 76 bytes is a lot I suggest getting more RAM). From a performance stand point, the overhead is negligible.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 08:53:47 pm
Passing by const reference and only making a copy if it needs to be modified results in less copies.
I wouldn't pass by non-const reference. That would cause too many issues about the re-usability of the original state object.
Copying 76 bytes on the stack is nothing to do with the amount of ram. It depends mainly on CPU.

I inherit my classes from sf::Drawable and implement the draw function. Objects may contain subojects that need drawing. Not all objects are interested in changing the render state. This is the motivation of my asking. Is this not a good design?
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Laurent on December 26, 2014, 08:58:33 pm
Quote
Is this not a good design?
It is. Passing the render states by value is also a good design. The thing is, nobody cares because the difference will never be noticeable. There's really nothing else to say about it ;)
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 09:09:13 pm
Could you explain why passing render states by value is good design?
I'm just curious because it's different to the way I was taught to program* and would like to learn more.
Thanks

(Pass basics by value, pass big things by reference, I know it's only a rule of thumb)
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 09:28:36 pm
Read a C++ book/pdf or something, I'm sure it outlines the ups and downs for using both. This is not a C++ tutorial forum.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 09:33:17 pm
Hey I've been coding C++ for years so cut the attitude please. If you're going to be flippant, you at least need to be right, which you haven't been in your previous posts.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 09:53:00 pm
Theres no need to be rude. This is not a C++ help and support forum. If you have been coding C++ for years, I'm sure you would know this by now or at least have the ability to source the information yourself.

Passing by value, reference or pointer is not just about size, but about utility as well. The one you chose depends on what is going to happen to the variable that is being passed.

Quote from: http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value
Say I want to share a web page with you.

If I tell you the URL, I'm passing by reference. You can use that URL to see the same web page I can see. If that page is changed, we both see the changes. If you delete the URL, all you're doing is destroying your reference to that page - you're not deleting the actual page itself.

If I print out the page and give you the printout, I'm passing by value. Your page is a disconnected copy of the original. You won't see any subsequent changes, and any changes that you make (e.g. scribbling on your printout) will not show up on the original page. If you destroy the printout, you have actually destroyed your copy of the object - but the original web page remains intact.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 10:00:42 pm
What is the difference between

void func(State s)
{
        // s not changed
        func2(s);
}

void func(State s)
{
        // s needs to be changed
        s.a = 5;
        func2(s);
}

and

void func(const State& s)
{
        // s not changed
        func2(s);
}

void func(const State& s)
{
        // s needs to be changed
        State s2 = s;
        s2.a = 5;
        func2(s2);
}

Except that in the former, the state is always copied, and in the latter, the state is only copied if it needs to be modified?

My question is why the latter is not considered the better solution.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 26, 2014, 10:05:14 pm
More code for no justifyable reason? As I keep saying, it is trivial to copy RenderStates, it doesnt need to be passed by reference, I dont know how else to say it.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 10:11:24 pm
You didn't appear to understand what I was saying so that is why I put the code. But you are very rude so I'm not going to talk to you any more.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Jesper Juhl on December 26, 2014, 10:22:21 pm
I'm not near a compiler for a couple of days so I can't check, but modern optimizing compilers are pretty smart, and I'd guess that if you checked the disassembly from an optimized build you'd see that the compiler probably elides/removes the copy completely in rhe case where it is not modified (as already mentioned).
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Laurent on December 26, 2014, 10:54:02 pm
Sorry guys but... This whole discussion looks really stupid, you should stop it :P

Neil, in case it was not clear enough, yes you're right, from a pure technical point of view your code is more "optimized" (*). But nobody cares because in the end it will make no difference. So I pass by value to save one extra line of code because 80% of SFML classes need to do that copy. That's just it...

(*) compilers are smart, I'm pretty sure it doesn't even make any difference at all
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Neil on December 26, 2014, 10:55:16 pm
I can believe that the cost of passing render states by value is trivial and so there's no point worrying about it.

I am reluctant to believe the compiler can optimize away the copy in a pass by value in this case. Draw is a virtual function and it may not be known until run-time whether the states parameter is modified or not by the resolved function.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: StormWingDelta on December 27, 2014, 12:53:37 am
I can believe that the cost of passing render states by value is trivial and so there's no point worrying about it.

I am reluctant to believe the compiler can optimize away the copy in a pass by value in this case. Draw is a virtual function and it may not be known until run-time whether the states parameter is modified or not by the resolved function.

It comes down to the IDE you are using and the other parts like the compiler.  If I remember right both Code::Blocks and Visual Studio do a lot of the optimization that we'd have to have done manually years back.  It most likely can optimize things you wouldn't think of.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: eXpl0it3r on December 27, 2014, 01:17:43 am
StormWingDelta: What you said makes no sense and what you meant to say has already been said multiple times. An IDE (Integrated Development Environment) does absolutely not optimize anything, it doesn't even produce any kind of binary code. The compiler creates the binary code and does the optimization! By now you should really be able to tell the difference between an IDE and a compiler.

I am reluctant to believe the compiler can optimize away the copy in a pass by value in this case. Draw is a virtual function and it may not be known until run-time whether the states parameter is modified or not by the resolved function.
Programming is never about any kind of believe. Study, try, test, profile. The easiest way is really to go write reliable test cases. The harder way is to go study what the standard allows and what the compilers actually do (of course that only works for open source compilers). ;)

As for the discussion in general: Stop trying to optimize stuff which hasn't been proven to be a bottleneck in anyone's code.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Nexus on December 30, 2014, 02:55:34 am
I understand Nei's argument because the general rule is: use const reference for bigger objects, value for built-ins and small classes. The reason why SFML deviates here has been mentioned: the states are mostly modified, so code is simpler.

And Gambit, don't be rude just because you're on the same side as SFML team members. When you make a (bad) argument and are asked for clarification, then explain your point.
Title: Re: Why RenderStates is passed by value in draw function?
Post by: Gambit on December 30, 2014, 07:05:16 am
I wasnt trying to be rude, I was just trying to get a point across.