HNHacker News
TopNewBestAskShowJobs

ack_complete

834 karma · joined January 8, 2022

submissionscomments
ack_complete··on I can't upgrade to Windows 11, now leave me alone
Worse than that, there's no consistency in Fn+key shortcuts. Recently acquired an HP Ergonomic Keyboard as a replacement for a broken Sculpt, only to find out that it literally cannot send Ctrl+Break -- there's no key for it, no Fn+key shortcut for it and the remapping software doesn't simulate it properly.
ack_complete··on Getting bitten by Intel's poor naming schemes
This is unfortunately the same for GPUs. The graphics APIs expose capability bits or extensions indicating what features the hardware and driver supports, but the graphics vendors don't always publish documentation on what generations of their hardware support various features, so your program is expected to dynamically adapt to arbitrary combinations of features. This is no longer as bad as it used to be due to consolidation in the graphics market, but people still have to build ad-hoc crowd sourced databases of GPU caps bits.

It's also not monotonic, on both CPU and GPU sides features can go away later because either due to a hardware bug or the vendor lost interest in supporting it.

ack_complete··on Native vs. emulation: World of Warcraft game performance on Snapdragon X Elite
AVX(2)'s main advantage is 256-bit width, since many of its operations are simply concatenated 128-bit ops (weird for ops like VPALIGNR), and cross-lane operations are expensive. NEON, on the other hand, only supports 128-bit ops, so AVX operations need to be split by the emulator.

I'd expect more of a gain from enabling FMA, but that's assuming the program actually got built to use FMA -- it needs to either use it explicitly or have relaxations to allow the contraction. Oryon has 4 x 128-bit NEON pipes with 3c latency fadd and 4c latency fmul/fma, so it easily ends up latency bottlenecked unless there are plenty of independent calculations.

ack_complete··on Native vs. emulation: World of Warcraft game performance on Snapdragon X Elite
The compiler is also a factor, as MSVC's ARM64 backend is less mature than the x64 backend, while the xtajit(64) emulators in Windows were written by emulation veterans. But even then, I've typically seen a ~25% penalty between a native optimized ARM64 build and an emulated optimized x64 build. Major optimized code paths being disabled or suboptimal in the ARM64 port would definitely be more plausible, especially in licensed third-party libraries.
ack_complete··on Closures as Win32 Window Procedures
I'm not convinced this is always guaranteed for a Windows x64 program. When running on bare x64 hardware, FlushInstructionCache() does seem to be an (inefficient) noop on Windows 11 x64, but when running in emulation on Windows 11 ARM64, it's running a significantly larger amount of ARM64 native code -- it looks like it might be ensuring that stale JIT code is flushed.
ack_complete··on Closures as Win32 Window Procedures
The stdcall calling convention used APIs and API callbacks on Windows x86 doesn't use registers at all, all parameters are passed on the stack. MSVC does support thiscall/fastcall/vectorcall conventions that pass some values in registers, but the system APIs and COM interfaces all use stdcall.

Windows x64 and ARM64 do use register passing, with 4 registers for x64 (rcx/rdx/r8/r9) and 8 registers for ARM64 (x0-x7). Passing an additional parameter on the stack would be cheap compared to the workarounds that everyone has to do now.

ack_complete··on Closures as Win32 Window Procedures
There's an annoying corner case when using SetWindowLongPtr/GetWindowLongPtr() -- Windows sends WM_GETMINMAXINFO before WM_NCCREATE. This can be worked around with a thread local, but a trampoline inherently handles it. Trampolines are also useful for other Win32 user functions that don't have an easy way to store context data, such as SetWindowsHookEx(). They're also slightly faster, though GetWindowLongPtr() at least seems able to avoid a syscall.

The code as written, though, is missing a call to FlushInstructionCache() and might not work in processes that prohibit dynamic code generation. An alternative is to just pregenerate an array of trampolines in a code segment, each referencing a mutable pointer in a parallel array in the data segment. These can be generated straightforwardly with a little template magic. This adds size to the executable unlike an empty RWX segment, but doesn't run afoul of any dynamic codegen restrictions or require I-cache flushing. The number of trampolines must be predetermined, but the RWX segment has the same limitation.

