function WindowPrivate:Render()
local final = table.create(#self.pixels, 0) :: { number }
local n = math.round(#final / 2)
for i, color in ipairs(self.pixels) do
if i % n == 0 then
task.wait()
end
local i = (i - 1) * 4
final[i + 1] = bit32.rshift(color, 24) / 255
final[i + 2] = bit32.band(bit32.rshift(color, 16), 0xFF) / 255
final[i + 3] = bit32.band(bit32.rshift(color, 8), 0xFF) / 255
final[i + 4] = bit32.band(color, 0xFF) / 255
end
(self.renderer :: EditableImage):WritePixels(Vector2.zero, self.size, final)
end
@saaawdust whatās the purpose of having to allocate a new framebuffer and having to do bit32 per pixel, per frame? why cant you not pass self.pixels to WritePixels?
For OSGL to use less memory, that had to be done (more said later).
is this the reason? maybe this is why buffers should be allowed in WritePixels, iād imagine there would be less overhead there than to allocate, iterate and bit32
If it supported buffers it would indeed be way better, but thatās for Roblox. We donāt use buffers either way. And yes, thatās why editing pixels takes more time.
The 2 code snippets are completely irrelevant. That shows how desperate you are to prove OSGL is bad. Why are you answering questions? Itās for the developers of OSGL, not you.
This argument has been settled in discord, please do not continue it!
For anyone wondering, yes, as msix29 mentioned, OSGL takes longer to draw a pixel, (around 30 - 40% slower) than CD. OSGL however does this for lower-memory-usage, and slightly higher overall FPS. CD, on the other hand, can draw much faster than OSGL, yet you will get a lower FPS, and higher memory usage. OSGL has less memory usage since it uses a width*height length array instead of a width*height*4 due to the way colors are stored (Read more about this here) although the final array is computed in the end.
Memory does matter as much as the CPU. If you want to draw faster, use CD. If you want better overall FPS, then use OSGL. CD is good if you want just to render 1 specific thing on the screen. OSGL is good if you also want other things on the screen at the same time. Use whichever one suits your project better, which in this case, since you want the speed, is CD.
If you want to improve something, or believe something could be faster, remember the project is Open-Source on Github here. Just because you believe one thing is more important than the other, doesnāt mean everyone has to agree with you, lol.
Apologies for not replying to your message earlier, I actually never saw this one. We canāt pass self.pixels as we use a custom memory-efficient format other than the one EditableImages use. We store each color in oneu32 (each channel is a u8), while EditableImages expect 4 different numbers for each channel, so we have to unpack the u8s from our u32 to get them.
oh my bad I forgot I enabled fflags for it. just to give you an idea, itās way faster than using tables and itās a lot faster to clear too since you can use buffer.fill to clear it instead of manually iterating.
This is an incredibly interesting library! Iāve only casually perused the code, though Iād like to ask ā have you tried benchmarking the code to use Vector3ās instead of numbers? Unlike Vector2ās, Vector3ās are native types, and as such have faster operations. You seem to be performing a lot of operations with coordinate numbers & number pairs, so Iād recommend switching em out to Vector3ās to see if thereās any performance gains to be made
Well, for the mean time, I would leave the code as it is, since buffers are behind a FFlag theyāre probably unstable. Iāll still be comparing performances (away from OSGL) though.
The suggestion is quite nice, we may consider implementing it.
In the meantime, itās likely that the performance will actually be worse. This is because metatables are most likely used, which could potentially slow down the process compared to plain numbers. Generally speaking, thereās no operation we perform that the Vector3 would be superior at (itās primarily multiplication and division, lol), as thereās a third number that will also have to undergo that operation. Furthermore, it could be quite confusing to use it in our API.
Does the use of a native type necessarily imply that it would not utilize metatables? I donāt think so. As previously stated, it is āmost likely usedā, not 100% used. I have also mentioned other factors that would influence this.
I am confused as to the point you are trying to make. For 1-dimensional scalar operations it does not make much sense to use vectors, however given that this module works with multiple dimensions, vector operations are more optimal and efficient over scalar operations. The DevForum post I linked, which was written by a Roblox engineer, states this very same point.
My point is that thereās an extra number that we donāt use. We use 2D values, a Vector3 has 3, meaning thereās one extra number that all operations happen to, and we donāt even use it! Iām unsure of where exactly do you want to use them, but depending on that, the 1 operation on the 1 extra number can turn into hundreds.
Vector operations are a single instruction, while two separate number operations need to be 2 separate instructions. The overhead from running an instruction is bigger than the actual math operation so vectors will actually be faster than numbers here, from what I tested vector operations are around 30% faster than 2 number operations.
You can for example use a Vector3 as a replacement to what would have been a Vector2 and make your functions accept them as an argument, instead of asking 2 number arguments for each coordinate.
Also vector operations being native means their math operations donāt go through metatables but have a fast-path internally, not too sure about their methods though.
Hmm. Pretty interesting. They are not a single instruction, though. Yes you may only be calling one function instead of 2 math operations, but the function would be doing atleast 3 math operations; more than 2 plain numbers. As to the overhead of the instructionsā¦ Iām no expert on that so I wouldnāt be commenting. I have no idea how your testing code showed it 30% faster, but I would love to see it. And Iāll try it myself.
Pretty confusing, isnāt it?? The whole library is 2D.
No, no. I didnāt mean metatables for in their operations, but rather the overhead of actually creating the metatables (in .new). I doubt Iāll be using any of the methods, anyways.
Testing for: two numbers
Took a total of 0.0865918950876221ms for 1000000 iterations.
With an average of 8.65918950876221e-08 ms/iteration.
Testing for: Vector3
Took a total of 0.33612719230586663ms for 1000000 iterations.
With an average of 3.361271923058666e-07 ms/iteration.
Testing for: two numbers
Took a total of 10.434128615015652ms for 100000000 iterations.
With an average of 1.0434128615015652e-07 ms/iteration.
Testing for: Vector3
Took a total of 70.19527274835855ms for 100000000 iterations.
With an average of 7.019527274835855e-07 ms/iteration.
I couldnāt find the beta, but looking at the date (2021), I think itās been out of beta.
These math operations take sub nanoseconds, itās executing the instruction that tends to take a little longer. From what I tested, a vector math operation takes 3.1 nanoseconds and two number math operations take a little above 4 nanoseconds.
Vector creation doesnāt set any metatables by itself, thatās what makes it a native object. Even strings have metatables but creating them doesnāt āsetā the metatable again, they already have the metatable on them.