The fragment shader's default precision is lowp, which NVIDIA's Vulkan driver
runs as fp16, and the product (2c+1)(2f+1) reaches 511*511, past fp16's range.
Split/Second's bloom saturated whole channels; its two bloom dumps go from MSE
2354/9305 to 80/153, the same as OpenGL.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With MSAA, a pixel that a primitive only partly covers otherwise
extrapolates them to the pixel center, outside the primitive, and samples
textures outside its UV range. Without MSAA nothing changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The GE's bilinear filter truncates (4-bit weights, twice), and rounding the
GPU's finer filtered value made each texel about a level brighter. God Eater
Burst's bloom is faint and feeds back into itself pass after pass, so that
roughly doubled it: its dumps go from 15-31k px off the PSP to 0.4-3k, the
#17033 ones from 79k/107k to 25k/47k. Split/Second and Call of Duty: Road to
Victory improve too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The GE's blend terms are floor((2c+1)(2f+1)/1024), which truncates, while the
hardware multiplies by f/255 and rounds, so every pass of a fixed color blend
chain came out up to a level brighter. God Eater Burst's bloom is many such
passes and ended up far too bright.
For additive FIXA/FIXB blends that aren't just 0 and 0xFFFFFF, the shader
now computes the src term exactly and lowers it by 0.5 - (2B+1)/1024, and the
blend constant is the GE's dst factor (2B+1)/512, so the hardware's rounding
of the sum lands on the GE's floor (except where the src term would go below
zero). Blend constants are passed as floats to make that possible.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fragment Z is the PSP's Z / 65536, and flat draws land exactly on an
integer Z. floor(z * 65535) put that Z - Z/65536 just above the boundary, so
float error (which differs with W) could drop it by one: Patlabor redraws a
HUD icon at the same depth with GEQUAL, and the second draw failed on
Vulkan. Floor Z + 0.01 instead, and store Z / 65535, as clears and the depth
clamp path do. Also fixes Heroes Phantasia #6485.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing writes depth then, so the shader write is wasted. On Apple's OpenGL
it also broke Tales of Phantasia (PixelDepthRounding): once the shader writes
gl_FragDepth, a discarded fragment still writes stencil, so a color-tested
stencil pass marked the whole area and the background tiles drawn with
stencil EQUAL 0 vanished.
New FS ID bit, so both shader caches get a version bump.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove two unused helper functions that were left behind after refactoring:
1. unpackUVec3: Left over from commit 4329aaa31c ("GPU: Apply color
test mask as a uint") which refactored color test to use
roundAndScaleTo8x4 with direct uint comparison instead of unpacking
to uvec3 components.
2. packFloatsTo8x4: Left over from commit aec22491fe ("Don't expand
alphaColorRef to 128 bytes") which changed u_alphacolorref from vec4
to uint, making the float-to-uint packing function unnecessary.
Both functions were defined but never called, wasting shader compilation
time and binary size for shaders that enable color testing.
Signed-off-by: Chris Healy <cphealy@gmail.com>
Seems in lowp precision (as seen on some Android devices) this got
rounded up to 256 when multiplied by 1.0, causing the u8 to overflow, giving
us the wrong value instead of nicely rounding down to 255 with the floor
function.
Fixes#19235
Note that we also offset the lookup slightly to miss the wrap-around
points. The existing 31 scale factor instead of 32, together with that
half-texel, are enough to avoid that problem.
Fixes#18300
Haven't been using these for a while.
I've come to the conclusion here that I think it's better to try to
deal with the issues using safe workarounds like copies, instead of
relying on features with somewhat iffy driver support that are not
universal across APIs anyway.