ack_complete··on The stack circuitry of the Intel 8087 floating point chip, reverse-engineered
You're not wrong, the performance gain from proper FPU instruction scheduling on a Pentium was immense. But applications written prior to Quake and the Pentium gaining prominence or non-game oriented would have needed more blended code generation. Optimizing for the highest end CPU at the time at the cost of the lowest end CPU wouldn't necessarily have been a good idea, unless your lowest CPU was a Pentium. (Which it was for Quake, which was a slideshow on a 486.)

K6 did have the advantage of being OOO, which reduced the importance of instruction scheduling a lot, and having good integer performance. It also had some advantage with 3DNow! starting with K6-2, for the limited software that could use it.

ack_complete··on The stack circuitry of the Intel 8087 floating point chip, reverse-engineered
Nah. As others have said, translating infix to RPN is pretty easy to do. The nasty part was keeping values within registers on the stack, especially within loops. The 8087 couldn't do binary ops between two arbitrary locations on the stack, one had to be the top of stack. This meant that if you need to add two non-top locations, for example, you had to exchange (FXCH) one of them to the top of the stack first. This meant that optimized x87 code tended to be a mess of FXCH instructions.

Complicating this further, doing this in a loop requires that the stack state match between the start and end of the loop. This can be challenging to do with minimal FXCH instructions. I've seen compilers emit 3+ FXCH instructions in a row at the end of a loop to match the stack state, where with some hairy rearrangement it was possible to get it down to 2 or 1.

Finally, the performance characteristics of different x87 implementations varied in annoying ways. The Intel Pentium, for instance, required very heavy use of FXCH to keep the add and multiply pipelines busy. Other x87 FPUs at the time, however, were non-pipelined, some taking 4 cycles for an FADD and another 4 cycles for FXCH. This meant that rearranging x87 code for Pentium could _halve_ the speed on other CPUs.

ack_complete··on Cool-retro-term: terminal emulator which mimics look and feel of CRTs
It also happens with digital cameras for similar reasons, due to CCD scanning. But yeah, that doesn't happen looking directly at a CRT.

The bloom is also too blobby, because it's a gaussian blur. I ran into the same issue trying to implement a similar effect. The bloom shape needs to sharper to look realistic -- which also means unfortunately a non-separable blur.

ack_complete··on Bypassing the Branch Predictor
Cold branch comes to mind -- something like a interrupt handler, that is run often enough but not in high enough bursts.
ack_complete··on LLM policy?
> I can't imagine that any policy against LLM code would allow this sort of thing, but I also imagine that if I don't say "this was made by a coding agent", that no one would ever know. So, should I just stop contributing, or start lying?

If a project has a stated policy that code written with an LLM-based aid is not accepted, then it shouldn't be submitted, same as with anything else that might be prohibited. If you attempt to circumvent this by hiding it and it is revealed that you knowingly did so in violation of the policy, then it would be unsurprising for you to receive a harsh reply and/or ban, as well as a revert if the PR was committed. This would be the same as any other prohibition, such as submitting code copied from another project with an incompatible license.

You could argue that such a blanket ban is unwarranted, and you might be right. But the project maintainers have a right to set the submission rules for their project, even if it rules out high-quality LLM assisted submissions. The right way to deal with this is to ask the project maintainers if they would be willing the adjust the policy, not to try to slip such code into the project anyway.

ack_complete··on Windows 10 Deadline Boosts Mac Sales
This was a late addition to the Windows 11 supported CPU list. The rumor is that this happened after it was pointed out that Microsoft was still selling brand new Surface Studio 2 devices that had 7th gen Intel CPUs.
ack_complete··on When you opened a screen shot of a video in Paint, the video was playing in it
The video overlays in question are not drawn by blending into a framebuffer in memory. They're two separate display planes that are read in parallel by the display path, scaled, and blended together at scan-out time. There are only reads, no writes. Modern GPUs support alpha-blended display planes using the alpha channel that is otherwise often required to exist anyway as padding.

As OP noted, using hardware display planes can have efficiency advantages for cases like floating controls over a video or smoothly animating a plane over a static background, since it avoids an extra read+write for the composited image. However, it also has some quirks -- like hardware bandwidth limits on how small a display plane can be scaled.

ack_complete··on When you opened a screen shot of a video in Paint, the video was playing in it
A green stripe on the right/bottom is usually due to a different issue: interpolation errors in chroma planes when decoding YCbCr video. The chroma planes use a biased encoding where 0 (no color) is mapped to 128. A sloppy YCbCr to RGB conversion without proper clamping can interpolate against 0 at edges, which is interpreted as max negative chroma red/blue -- which combined together produces green. This can happen either due to an incorrectly padded texture or failing to handle the special final sample case for 4:2:2 chroma.

