Enemies "slide" when hit

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.

Post a reply

Smilies
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :geek: :ugeek: :!: :?: :idea: :arrow: :| :mrgreen: :3: :wub: >:( :blergh:
View more smilies

BBCode is OFF
Smilies are ON

Topic review
   

Expand view Topic review: Enemies "slide" when hit

Re: Enemies "slide" when hit

by dpJudas » Fri Dec 07, 2018 2:48 pm

Okay, good news. Turns out I just don't know the x64 calling convention well enough. xmm1 to xmm3 are the registers used for this call, because the first argument is a pointer and that makes it skip the first xmm parameter register as well. Since xmm3 is pitch, that means its passing "xmm1 = speed, xmm2 = angle, xmm3 = pitch".

In short: this bug is now fixed and there isn't another bug. :)

Re: Enemies "slide" when hit

by dpJudas » Fri Dec 07, 2018 12:44 pm

I also try stay clear of template libraries. Aside from making the library itself visually crap to read, it also makes it terrible for the consumer. I'd say templates should only be used for basic utility functions or containers.

In the asmjit case its a bit strange though, because as far I can tell those functions didn't even need to be templated. It is almost as if he's trying to do compile time checks (like the gzdoom drawers) to speed things up, but in code where you shouldn't need to be so aggressive about that. On top of that everything is stored as compactly as possible in memory. While such code may be faster I don't think it is worth it except for the uttermost critical loops in a program.

Btw. I implemented the XOR and the bug itself seems to be gone. But there's still something wrong - while looking at the dumpjit output I noticed it does this in Actor.AimBulletMissile:

Code: Select all

; line 17: 19000002 LDP
test rbx, rbx                           ; test regA0, regA0
je L8                                   ; je L8
movsd xmm0, qword [rbx+344]             ; movsd regF0, qword [regA0+344] // speed

; line 17: 19010003 LDP
test rbx, rbx                           ; test regA0, regA0
je L9                                   ; je L9
movsd xmm1, qword [rbx+120]             ; movsd regF1, qword [regA0+120] // angle

; line 17: 19020004 LDP
test rbx, rbx                           ; test regA0, regA0
je L10                                  ; je L10
movsd xmm3, qword [rbx+112]             ; movsd regF2, qword [regA0+112] // pitch

; line 17: 50020400 CALL_K
xorps xmm0, xmm1                        ; [Swap] regF0, regF1
xorps xmm1, xmm0
xorps xmm0, xmm1
movapd xmm2, xmm0                       ; [Move] regF1
mov rcx, rbx                            ; [Duplicate] regA0
call 140701174325264                    ; Actor.Vel3DFromAngle [Native] // xmm0 = angle, xmm1 = speed, xmm2 = angle ?? clearly not right!
Trying to debug now why on earth it doesn't even seem try assign regF2 to any of the argument registers.

Re: Enemies "slide" when hit

by Graf Zahl » Fri Dec 07, 2018 12:21 pm

dpJudas wrote: The code dealing with the registers in asmjit uses some somewhat nasty templating to share code between different register types
And this is why I normally steer clear of those 'cool' templated libraries. The only other one in GZDoom is RapidJSON, and not surprisingly, it also contains a bug I had to work around - and to my knowledge they still haven't fixed it, even two years after I reported it. (The library completely loses it if the user tries to write invalid data. Not only the incorrect values written get trashed, but the entire output becomes malformed.)

Template code tends to become totally unreadable rather quickly. The STL is also a good example for that.

Re: Enemies "slide" when hit

by dpJudas » Fri Dec 07, 2018 11:03 am

Graf Zahl wrote:When bugs like this one surface, all I can say is :puke:. They are the worst of all - problems with third party code...
Indeed. This is why I personally try to keep 3rd party dependencies at a minimum. Too bad in this case it wasn't an option.
phantombeta wrote:Ninja edit: What if we manually did swaps like this instead of letting asmjit do it? That could work...
Unfortunately we use virtual registers and the asmjit register allocator is what assigns them to real registers. We simply don't know that some code prior to the call decided to place those in xmm0 and xmm1.

The code dealing with the registers in asmjit uses some somewhat nasty templating to share code between different register types (general purpose, SSE, etc.). I've tried to understand its logic before and it didn't go too well. However the good news is that maybe I can implement the XOR swap for XMM registers. The asmjit code already has support for swapping GP registers like that, which means I just need to convince those template functions to follow that code path instead.

Re: Enemies "slide" when hit

by phantombeta » Fri Dec 07, 2018 9:12 am

I remember I stumbled upon this same bug when fixing MODF_RK. I can't remember what we did to fix it, though... :\
It should be doing a XOR swap in this case if it really needs to swap the registers, but for some reason it isn't.

Ninja edit: What if we manually did swaps like this instead of letting asmjit do it? That could work...

Re: Enemies "slide" when hit

by Graf Zahl » Fri Dec 07, 2018 4:48 am

When bugs like this one surface, all I can say is :puke:. They are the worst of all - problems with third party code...

Re: Enemies "slide" when hit

by dpJudas » Fri Dec 07, 2018 3:41 am

Eek, looks like it could be another register allocation bug in asmjit.

Essentially xmm1 holds regF2 and xmm2 holds regF1. The code wants to swap them - first two saves is the register allocator saving them to stack. Then it copies regF1 to xmm1 - so far so good. The bug is that it thinks it can copy the other way as well, but that of course doesn't work.

Re: Enemies "slide" when hit

by _mental_ » Fri Dec 07, 2018 3:33 am

Apparently, it's an issue with code generation. "Sliding" bug is caused by this Actor.Thrust() call. Here is a corresponding JIT dump:

Code: Select all

; line 73: 50070300 CALL_K
movsd oword [rsp+120], xmm1             ; [Save] regF1
movsd oword [rsp+112], xmm2             ; [Save] regF2
mov rcx, rbx                            ; [Duplicate] regA0
movapd xmm1, xmm2                       ; [Duplicate] regF2                       // ???
movapd xmm2, xmm1                       ; [Duplicate] regF1                       // ???
call 140698867386448                    ; Actor.Thrust [Native]
No surprise that angle and speed arguments for this native function are the same.

Re: Enemies "slide" when hit

by lemming » Thu Dec 06, 2018 7:44 pm

Rachael's video clip seems consistent with the behavior I noticed. I'll also see if I can bisect it down to the commit responsible, since it has to have been exposed by something within the ~24-48 hours before the commit SHA1 I listed.

edit:

It seems to have been introduced somewhere between 101ebe17311ff517af1a62c0092462f6b4ce95e2, where the bug does not occur, and de5ab0b4b69032316f24a4e47d58310ea994a551, where it does. I cannot, unfortunately, narrow it down any better than that right now, because every commit in between those two either fails to build, or fails to run with the error "gzdoom.pk3:zscript/actor.txt, line 670: The function 'Actor.LineAttack' has not been exported from the executable".

Hope that helps. I don't know your codebase well enough to mess around with the intervening commits and get them to work.

Re: Enemies "slide" when hit

by Graf Zahl » Thu Dec 06, 2018 10:32 am

Rachael wrote: When "vm_jit" is set to 0, the angles are always correct.
Ok, that's why I did not notice during most later tests. That should narrow it down considerably. My guess is that there's another direct native function where the signature does not match the definition.

Re: Enemies "slide" when hit

by Rachael » Thu Dec 06, 2018 9:40 am

I tried this to reproduce it: set "sv_damagefactormobj 100" to make it much more obvious what's happening with kickbacks. Then set godmode and infinite ammo and go slaughtering monsters - pay close attention to what happens to them on the map. They all go flying northeast.

This video is NOT meant to be debugged directly - it just shows the effect in action. For what it's worth, it reveals another bug: Somehow, WolfySS was able to see me on spawn.

When "vm_jit" is set to 0, the angles are always correct.

Re: Enemies "slide" when hit

by _mental_ » Thu Dec 06, 2018 9:18 am

Tried Rachael's steps to reproduce with Debug Win64 and got bunch of beloved Invalid sound position (-111.044632, 1014.617737, -inf) for actor of class ArchvileFire at the beginning of Doom II MAP01.
Z coordinate is always bad while X and Y are correct.

Re: Enemies "slide" when hit

by Graf Zahl » Thu Dec 06, 2018 9:04 am

Angles are exported properly. This is more likely some of the bad coding in the old kickback code now showing its ugly face. I thought I had it fixed before committing, but apparently not.

Re: Enemies "slide" when hit

by Rachael » Thu Dec 06, 2018 9:02 am

I actually just noticed this, too. I set "sv_damagefactormobj 0" on an archvile and shot it with a high damage weapon and it slid toward me. Are angles being exported correctly between C++ and ZScript? Are there any degree or radian conversions that should be happening and aren't?

Re: Enemies "slide" when hit

by phantombeta » Thu Dec 06, 2018 8:31 am

The kickback and explosions are reversed. dpJudas noticed the same issue, too.
This can be easily noticed in a mod such as Guncaster, where the starting weapon has massive kickback - it thrusts sideways instead of backwards.

Top