View Issue Details

IDProjectCategoryView StatusLast Update
0002474Infinitode 2[All Projects] Infinitode 2public2024-07-22 01:59
ReporterGoles Assigned Totherainycat  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionnot fixable 
PlatformDesktopOSWindowsOS VersionAny
Product Version1.9.0 (Season 3) 
Target VersionFixed in Version 
Summary0002474: [b204] Quad broken display on certain rotation & size
Description

Bug found not by me, Elfox asked to report this.

If you draw quad by certain rotation and size it will be broken, example shown in the script below.

Steps To Reproduce

Run this script:

local time = 0
S.events:getListeners(C.SystemsPostSetup):add(C.Listener(function()
    S._render:addLayer(C.Layer(701, false, C.LayerRenderer(function(batch, delta, _, _)
        --                             coordX,             coordY              origin, size,     scaleX,               scaleY,               rotate
        C.Quad:getNoQuad():draw(batch, math.sin(time)*128, math.cos(time)*128, 64, 64, 128, 128, 1+math.sin(time)*0.5, 1+math.cos(time)*0.5, time*30%360)
        -- guaranteed bug
        -- C.Quad:getNoQuad():draw(batch, math.sin(time)*128, math.cos(time)*128, 64, 64, 128, 128, 1+math.sin(1)*0.5, 1+math.cos(1)*0.5, time*30%360)
        time = time + delta
    end)))
end))
Additional Information

Bug found not by me, Elfox asked to report this.

Video: https://www.youtube.com/watch?v=I_Muw0saZuw

TagsNo tags attached.

Activities

therainycat

therainycat

2024-07-22 01:56

administrator   ~0002556

The problem is related to LuaVM.
Lua only has a single underlying data type for numbers (double) - that's the first piece of the problem.
There's no method overload in Lua, while it works perfectly fine in Java (a class can have multiple methods with the same name) - that's the second piece.
Each time an overloaded method is called, Lua has to guess which of the overloaded methods the script wants to call.

Now the whole picture:
There are 3 "draw" methods in Quad, and they all differ in the amount of parameters. Lua guesses the method incorrectly depending on the value of parameters being passed - since every number is stored as a "double", it has to quess the data type of the number too, so for example "121.0" will be percieved by the Lua VM as "it looks like a 'byte' to me" while "357.28" will make it think "it is definitely a 'float' or a 'double'", which results in a different "guessing score" and sometimes it mispredicts the method.

I'm not going to fix this, because this would only make the method guessing algorithm more demanding in terms of performance. Speaking of which, the performance is already awful when the VM has to predict such methods all the time.
We have to avoid method overloads, and there's already a way of doing so:

local fQuadDraw = C.Quad:_findMethod("draw", C.Batch --[[@as Class]], java.float, java.float, java.float, java.float, java.float, java.float, java.float, java.float, java.float)

This will specify the exact method we want to call and it will be stored in a variable (serializable). It can be used like this:

fQuadDraw(q, batch, coordX, coordY, oX, oY, sX, sY, sclX, sclY, angle) -- We have to pass the Quad as the first argument so it becomes 'self'

This should result in a much better performance and it should always call the method we need.

Overloads also work for constructors, but they are easier to work with (if you have Lua definitions generated). Quad has multiple constructors, and we avoid the quess work by specifying the exact constructor we need (for example, "new_ATR" for (AtlasTextureRegion) or "new_Q_b" for (Quad, boolean)).
I have not generated such suffixes for methods - only for constructors, because some difficulties arise when we take interfaces into the equation (you can call something by its interface methods, which will result in a different method names etc.)

This issue will be addressed later, because I have no time for that now. I see 2 possible solutions:

  • Try to add suffixes like in constructors and see what can be done with the interfaces
  • Add some kind of a notification to the developer console each time an overloaded method is being called (one notification per script/lineNumber). It should help to eliminate overloads completely, reducing the chance of such bugs and improving the performance.
therainycat

therainycat

2024-07-22 01:59

administrator   ~0002557

Take a look at matrix-background-optimized.lua which uses method references for performance reasons.

Issue History

Date Modified Username Field Change
2024-07-21 20:41 Goles New Issue
2024-07-22 01:56 therainycat Note Added: 0002556
2024-07-22 01:57 therainycat Assigned To => therainycat
2024-07-22 01:57 therainycat Status new => closed
2024-07-22 01:57 therainycat Resolution open => not fixable
2024-07-22 01:59 therainycat Note Added: 0002557