This issue can happen with overlays, but also non-overlay GPU drawing or CPU conversion routines.

ack_complete··on PlayStation 3 Architecture (2021)
Some do, some ARM-based devices have tightly coupled memory (TCM). The RP2040 in the original Raspberry Pi also has a 4K bank for each core intended for stack and per-core variables, though it is not limited to access only by that core.

The main disadvantage of such dedicated memory is inefficient usage compared to using that same amount of fast local memory to cache _all_ of main memory.

ack_complete··on Sharp Bilinear Filters: Big Clean Pixels for Pixel Art
While true in the general case, in this case the bilinear downscaling pass is being applied to a signal already previously upsampled using a known specific filter (box filter). Aliasing is therefore more limited and controlled.
ack_complete··on Prefix sum: 20 GB/s (2.6x baseline)
This is partially due to the compromises of mappingvector intrinsics into C (with C++ only being marginally better). In a more vector-oriented language, such as shader languages, this:

  s1 = vaddq_u32(s1, vextq_u32(z, s1, 2));
  s1 = vaddq_u32(s1, vdupq_laneq_u32(s0, 3));
would be more like this:

  s1.xy += s1.zw;
  s1 += s0.w;
ack_complete··on JIT: So you want to be faster than an interpreter on modern CPUs
The difference between interpreters and simple JITs has narrowed partly due to two factors: better indirect branch predictors with global history, and wider execution bandwidth to absorb the additional dispatch instructions. Intel CPUs starting with Haswell, for instance, show less branch misprediction impact due to better ability to predict jump path patterns through the interpreter. A basic jump table no longer suffers as much compared to tail-calling/dispatch or a simple splicing JIT.
ack_complete··on Jeep pushed software update that bricked all 2024 Wrangler 4xe models
There was an unreal lack of awareness when the Windows Ink team engaged Reddit on this issue -- talking about "legacy" apps when such apps included the latest release version of Photoshop.
ack_complete··on Why is Windows still tinkering with critical sections? – The Old New Thing
To add to what others have said, additional characteristics of a Win32 critical section:

- It is purely an in-process lock, and originally the main way of arbitrating access to shared memory within a process.

- It is counted and can be recursively locked.

- It defaults to simple blocking, but can also be configured to do some amount of spin-waiting before blocking.

- CritSecs are registered in a global debug list that can be accessed by debuggers. WinDbg's !locks command can display all locked critical sections in a process and which threads have locked them.

Originally in Win32, there were only two types of lock, the critical section for in-process locking, and the mutex for cross-process or named locks. Vista added the slim reader/writer lock, which is a much lighter weight, pointer-sized lock that uses the more modern wait-on-address approach to locking.

ack_complete··on Snapdragon X2 Elite ARM Laptop CPU
Following up that last part -- I recompiled my x64 codebase with /volatileMetadata-, which reduced the volatile metadata by ~20K (the remainder most likely from the statically linked CRT). The profiling results were negligible, under noise level between the builds and both about 15-30% below the native ARM64 build.

The interesting part is when the compatibility settings for the executables are modified to change the default multi-core setting from Fast to Strict Multi-Core Operation. In that mode, the build without volatile metadata runs about 20% slower than the default build. That indicates that the x64 emulator may be taking some liberties with memory ordering by default. Note that while this application is multithreaded, the worker threads do little and it is very highly single thread bottlenecked.

ack_complete··on Athlon 64: How AMD turned the tables on Intel
No need for suspicion, the documentation confirms this was a factor:

https://learn.microsoft.com/en-us/windows/win32/winprog64/ru...

ack_complete··on Snapdragon X2 Elite ARM Laptop CPU
> Efficient TSO emulation is crucial (both on Windows and elsewhere)

Yes, but this is not in contention...? No one is disputing that TSO semantics in the emulated x86 code need to be preserved and that it needs to be done fast, we're talking about the tradeoffs of also having TSO support on the host platform.

> The blog claims hardware TSO is non-ideal on Windows only (because Microsoft adapted the ecosystem to facilitate software-based TSO emulation). (Even then, it's unclear if the author quantified the concrete impact)

> Hardware TSO is still of tremendous value on systems that don't have ecosystem support

That isn't what the author said. From the article:

> Another common misconception about Rosetta is that it is fast because the hardware enforces Intel memory ordering, something called Total Store Ordering. I will make the argument that TSO is the last thing you want, since I know from experience the emulator has to access its own private memory and none of those memory accesses needs to be ordered. In my opinion, TSO is ar red herring that isn't really improving performance, but it sounds nice on paper.

That is a direct statement on Rosetta/macOS and does not mention Prism/Windows. How correct that assessment may be is another matter, but it is not talking about Windows only.

> Those applications would still benefit from ARM64EC (i.e. native system libraries), but the actual application code would be affected quite badly by the TSO impact then, depending on how good their fallback heuristics are.

I will have to check this, I don't think it's that bad. JITted programs run much, much better on my Snapdragon X device than the older Snapdragon 835, but there are a lot of variables there (CPU much faster/wider, Windows 11 Prism vs. Windows 10 emulator, x86 vs x64 emulation). I have a program with native x64/ARM64 builds that runs at -25% speed in emulated x64 vs native ARM64, I'm curious myself to see how it runs with volatile metadata disabled.

ack_complete··on Snapdragon X2 Elite ARM Laptop CPU
How is it a misinterpretation? To re-quote that last sentence:

> In my opinion, TSO is a red herring that isn't really improving performance, but it sounds nice on paper.

That's the author directly saying that TSO isn't the major emulation performance gain that people think it is. You're correct that there are countering effects between TSO's benefits to the emulated code vs. the negative effects on the emulator and other non-emulated code in the same process that are fine running non-TSO, but to users, this distinction doesn't matter. All that matters is the performance of emulated program as a whole.

As for the volatile metadata, you're correct that MSVC inserts additional data to aid the emulation. What's not so great is that:

- It was basically an almost undocumented, silent addition to MSVC.

- In some cases, it will slow down the generated x64 code slightly by adding NOPs where necessary to disambiguate the volatile access metadata.

- It only affects code statically compiled with a recent version of MSVC (late VS2019 or later). It doesn't help executables compiled with non-MSVC compilers like Clang, nor any JIT code, nor is there any documentation indicating how to support either of these cases.

ack_complete··on Snapdragon X2 Elite ARM Laptop CPU
Ironically, the app I've had the most trouble with is Visual Studio 2022. Since it has a native ARM64 build and installation of the x64 version is blocked, there are a bunch of IDE extensions that are unavailable.
ack_complete··on Snapdragon X2 Elite ARM Laptop CPU
People who have worked on the Windows x64 emulator claim that TSO isn't as much of a deal as claimed, other factors like enhanced hardware flag conversion support and function call optimizations play a significant role too:

http://www.emulators.com/docs/abc_exit_xta.htm

ack_complete··on DXGI debugging: Microsoft put me on a list
No, the Agility SDK only includes updated D3D12 core and debug layer components.

https://microsoft.github.io/DirectX-Specs/d3d/D3D12Redistrib...

ack_complete··on DXGI debugging: Microsoft put me on a list
The features in question are platform agnostic. They could temporarily disable the detouring for native ARM64 apps since the mechanism is broken on that architecture, but it's not ideal since the Snapdragon X platform is one of the main platforms for the Auto Super Resolution feature. Upgrading sequential/blit mode swap chains to flip model theoretically should be legacy, but as OP shows, it's not really as new graphics code is still being shipped without flip model support.

Note that the detouring problem is only an issue for native ARM64 programs. x64 programs running in emulation on Windows ARM64 work fine.

ack_complete··on DXGI debugging: Microsoft put me on a list
The Agility SDK is unrelated to what is being discussed here. It is a delivery mechanism for the Direct3D 12 runtime instead of DXGI, it is opt-in from the application side, and is done through a more stable loader stage in the core OS instead of hot-patching.

It does, however, give insight into the situation that the DirectX team is in. The in-box version of D3D12Core in the latest version of Windows 11 is SDK version 612. This can be compared against the released Agility SDK versions:

https://devblogs.microsoft.com/directx/gettingstarted-dx12ag...

SDK version 612 is just before the 613 Agility SDK release on 3/11/2024. This means that the version of DirectX 12 they are able to ship in the main OS is a year and a half behind the latest released version.

← PreviousPage 4 of 11Next →