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)
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 ec = Float4(1.055f) * power(c, Float4(1.0f / 2.4f)) - Float4(0.055f);
......@@ -1365,7 +1365,7 @@ Float4 Blitter::LinearToSRGB(Float4 &c)
return s;
}
Float4 Blitter::sRGBtoLinear(Float4 &c)
Float4 Blitter::sRGBtoLinear(const Float4 &c)
{
Float4 lc = c * Float4(1.0f / 12.92f);
Float4 ec = power((c + Float4(0.055f)) * Float4(1.0f / 1.055f), Float4(2.4f));
......
......@@ -161,8 +161,8 @@ private:
void write(Int4 &color, Pointer<Byte> element, const State &state);
static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false);
static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes);
static Float4 LinearToSRGB(Float4 &color);
static Float4 sRGBtoLinear(Float4 &color);
static Float4 LinearToSRGB(const Float4 &color);
static Float4 sRGBtoLinear(const Float4 &color);
using BlitFunction = FunctionT<void(const BlitData *)>;
using BlitRoutineType = BlitFunction::RoutineType;
......
......@@ -270,7 +270,7 @@ Constants::Constants()
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++)
......
......@@ -72,7 +72,7 @@ struct Constants
word4 mask5551Q[16]; // 4 bit writemask -> A1R5G5B5 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 sRGBtoLinear12_16[4096];
......
......@@ -2711,9 +2711,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
{
Pointer<Byte> LUT = constants + OFFSET(Constants, sRGBtoLinear12_16);
c.x = As<UShort4>(c.x) >> 4;
c.y = As<UShort4>(c.y) >> 4;
c.z = As<UShort4>(c.z) >> 4;
c.x = AddSat(As<UShort4>(c.x), UShort4(0x0007)) >> 4;
c.y = AddSat(As<UShort4>(c.y), UShort4(0x0007)) >> 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, 1))), 1);
......@@ -2733,9 +2733,9 @@ void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
void PixelRoutine::linearToSRGB16_12_16(Vector4s &c)
{
c.x = As<UShort4>(c.x) >> 4;
c.y = As<UShort4>(c.y) >> 4;
c.z = As<UShort4>(c.z) >> 4;
c.x = AddSat(As<UShort4>(c.x), UShort4(0x0007)) >> 4;
c.y = AddSat(As<UShort4>(c.y), UShort4(0x0007)) >> 4;
c.z = AddSat(As<UShort4>(c.z), UShort4(0x0007)) >> 4;
linearToSRGB12_16(c);
}
......
......@@ -1746,7 +1746,10 @@ Vector4s SamplerCore::sampleTexel(UInt index[4], Pointer<Byte> buffer)
{
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)
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;
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, 1))), 1);
......
......@@ -96,7 +96,7 @@ private:
void convertSigned15(Float4 &cf, Short4 &ci);
void convertUnsigned16(Float4 &cf, Short4 &ci);
void sRGBtoLinear16_8_16(Short4 &c);
void sRGBtoLinearFF00(Short4 &c);
bool hasFloatTexture() const;
bool hasUnnormalizedIntegerTexture() const;
......
......@@ -162,13 +162,13 @@ Float4 logarithm2(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)
}
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)
}
......
......@@ -330,11 +330,11 @@ inline float sRGBtoLinear(float c)
{
if(c <= 0.04045f)
{
return c * 0.07739938f; // 1.0f / 12.92f;
return c / 12.92f;
}
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)
}
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