Commit 2883de94 by Nicolas Capens Committed by Nicolas Capens

Fix sRGB conversion precision issues

When sampling an sRGB texture format, we have a vector of 16-bit elements where 0xFF00 represents 1.0, but we were using a lookup table which produced results in a 0xFFFF base. Also on linear to sRGB conversion, precision was lost due to truncating to 12-bit. Adding a rounding factor before truncating preserves precision. Bug: b/149574741 Change-Id: I19218c958867c4b5e97dc3b62b4ea83f37161134 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/41268 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: Nicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 0bbf7ba9
...@@ -1354,7 +1354,7 @@ Int Blitter::ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes) ...@@ -1354,7 +1354,7 @@ Int Blitter::ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes)
return y * pitchB + x * bytes; return y * pitchB + x * bytes;
} }
Float4 Blitter::LinearToSRGB(Float4 &c) Float4 Blitter::LinearToSRGB(const Float4 &c)
{ {
Float4 lc = Min(c, Float4(0.0031308f)) * Float4(12.92f); Float4 lc = Min(c, Float4(0.0031308f)) * Float4(12.92f);
Float4 ec = Float4(1.055f) * power(c, Float4(1.0f / 2.4f)) - Float4(0.055f); Float4 ec = Float4(1.055f) * power(c, Float4(1.0f / 2.4f)) - Float4(0.055f);
...@@ -1365,7 +1365,7 @@ Float4 Blitter::LinearToSRGB(Float4 &c) ...@@ -1365,7 +1365,7 @@ Float4 Blitter::LinearToSRGB(Float4 &c)
return s; return s;
} }
Float4 Blitter::sRGBtoLinear(Float4 &c) Float4 Blitter::sRGBtoLinear(const Float4 &c)
{ {
Float4 lc = c * Float4(1.0f / 12.92f); Float4 lc = c * Float4(1.0f / 12.92f);
Float4 ec = power((c + Float4(0.055f)) * Float4(1.0f / 1.055f), Float4(2.4f)); Float4 ec = power((c + Float4(0.055f)) * Float4(1.0f / 1.055f), Float4(2.4f));
......
...@@ -161,8 +161,8 @@ private: ...@@ -161,8 +161,8 @@ private:
void write(Int4 &color, Pointer<Byte> element, const State &state); void write(Int4 &color, Pointer<Byte> element, const State &state);
static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false); static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false);
static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes); static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes);
static Float4 LinearToSRGB(Float4 &color); static Float4 LinearToSRGB(const Float4 &color);
static Float4 sRGBtoLinear(Float4 &color); static Float4 sRGBtoLinear(const Float4 &color);
using BlitFunction = FunctionT<void(const BlitData *)>; using BlitFunction = FunctionT<void(const BlitData *)>;
using BlitRoutineType = BlitFunction::RoutineType; using BlitRoutineType = BlitFunction::RoutineType;
......
...@@ -270,7 +270,7 @@ Constants::Constants() ...@@ -270,7 +270,7 @@ Constants::Constants()
for(int i = 0; i < 256; i++) for(int i = 0; i < 256; i++)
{ {
sRGBtoLinear8_16[i] = (unsigned short)(sRGBtoLinear((float)i / 0xFF) * 0xFFFF + 0.5f); sRGBtoLinearFF_FF00[i] = (unsigned short)(sRGBtoLinear((float)i / 0xFF) * 0xFF00 + 0.5f);
} }
for(int i = 0; i < 0x1000; i++) for(int i = 0; i < 0x1000; i++)
......
...@@ -72,7 +72,7 @@ struct Constants ...@@ -72,7 +72,7 @@ struct Constants
word4 mask5551Q[16]; // 4 bit writemask -> A1R5G5B5 bit patterns, replicated 4x word4 mask5551Q[16]; // 4 bit writemask -> A1R5G5B5 bit patterns, replicated 4x
dword4 mask11X[8]; // 3 bit writemask -> B10G11R11 bit patterns, replicated 4x dword4 mask11X[8]; // 3 bit writemask -> B10G11R11 bit patterns, replicated 4x
unsigned short sRGBtoLinear8_16[256]; unsigned short sRGBtoLinearFF_FF00[256];
unsigned short linearToSRGB12_16[4096]; unsigned short linearToSRGB12_16[4096];
unsigned short sRGBtoLinear12_16[4096]; unsigned short sRGBtoLinear12_16[4096];
......
...@@ -2711,9 +2711,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c) ...@@ -2711,9 +2711,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
{ {
Pointer<Byte> LUT = constants + OFFSET(Constants, sRGBtoLinear12_16); Pointer<Byte> LUT = constants + OFFSET(Constants, sRGBtoLinear12_16);
c.x = As<UShort4>(c.x) >> 4; c.x = AddSat(As<UShort4>(c.x), UShort4(0x0007)) >> 4;
c.y = As<UShort4>(c.y) >> 4; c.y = AddSat(As<UShort4>(c.y), UShort4(0x0007)) >> 4;
c.z = As<UShort4>(c.z) >> 4; c.z = AddSat(As<UShort4>(c.z), UShort4(0x0007)) >> 4;
c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 0))), 0); c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 0))), 0);
c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 1))), 1); c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 1))), 1);
...@@ -2733,9 +2733,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c) ...@@ -2733,9 +2733,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
void PixelRoutine::linearToSRGB16_12_16(Vector4s &c) void PixelRoutine::linearToSRGB16_12_16(Vector4s &c)
{ {
c.x = As<UShort4>(c.x) >> 4; c.x = AddSat(As<UShort4>(c.x), UShort4(0x0007)) >> 4;
c.y = As<UShort4>(c.y) >> 4; c.y = AddSat(As<UShort4>(c.y), UShort4(0x0007)) >> 4;
c.z = As<UShort4>(c.z) >> 4; c.z = AddSat(As<UShort4>(c.z), UShort4(0x0007)) >> 4;
linearToSRGB12_16(c); linearToSRGB12_16(c);
} }
......
...@@ -1746,7 +1746,10 @@ Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer) ...@@ -1746,7 +1746,10 @@ Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer)
{ {
if(isRGBComponent(i)) if(isRGBComponent(i))
{ {
sRGBtoLinear16_8_16(c[i]); // The current table-based sRGB conversion requires 0xFF00 to represent 1.0.
ASSERT(state.textureFormat.has8bitTextureComponents());
sRGBtoLinearFF00(c[i]);
} }
} }
} }
...@@ -2492,11 +2495,11 @@ void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs) ...@@ -2492,11 +2495,11 @@ void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs)
cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF); cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF);
} }
void SamplerCore::sRGBtoLinear16_8_16(Short4 &c) void SamplerCore::sRGBtoLinearFF00(Short4 &c)
{ {
c = As<UShort4>(c) >> 8; c = As<UShort4>(c) >> 8;
Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants, sRGBtoLinear8_16)); Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants, sRGBtoLinearFF_FF00));
c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0); c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0);
c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1); c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1);
......
...@@ -96,7 +96,7 @@ private: ...@@ -96,7 +96,7 @@ private:
void convertSigned15(Float4 &cf, Short4 &ci); void convertSigned15(Float4 &cf, Short4 &ci);
void convertUnsigned16(Float4 &cf, Short4 &ci); void convertUnsigned16(Float4 &cf, Short4 &ci);
void sRGBtoLinear16_8_16(Short4 &c); void sRGBtoLinearFF00(Short4 &c);
bool hasFloatTexture() const; bool hasFloatTexture() const;
bool hasUnnormalizedIntegerTexture() const; bool hasUnnormalizedIntegerTexture() const;
......
...@@ -162,13 +162,13 @@ Float4 logarithm2(RValue<Float4> x, bool pp) ...@@ -162,13 +162,13 @@ Float4 logarithm2(RValue<Float4> x, bool pp)
Float4 exponential(RValue<Float4> x, bool pp) Float4 exponential(RValue<Float4> x, bool pp)
{ {
// FIXME: Propagate the constant // TODO: Propagate the constant
return exponential2(Float4(1.44269504f) * x, pp); // 1/ln(2) return exponential2(Float4(1.44269504f) * x, pp); // 1/ln(2)
} }
Float4 logarithm(RValue<Float4> x, bool pp) Float4 logarithm(RValue<Float4> x, bool pp)
{ {
// FIXME: Propagate the constant // TODO: Propagate the constant
return Float4(6.93147181e-1f) * logarithm2(x, pp); // ln(2) return Float4(6.93147181e-1f) * logarithm2(x, pp); // ln(2)
} }
......
...@@ -330,11 +330,11 @@ inline float sRGBtoLinear(float c) ...@@ -330,11 +330,11 @@ inline float sRGBtoLinear(float c)
{ {
if(c <= 0.04045f) if(c <= 0.04045f)
{ {
return c * 0.07739938f; // 1.0f / 12.92f; return c / 12.92f;
} }
else else
{ {
return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f return powf((c + 0.055f) / 1.055f, 2.4f);
} }
} }
...@@ -346,7 +346,7 @@ inline float linearToSRGB(float c) ...@@ -346,7 +346,7 @@ inline float linearToSRGB(float c)
} }
else else
{ {
return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment