Page MenuHomeWildfire Games

Refactor and cleanup of CGameView
ClosedPublic

Authored by vladislavbelov on Jun 10 2018, 3:51 PM.

Details

Reviewers
asterix
Group Reviewers
Restricted Owners Package(Owns No Changed Paths)
Commits
rP22214: Refactor and cleanup of CGameView.
Summary

Removed unused functions, split public and private methods, moved internal helpers to private, added constness for getters, removed code duplications.

Also it's another help step for the isometric view.

Test Plan
  1. Apply the patch and run the game
  2. Check that camera works as before (save games, jump points)

Diff Detail

Repository
rP 0 A.D. Public Repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

vladislavbelov created this revision.Jun 10 2018, 3:51 PM
vladislavbelov edited the summary of this revision. (Show Details)
Vulcan added a subscriber: Vulcan.Jun 10 2018, 4:02 PM

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/differential/641/display/redirect

elexis added a subscriber: elexis.Jun 10 2018, 4:21 PM
elexis added inline comments.
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

It should not be possible to use a getter as a setter

450 ↗(On Diff #6746)

A getter should not be used as a setter

vladislavbelov added inline comments.Jun 10 2018, 6:56 PM
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

True, but the access to private member is worse. Also it's common practise for our code. So it'd be good to improve it. But it's not possible here yet without much useless code, until we have callbacks for configs.

elexis added inline comments.Dec 27 2018, 1:17 PM
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

Private member access bad because it's the responsibility of the class that owns the member to set the member, therefore it should be CGameViewImpl loading it's own data, rather than CGameView loading data and pusing it into CGameViewImpl and the calls should be moved, and the getters can be const if they are needed at all? I didn't check if the CGameViewImpl / CGameView separation is useful to begin with.

source/graphics/GameView.h
60 ↗(On Diff #6746)

This moved hunk would be better off in a separate patch that doesn't change the logic, then one can read the diff that changes something independent from the diff that doesn't change logic. This move looks legit at first sight.

62 ↗(On Diff #6746)

good

source/ps/SavedGame.cpp
104 ↗(On Diff #6746)

This would be be cleaner to use the Vector2D <-> JSValue conversion from GuiScriptConversions.cpp.
(Needs equivalent change for loading then)

wraitii added inline comments.
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

I honestly haven't ready anything on where this gets called but returning a reference to a float should basically never happen anywhere in code. A pointer I might accept because at least it's obvious that it's a pointer when used elsewhere but a reference is just too dangerous.

vladislavbelov marked an inline comment as done.Dec 28 2018, 10:48 AM
vladislavbelov added inline comments.
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

True, the only reason why I added this - many useless code to add. It's used in the following lines (6 times):

CFG_GET_VAL("view.pos.smoothness", m->PosX.GetSmoothness());
...

So if we'd use getters/setters, we've to add an additional code for each line like:

bool smoothness;
...
smoothness = false;
CFG_GET_VAL("view.pos.smoothness", smoothness);
m->PosX.SetSmoothness(smoothness);

Or use the a macro.

A pointer I might accept because at least it's obvious that it's a pointer when used elsewhere but a reference is just too dangerous.

I agree with pointer.

Probably it'd be good to process this patch after D1573.

wraitii added inline comments.Dec 28 2018, 11:18 AM
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

Some sort of CFG_GET_VAL_AND_SET macro seems like the obvious better option here to me - but agreed.

vladislavbelov marked an inline comment as done.Dec 28 2018, 11:19 AM
vladislavbelov added inline comments.
source/graphics/GameView.cpp
142 ↗(On Diff #6746)

Or CFG_GET_VAL_OR_DEFAULT :)

Stan added a subscriber: Stan.Feb 25 2019, 10:24 AM

Some comments.

source/graphics/GameView.cpp
1 ↗(On Diff #6746)

2019

source/graphics/GameView.h
1 ↗(On Diff #6746)

2019

97 ↗(On Diff #6746)

If you are going that road -> Doxygen style

/**
 * Unloads all graphics resources loaded by RegisterInit.
 */
asterix requested changes to this revision.Feb 25 2019, 1:44 PM
asterix added a subscriber: asterix.

Please look at comments from Stan, me and others.

source/graphics/scripting/JSInterface_GameView.cpp
1 ↗(On Diff #6746)

2019

This revision now requires changes to proceed.Feb 25 2019, 1:44 PM
vladislavbelov marked 2 inline comments as done.

@wraitii @elexis Removed m_Smoothness getter until we have something finished with config.

Successful build - Chance fights ever on the side of the prudent.

Link to build: https://jenkins.wildfiregames.com/job/differential/1136/display/redirect

@wraitii @elexis Removed m_Smoothness getter until we have something finished with config.

From a superficial look, nothing that would make me raise a concern. (hindsight-me is usually smarter though.)

source/graphics/GameView.cpp
85 ↗(On Diff #7620)

arguments should be const ref unless they are intended to be changed or unless we need a copy, right?
There have been debates whether a reference to a number is faster than copying the number, but it seems good to have it consistent and more logical to me to avoid allocation of a new variable if we can avoid it.

903 ↗(On Diff #7620)

Perhaps the implementation can store the Vector3D directly, so that we can return a const ref here instead of creating a vector? (I didn't check)

source/graphics/GameView.h
60 ↗(On Diff #7620)

I guess this was only sorted by public / private

62 ↗(On Diff #7620)

The GetCameraX,GetCameraZ -> GetCameraRotation change is good

source/ps/SavedGame.cpp
101 ↗(On Diff #7620)

This should pass the Vector3D directly, should not be much to rework

vladislavbelov added inline comments.Mar 26 2019, 2:02 AM
source/graphics/GameView.cpp
85 ↗(On Diff #7620)

Basic types like float, int as so on (not double or long long on 32bit platforms) may but don't have to be passed as const ref, because they fit into usual CPU register. There is no allocation. Because all these variables will be created on stack.

Example:

class Test
{
    int m_Value = 0;
public:
    __attribute__((noinline)) // disable inlining
    void foo1(int value)
    {
        m_Value = value;
    }

    __attribute__((noinline)) // disable inlining
    void foo2(const int& value)
    {
        m_Value = value;
    }

    int GetValue() const { return m_Value; }
};

Test test;
int g_Sum = 0;

void foo(int n)
{
    if (n > 0)
        test.foo1(n);
    else if (n < 0)
        test.foo2(n);
    else
        g_Sum += test.GetValue();
}

Clang with -O0 assembler (rdi = this):

Test::foo1(int):
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     dword ptr [rbp - 12], esi
        mov     rdi, qword ptr [rbp - 8]
        mov     esi, dword ptr [rbp - 12]
        mov     dword ptr [rdi], esi
        pop     rbp
        ret
Test::foo2(int const&):
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     qword ptr [rbp - 16], rsi
        mov     rsi, qword ptr [rbp - 8]
        mov     rdi, qword ptr [rbp - 16]
        mov     eax, dword ptr [rdi]
        mov     dword ptr [rsi], eax
        pop     rbp
        ret

Clang with -O2 assembler:

Test::foo1(int):
        mov     dword ptr [rdi], esi
        ret
Test::foo2(int const&):
        mov     eax, dword ptr [rsi]
        mov     dword ptr [rdi], eax
        ret

        mov     dword ptr [rsp + 4], edi
; foo1 call:
        mov     esi, edi
        mov     edi, offset test
        pop     rax
        jmp     Test::foo1(int)
; foo2 call:
        lea     rsi, [rsp + 4]
        mov     edi, offset test
        call    Test::foo2(int const&)
        pop     rax
        ret

As you can see the const int& contains one more memory reading. Also compiler still optimised calls and used registers directly despite the disabled inlining.

In most cases these operations are really near, but const int& can be a little slower, like by 1-2%, also there're cache misses.

903 ↗(On Diff #7620)

But then we need to check and update it, when we changed the source.

source/ps/SavedGame.cpp
101 ↗(On Diff #7620)

I think it's irrelevant to the patch goal. As I mentioned below I suggest to create another ticket/task, as it's pretty simple but requires more changes.

104 ↗(On Diff #6746)

It'd good to do so, I suggest to make it as a simple ticket/task for that for beginning contributors.

elexis added a comment.EditedMar 26 2019, 1:01 PM

If you want to commit this patch to continue working on greater features that depend on this, and if you have done your best to ensure the correctness, I would suggest to take that decision to commit into your hands.

Edit: You can add "Comments By:" if you can't post "Reviewed By:"

source/graphics/GameView.cpp
85 ↗(On Diff #7620)

Thank you, I have never seen a that factual analysis on this!

I wonder if we could make this a coding convention to gain consistent code, to avoid repetition of these debates and to inform people of the reasons behind the omitted reference and for which fundamental types references should be used.

source/ps/SavedGame.cpp
101 ↗(On Diff #7620)

EDIT: See comment below, I assumed we have the Vector3D conversion too, but we only have the Vector2D conversion. If we had them, then I would argue:

Relation to the implementation:
If one adds a new line to the codebase, one should examine that the line is correct.
By proposing to write a ticket, you acknowledge that the lines are not the way we want them to become. So:
Choice 1: Replace 3 lines with 3 lines that you know to be wrong, create a ticket to fix that
Choice 2: Replace 3 lines with 1 line that you know to be right, and 1 modified line in session.js, not create a ticket

So it's not like we have the choice between investing more time to fix something additional, but it's saving time while fixing things.

It's arguably related to the goal of the patch, if the goal of the patch includes to use one CVector3D getter instead of three numeric getters above.

Arguably the argument could be extended to have SetCameraData use the vector. Then it would indeed cost a 2 more lines changed, but probably still less time than modifying the line once, then writing a ticket and modifying the same line again.

Anyway, you are free to chose, I'm confident you don't break things and it's easier to fix 10 lines of code than to argue in 30 lines.


But since we don't have the Vector3D conversion, the argument is dead.
I remember trying to write a macro once, so that we don't have to copy&paste it for 2D/3D, but I discontinued working on that, wasn't so easy.

104 ↗(On Diff #6746)

That comment was wrong, we already have that conversion in ScriptConversions.cpp, it's used for JS <-> C++ entity positions for example.
We only don't have the Vector3D one I think

vladislavbelov added inline comments.Mar 26 2019, 2:28 PM
source/graphics/GameView.cpp
85 ↗(On Diff #7620)

Yeah, notes in CC would be useful.

source/ps/SavedGame.cpp
101 ↗(On Diff #7620)

Yeah, my point for ticket was about adding the Vector3D conversion, not the just lines replacing.

In D1571#73526, @elexis wrote:

If you want to commit this patch to continue working on greater features that depend on this, and if you have done your best to ensure the correctness, I would suggest to take that decision to commit into your hands.

Edit: You can add "Comments By:" if you can't post "Reviewed By:"

Can I really do that? To commit without accept if it's not a blocker.

In D1571#73526, @elexis wrote:

If you want to commit this patch to continue working on greater features that depend on this, and if you have done your best to ensure the correctness, I would suggest to take that decision to commit into your hands.

Edit: You can add "Comments By:" if you can't post "Reviewed By:"

Can I really do that? To commit without accept if it's not a blocker.

If you ask if WFGs policy allows for unreviewed commits, then I wonder why you ask, after you saw me committing hundreds of unreviewed patches and always arguing for that freedom, other people committing unreviewed patches this release, and last but not least the lengthy forum discussions to reinsure this freedom, last one at https://wildfiregames.com/forum/index.php?/topic/25169-post-a23-commit-frenzy/. One of my arguments is that granting a developer access to commit patches of people who can't be trusted (external contributors) implies trusting the developer to decide over the quality of a contribution singlehandedly. Another argument is that there is a big difference in quality between reviews and peer reviews. If the author knows the code in question much better than anyone else, the reviews won't be very effective nor efficient. On the other hand reviews cost time for the reviewer - if the reviewer wants to do a good job, it costs similarly much time as compared to writing the patch.
So it depends on the specific patch, on the active members and their knowledge of the affected code whether and how much a review benefits, and it depends on good taste and luck to see which patches would be better proposed first and which ones are simple and solid enough to go in sooner than later.
The other problem is that the delay that occurs when no reviews are performed. Often one spends 10% of the time writing the code, 15% of the time arguing on it and 75% on the time waiting for nothing. But if one can already see that the result is the same as if one worked alone, and if one knows the quality will be good and sufficient, then the only difference between the two results is that in the one case, one could have closed the file after the implementation was finished, and in the other case you have to wait for possibly months to gain nothing.

If you ask if you can commit this specific commit without review, I can't speak on the impact of a patch that I didn't verify for myself. But I trust you to be able to judge this patch, and we gave you a double edged sword to butter the bread, so care.

In D1571#73534, @elexis wrote:

If you ask if WFGs policy allows for unreviewed commits, then I wonder why you ask, after you saw me committing hundreds of unreviewed patches and always arguing for that freedom, other people committing unreviewed patches this release, and last but not least the lengthy forum discussions to reinsure this freedom, last one at https://wildfiregames.com/forum/index.php?/topic/25169-post-a23-commit-frenzy/. One of my arguments is that granting a developer access to commit patches of people who can't be trusted (external contributors) implies trusting the developer to decide over the quality of a contribution singlehandedly. Another argument is that there is a big difference in quality between reviews and peer reviews. If the author knows the code in question much better than anyone else, the reviews won't be very effective nor efficient. On the other hand reviews cost time for the reviewer - if the reviewer wants to do a good job, it costs similarly much time as compared to writing the patch.
So it depends on the specific patch, on the active members and their knowledge of the affected code whether and how much a review benefits, and it depends on good taste and luck to see which patches would be better proposed first and which ones are simple and solid enough to go in sooner than later.

Yeah, I understand your point. My point is that everyone mistakes, and waiting for more review sometimes decreases a mistake chance. But sometimes it takes too much time.

But I trust you to be able to judge this patch, and we gave you a double edged sword to butter the bread, so care.

I appreciate your trust.

Stan added a comment.Apr 8 2019, 9:50 PM

Here are some comments.

source/graphics/GameView.cpp
66 ↗(On Diff #7620)

Doxygen

171 ↗(On Diff #7620)

Should be 0.f no ? Same for everything below.

333 ↗(On Diff #7620)

Macro / Function ?

388 ↗(On Diff #7620)

why no & ?

411 ↗(On Diff #7620)

Should we really return int ?

465 ↗(On Diff #7620)

Magic number ?

467 ↗(On Diff #7620)

Magic number ?

468 ↗(On Diff #7620)

Magic number ?

907 ↗(On Diff #7620)

Could be a doxygen todo or a ticket

source/graphics/GameView.h
74 ↗(On Diff #7620)

Should be doxygen.

100 ↗(On Diff #7620)

Same here

109 ↗(On Diff #7620)

Shouldn't that be at the top of the file ?

97 ↗(On Diff #6746)

Still accurate :D

vladislavbelov added inline comments.Apr 8 2019, 10:15 PM
source/graphics/GameView.cpp
388 ↗(On Diff #7620)

Because it's a reference, not a pointer.

411 ↗(On Diff #7620)

I think we shouldn't, but it's not bad here yet.

465 ↗(On Diff #7620)

Yeah, unfortunately we have magic numbers for RegMemFun. We need a task to refactor it, it also occurs in other files.

907 ↗(On Diff #7620)

It's not todo I suppose, because we didn't want to use it AFAIK.

wraitii added a comment.EditedApr 13 2019, 3:23 PM

Agreed with elexis that you may commit this if you're confident enough.

source/graphics/GameView.cpp
85 ↗(On Diff #7620)

I thought this was already a rule we had TBH, not passing trivial types by reference is fairly classic C++ advice.

This revision was not accepted when it landed; it landed in state Needs Review.Apr 23 2019, 12:12 AM
This revision was automatically updated to reflect the committed changes.