Recent submissions

Comment · 13 days ago
Google and Apple aren't, but my banks and government services are trying their best.
Comment · 1 month ago
It's not up to .NET AOT, it's up to Xbox and Sony.

.NET can generate the code, but your game won't pass certification if it runs machine code generated by something other than the officially provided C/C++ tool chain.

Comment · 1 month ago
Australian sticker price includes 10% GST so the correct way to compare is to take the tax free US price, convert that to AUD and add 10%. Applying that process yields $1633 AUD so the sticker price we get is actually better than the US price.
Comment · 1 month ago
> Git and P4 are not meant to be directly competitive here.

True, but for the problems that Git LFS solves P4 is usually the other option. P4 handles large binaries very well, caveat being the rest of P4. In some projects the caveats are worth it. I work in video games and our in house engine has an unfiltered checkout size over a 1TB.

I've found LFS very brittle when bouncing between branches and moving around in history. There's been many times I've had my local check out blow up through rebases or mistakes I've made. Many times the recovery is to nuke and re-clone. With a 1TB repo that's not a good option.

It's been a while since I've used it, and I'm sure some of my problems were skill issues, but I never found it worth the pain at any scale I've tried to use it.

Comment · 1 month ago
From my experience Git LFS is extremely brittle and will break your local check out if you so much as breath on it wrong. Perforce is an expensive solution to the problems of LFS, and I've yet to find a workflow as powerful as my git workflows for managing code.

I don't really see what the article is talking about as the future, but if P4 or Git LFS is the best we can do as a species then we're doomed. All VCS options suck for one reason or another, I hope we don't stop trying to make something better. If only to save me from perforce.

Comment · 1 month ago
Absolutely, I agree. I suspect that explicit branch for the hot path is doing a lot too.

Separating the hot path into a prefix before calling into a separate cold function should still generate better code. Your prefix only needs to allocate registers and stack space for just that single path. You would only pay the spilling costs in the old code off the hot path rather than every instruction. And I would expect the branch prediction accuracy of that prefix check to be higher than having the hot and cold paths all dispatching through the same tree of branches.

However it's speculation until you measure so I could be wrong.

Good article in any case, I enjoyed reading along.

Comment · 1 month ago
I'm not convinced the performance benefits are entirely the result of the more compact object representation. It definitely would help, but looking at the code snippets the author provides for the add instruction there's an important structural change that would be making a huge difference.

The old, enum based value type used a single big match statement to dispatch between all possible type combinations. Their assembler output looks like the match gets compiled to something like a big stack of nested if statements.

The new code uses an explicit fast path check with a dispatch into a tagged 'cold' path when the common case isn't hit. The generated code is a single upfront branch for the fast path that exits immediately, with a dispatch into the slow path in a separate function.

This would be contributing significantly to the performance improvements. The old path requires taking several branches even on the hot path. The new code has a single, highly predictable branch that skips all the messy dispatch for the other types.

This could have been implemented for the enum based value type, and I would expect to see a jump in performance there too even without the new compact value type. There will be a much higher branch predictor hit rate with the explicit fast path.

Comment · 1 month ago
Since when do Samsung ship driver updates? I'm being a bit hyperbolic but from my experience Samsung don't ship them very often either. To Google's credit, the Pixels get them quite frequently. Samsung is still better than most other Android vendors, who are somehow even worse.

It's depressing how bad the drivers are. They have 0 market pressure to improve the quality, unlike PC where the whiniest group on the internet (gamers on reddit) will crucify you for driver problems. I've spent too much time investigating and implementing workarounds. Though it does pay my bills...

Comment · 1 month ago
The Pixel 10 and 11 GPUs are offensively bad. Not only are the Power VR GPUs slow, and less capable feature wise than Mali and Adreno (Xclipse is still around too!), but the tile Google put in the Pixel 11 is actually an _older_ design than what they put in the Pixel 10. They just clocked it higher to make up the performance difference.

And then Google has the gall to charge basically flagship prices for their under powered junk.

Personally I don't buy flagship phones because I don't use their full compute capabilities anyway, but a Pixel 11 would cost 2x what I paid for my Pixel 8. For 0 GPU performance improvement.

Comment · 2 months ago
They cost 3x as much
Comment · 2 months ago
A VGPR is not the same thing as a vector register like in SSE4 or AVX. Each addressed register contains a single 32-bit value. A VGPR differs from an SGPR in that each thread in a thread group can have a different value in that register. An SGPR will have a uniform value shared with all threads in a group.

An add instruction on an AMD GPU adds two scalar values. If they're in a VGPR then each thread will add two values unique to that thread. A SIMD ISA as is common on a CPU is different because an add instruction explicitly adds a vector of values. xmm1 stores 128-bits of data. VGPR[1] stores 32-bits of data vectored over 32-64 threads in a thread group.

Without special instructions a thread can't access the VGPR values stored in other threads.

Comment · 2 months ago
Yes, of course writing naive code assuming each lane in a thread group is a real thread is going to cause problems, but I didn't feel like I needed to go into that level of detail replying to someone just learning about GPU internals. I tried to cover this loosely by mentioning how you need to know how it works for maximum performance.

If you want to get more pedantic you also need to look at your target hardware and their specific micro-architectural quirks and features to get the best performance. AMD specifically benefits a lot from exploiting the scalar unit over the vector unit, you save loads of register file space if you can keep data in SGPRs over VGPRs. There's lots of traps you can fall into where you can load data from buffers into SGPRs but they get promoted to VGPRs because the scalar unit lacks an opcode for like one math operation you did to the value somewhere.

While each lane isn't truly a thread because it doesn't have its own PC the programming model definitely tries to make it seem that way. The threads can terminate at different points too. And again, the ISA isn't a vector ISA. Your register values are scalar.

Comment · 2 months ago
Comment · 2 months ago
Most games haven't rendered directly into the "screen buffer" for 15-20 years.

Vast majority of titles use deferred rendering, and lighting is done off screen too. Usually the only thing done to the "screen buffer" is a final post-process pass or a copy.

Comment · 2 months ago
You can't actually ship a game on the porting toolkit without breaching the license. It's intended by Apple to aid porting to use Mac's native APIs one component at a time, but the license forbids redistribution or commercial use. The community can hack away with it however they want because Apple isn't going to chase every individual person, but a business can't ship it unless they want a nice call with Apple's legal team.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton