Simplifies emission of the blocks themselves (including inserting blocks
into the function's block list in the correct order), as well as phi after
the branching.
Also fixes 64bpp storing with blending in the fragment shader interlock
render backend implementation (had a typo that caused the high 32 bits to
overwrite the low ones).
C++ relational operators are supposed to raise FE_INVALID if an argument is
NaN, use std::isless/greater[equal] instead where they were easy to locate
(though there are other places possibly, mostly min/max and clamp usage was
checked).
Also fixes a copy-paste error making the CPU shader interpreter execute
MINs as MAXs instead.
Hopefully prevents some potential #1971-like situations.
WAIT_REG_MEM's implementation also allowed the compiler to load the value
only once, which caused an infinite loop with the other changes in the
commit (even in debug builds), so it's now accessed as volatile. Possibly
it would be even better to replace it with some (acquire/release?) atomic
load/store some day at least for the registers actually seen as
participating in those waits.
Also fixes the endianness being handled only on the first wait iteration in
WAIT_REG_MEM.
Accessing the same memory as different types (other than char) using
reinterpret_cast or a union is undefined behavior that has already caused
issues like #1971.
Also adds a XE_RESTRICT_VAR definition for declaring non-aliasing pointers
in performance-critical areas in the future.
Functional changes:
- Enable only actually used features, as drivers may take more optimal
paths when certain features are disabled.
- Support VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE.
- Fix the separateStencilMaskRef check doing the opposite.
- Support shaderRoundingModeRTEFloat32.
- Fix vkGetDeviceBufferMemoryRequirements pointer not passed to the Vulkan
Memory Allocator.
Stylistic changes:
- Move all device extensions, properties and features to one structure,
especially simplifying portability subset feature checks, and also making
it easier to request new extension functionality in the future.
- Remove extension suffixes from usage of promoted extensions.
AVX512 has native unsigned integer comparisons instructions, removing
the need to XOR the most-significant-bit with a constant in memory to
use the signed comparison instructions. These instructions only write to
a k-mask register though and need an additional call to `vpmovm2*` to
turn the mask-register into a vector-mask register.
As of Icelake:
`vpcmpu*` is all L3/T1
`vpmovm2d` is L1/T0.33
`vpmovm2{b,w}` is L3/T0.33
As of Zen4:
`vpcmpu*` is all L3/T0.50
`vpmovm2*` is all L1/T0.25
Other half of #2125. I don't know of any title that utilizes this instruction, but I went ahead and implemented it for completeness.
Verified the implementation with `instr__gen_vsubcuw` from #1348. Can be grabbed with:
```
git checkout origin/gen_tests -- src\xenia\cpu\ppc\testing\*vsubcuw.s
```
I don't know of any title that utilizes this instruction, but I went
ahead and implemented it for completeness.
Verified the implementation with `instr__gen_vaddcuw` from #1348. Can be
grabbed with:
```
git checkout origin/gen_tests -- src\xenia\cpu\ppc\testing\*vaddcuw.s
```
There's no limit on the number of memory exports in a shader on the real
Xenos, and exports can be done anywhere, including in loops. Now, instead
of deferring the exports to the end of the shader, and assuming that export
allocs are executed only once, Xenia flushes exports when it reaches an
alloc (allocs terminate memory exports on Xenos, as well as individual ALU
instructions with `serialize`, but not handling this case for simplicity,
it's only truly mandatory to flush memory exports before starting a new
one), the end of the shader, or a pixel with outstanding exports is killed.
To know which eM# registers need to be flushed to the memory, traversing
the successors of each exec potentially writing any eM#, and specifying
that certain eM# registers might have potentially been written before each
reached control flow instruction, until a flush point or the end of the
shader is reached.
Also, some games export to sub-32bpp formats. These are now supported via
atomic AND clearing the bits of the dword to replace followed by an atomic
OR inserting the new byte/short.
Uses `vpternlogd` to collapse the bitwise select operation into one
instruction. Though it needs a `vmovdqa` instruction since `vpternlogd`
reads and writes to the first argument.