Add `formatType` arg to computeSkipBytes.

Fix texture upload format tests:
- Format tests should definitely run on ES3 also.
- Also set filters to NEAREST since some formats aren't filterable.
- Fix RGB9_E5 test reference encoding and add a test for it.
- True int/uint textures require i/usamplers.

Bug: angleproject:2576
Change-Id: Ia5bac34cdee6554a88db339de443689a71a0cf70
Reviewed-on: https://chromium-review.googlesource.com/1068142
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index e479276..81b910a 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -1139,17 +1139,18 @@
     return bytes.ValueOrDie();
 }
 
-ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
-                                                           GLuint depthPitch,
-                                                           const PixelStoreStateBase &state,
-                                                           bool is3D) const
+ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLenum formatType,
+                                                       GLuint rowPitch,
+                                                       GLuint depthPitch,
+                                                       const PixelStoreStateBase &state,
+                                                       bool is3D) const
 {
     CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
     CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
     CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
     CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
     CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
-    CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
+    CheckedNumeric<GLuint> checkedPixelBytes(computePixelBytes(formatType));
     auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
     if (!is3D)
     {
@@ -1198,7 +1199,8 @@
     }
 
     CheckedNumeric<GLuint> checkedSkipBytes = 0;
-    ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
+    ANGLE_TRY_RESULT(computeSkipBytes(formatType, rowPitch, depthPitch, state, is3D),
+                     checkedSkipBytes);
 
     CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
 
diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h
index dbfe590..ebab7a9 100644
--- a/src/libANGLE/formatutils.h
+++ b/src/libANGLE/formatutils.h
@@ -71,7 +71,8 @@
 
     ErrorOrResult<GLuint> computeCompressedImageSize(const Extents &size) const;
 
-    ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
+    ErrorOrResult<GLuint> computeSkipBytes(GLenum formatType,
+                                           GLuint rowPitch,
                                            GLuint depthPitch,
                                            const PixelStoreStateBase &state,
                                            bool is3D) const;
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index 5f117a6..1aca71b 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -264,7 +264,7 @@
                                                      packState.rowLength),
                      outputPitch);
     GLuint outputSkipBytes = 0;
-    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, packState, false),
                      outputSkipBytes);
     outputSkipBytes +=
         (area.x - origArea.x) * sizedFormatInfo.pixelBytes + (area.y - origArea.y) * outputPitch;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index 527a29c..e3281eb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -291,7 +291,7 @@
                      inputDepthPitch);
     GLuint inputSkipBytes = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
+        formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack, applySkipImages),
         inputSkipBytes);
 
     const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 7a14e7e..027422a 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -742,9 +742,9 @@
     ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
                      srcDepthPitch);
     GLuint srcSkipBytes = 0;
-    ANGLE_TRY_RESULT(
-        internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.usesTex3D()),
-        srcSkipBytes);
+    ANGLE_TRY_RESULT(internalFormatInfo.computeSkipBytes(type, srcRowPitch, srcDepthPitch, unpack,
+                                                         index.usesTex3D()),
+                     srcSkipBytes);
 
     const d3d11::Format &d3d11Format =
         d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 03be38b..0132033 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -883,7 +883,7 @@
     ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
                      rowBytes);
     GLuint skipBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(type, rowBytes, 0, pack, false), skipBytes);
 
     gl::PixelPackState directPack;
     directPack.alignment   = 1;
@@ -925,7 +925,7 @@
         ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
                          rowBytes);
         GLuint skipBytes = 0;
-        ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+        ANGLE_TRY_RESULT(glFormat.computeSkipBytes(type, rowBytes, 0, pack, false), skipBytes);
 
         gl::PixelPackState directPack;
         directPack.alignment = 1;
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index 8b42280..2e51a68 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -349,7 +349,7 @@
 
     bool useTexImage3D = nativegl::UseTexImage3D(getType());
     GLuint skipBytes   = 0;
-    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(type, rowBytes, imageBytes, unpack, useTexImage3D),
                      skipBytes);
 
     const uint8_t *pixelsWithSkip = pixels + skipBytes;
@@ -404,7 +404,7 @@
                      imageBytes);
     bool useTexImage3D = nativegl::UseTexImage3D(getType());
     GLuint skipBytes   = 0;
-    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(type, rowBytes, imageBytes, unpack, useTexImage3D),
                      skipBytes);
 
     stateManager->setPixelUnpackState(unpack);
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp
index ed60218..83d8140 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.cpp
+++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -153,7 +153,7 @@
         rowBytes);
 
     GLuint skipBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, packState, false), skipBytes);
+    ANGLE_TRY_RESULT(glFormat.computeSkipBytes(type, rowBytes, 0, packState, false), skipBytes);
     pixels += skipBytes;
 
     // Skip OOB region up to first in bounds pixel
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 9ea4a8e..8e844e3 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -307,7 +307,7 @@
         sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
         outputPitch);
     GLuint outputSkipBytes = 0;
-    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, packState, false),
                      outputSkipBytes);
 
     outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 05995fb..44b7aa4 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -103,7 +103,7 @@
 
     GLuint inputSkipBytes = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
+        formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack, applySkipImages),
         inputSkipBytes);
 
     RendererVk *renderer = contextVk->getRenderer();
diff --git a/src/tests/gl_tests/TextureUploadFormatTest.cpp b/src/tests/gl_tests/TextureUploadFormatTest.cpp
index f5e4f69..2e95215 100644
--- a/src/tests/gl_tests/TextureUploadFormatTest.cpp
+++ b/src/tests/gl_tests/TextureUploadFormatTest.cpp
@@ -163,46 +163,87 @@
         const auto sVal = static_cast<uint32_t>(v < 0.0f);
         return Assemble(sVal, eVal, mVal);
     }
+
+    static constexpr float Decode(const uint32_t sVal, const uint32_t eVal, const uint32_t mVal)
+    {
+        constexpr int eBias = (1 << (kEBits - 1)) - 1;
+        constexpr int mDiv  = 1 << kMBits;
+        float ret = powf(-1, sVal) * powf(2, int(eVal) - eBias) * (1.0f + float(mVal) / mDiv);
+        return ret;
+    }
 };
 using Float16  = SizedFloat<1, 5, 10>;
 using UFloat11 = SizedFloat<0, 5, 6>;
 using UFloat10 = SizedFloat<0, 5, 5>;
 
-uint32_t EncodeRGB9_E5_Rev(const float signedR, const float signedG, const float signedB)
+struct RGB9_E5 final
 {
-    const float r       = std::max(0.0f, signedR);
-    const float g       = std::max(0.0f, signedG);
-    const float b       = std::max(0.0f, signedB);
-    const int eBits     = 5;
-    const int eBias     = (1 << (eBits - 1)) - 1;  // 15
-    const int eMax      = (1 << eBits) - 1;
-    const int mBits     = 9;
-    const uint32_t mMax = (1 << mBits) - 1;
-    // Maximize mVal for one channel
-    // => Find the lowest viable exponent
-    int minViableActualExp                    = 1 << eBits;
-    const auto fnMinimizeViableActualExponent = [&](const float v) {
-        const auto cur = static_cast<int>(ceil(log2f(v / mMax)));
-        if (cur < minViableActualExp)
-        {
-            minViableActualExp = cur;
-        }
-    };
-    fnMinimizeViableActualExponent(r);
-    fnMinimizeViableActualExponent(g);
-    fnMinimizeViableActualExponent(b);
-    const int eVal = std::max(0, std::min(minViableActualExp + eBias + mBits, eMax));
+    // GLES 3.0.5 p129
+    static constexpr int N = 9;   // number of mantissa bits per component
+    static constexpr int B = 15;  // exponent bias
 
-    const auto fnM = [&](const float v) {
-        const auto m = static_cast<uint32_t>(v * powf(2, static_cast<float>(mBits + eBias - eVal)));
-        return std::min(m, mMax);
-    };
+    static uint32_t Encode(const float red, const float green, const float blue)
+    {
+        const auto floori = [](const float x) { return static_cast<int>(floor(x)); };
+        // GLES 3.0.5 p129
+        constexpr int eMax = 31;  // max allowed biased exponent value
 
-    const auto mR = fnM(r);
-    const auto mG = fnM(g);
-    const auto mB = fnM(b);
-    return (mR << 0) | (mG << 9) | (mB << 18) | (eVal << 27);
-}
+        const float twoToN       = powf(2, N);
+        const float sharedExpMax = (twoToN - 1) / twoToN * powf(2, eMax - B);
+
+        const auto fnClampColor = [&](const float color) {
+            return std::max(0.0f, std::min(color, sharedExpMax));
+        };
+        const float redC   = fnClampColor(red);
+        const float greenC = fnClampColor(green);
+        const float blueC  = fnClampColor(blue);
+
+        const float maxC = std::max({redC, greenC, blueC});
+        const int expP   = std::max(-B - 1, floori(log2f(maxC))) + 1 + B;
+
+        const auto fnColorS = [&](const float colorC, const float exp) {
+            return floori(colorC / powf(2, exp - B - N) + 0.5f);
+        };
+        const int maxS = fnColorS(maxC, expP);
+        const int expS = expP + ((maxS == (1 << N)) ? 1 : 0);
+
+        const int redS   = fnColorS(redC, expS);
+        const int greenS = fnColorS(greenC, expS);
+        const int blueS  = fnColorS(blueC, expS);
+
+        // Pack as u32 EGBR.
+        uint32_t ret = expS & 0x1f;
+        ret <<= 9;
+        ret |= blueS & 0x1ff;
+        ret <<= 9;
+        ret |= greenS & 0x1ff;
+        ret <<= 9;
+        ret |= redS & 0x1ff;
+        return ret;
+    }
+
+    static void Decode(uint32_t packed,
+                       float *const out_red,
+                       float *const out_green,
+                       float *const out_blue)
+    {
+        const auto redS = packed & 0x1ff;
+        packed >>= 9;
+        const auto greenS = packed & 0x1ff;
+        packed >>= 9;
+        const auto blueS = packed & 0x1ff;
+        packed >>= 9;
+        const auto expS = packed & 0x1f;
+
+        // These are *not* IEEE-like UFloat14s.
+        // GLES 3.0.5 p165:
+        // red = redS*pow(2,expS-B-N)
+        const auto fnToFloat = [&](const uint32_t x) { return x * powf(2, int(expS) - B - N); };
+        *out_red             = fnToFloat(redS);
+        *out_green           = fnToFloat(greenS);
+        *out_blue            = fnToFloat(blueS);
+    }
+};
 
 }  // anonymous namespace
 
@@ -212,6 +253,9 @@
 // re-encode by hand.
 TEST(TextureUploadFormatTestInternals, Float16Encoding)
 {
+    EXPECT_EQ(Float16::Decode(0, 0x0f, 0), 1.0f);
+    EXPECT_EQ(Float16::Decode(0, 0x0f - 1, 0), 0.5f);
+
     EXPECT_EQ(Float16::Assemble(0, 0x0f, 0), Float16::Encode(1.0));
     EXPECT_EQ(Float16::Assemble(0, 0x0f - 1, 0), Float16::Encode(1.0 / 2));
 
@@ -221,6 +265,20 @@
     EXPECT_EQ(Float16::Assemble(0, 0x0f - 1, 1 << (Float16::kMBits - 2)), Float16::Encode(5.0 / 8));
 }
 
+// Ensure our RGB9_E5 encoding is reasonable, at least for our testcase.
+TEST(TextureUploadFormatTestInternals, RGB9E5Encoding)
+{
+    const auto fnTest = [](const float refR, const float refG, const float refB) {
+        const auto packed = RGB9_E5::Encode(refR, refG, refB);
+        float testR, testG, testB;
+        RGB9_E5::Decode(packed, &testR, &testG, &testB);
+        EXPECT_EQ(testR, refR);
+        EXPECT_EQ(testG, refG);
+        EXPECT_EQ(testB, refB);
+    };
+    fnTest(0.125f, 0.250f, 0.625f);
+}
+
 namespace
 {
 
@@ -247,13 +305,12 @@
 {
     ANGLE_SKIP_TEST_IF(IsD3D9() || IsD3D11_FL93());
 
-    constexpr char kVertShader[] = R"(
+    constexpr char kVertShaderES2[]     = R"(
         void main()
         {
             gl_PointSize = 1.0;
             gl_Position = vec4(0, 0, 0, 1);
         })";
-
     constexpr char kFragShader_Floats[] = R"(
         precision mediump float;
         uniform sampler2D uTex;
@@ -262,26 +319,7 @@
         {
             gl_FragColor = texture2D(uTex, vec2(0,0));
         })";
-    constexpr char kFragShader_Ints[]   = R"(
-        precision mediump float;
-        uniform sampler2D uTex;
-
-        void main()
-        {
-            gl_FragColor = texture2D(uTex, vec2(0,0)) / 8.0;
-        })";
-    ANGLE_GL_PROGRAM(floatsProg, kVertShader, kFragShader_Floats);
-    ANGLE_GL_PROGRAM(intsProg, kVertShader, kFragShader_Ints);
-
-    GLint uTex = glGetUniformLocation(floatsProg, "uTex");
-    ASSERT_NE(uTex, -1);
-    glUseProgram(floatsProg);
-    glUniform1i(uTex, 0);
-
-    uTex = glGetUniformLocation(intsProg, "uTex");
-    ASSERT_NE(uTex, -1);
-    glUseProgram(intsProg);
-    glUniform1i(uTex, 0);
+    ANGLE_GL_PROGRAM(floatsProg, kVertShaderES2, kFragShader_Floats);
 
     glDisable(GL_DITHER);
 
@@ -306,6 +344,9 @@
 
     GLTexture testTex;
     glBindTexture(GL_TEXTURE_2D, testTex);
+    // Must be nearest because some texture formats aren't filterable!
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
     ASSERT_GL_NO_ERROR();
 
@@ -330,7 +371,7 @@
         glTexImage2D(GL_TEXTURE_2D, 0, format.internalFormat, 1, 1, 0, format.unpackFormat,
                      format.unpackType, data);
         const auto uploadErr = glGetError();
-        if (uploadErr)
+        if (uploadErr)  // Format might not be supported. (e.g. on ES2)
             return;
 
         glClearColor(1, 0, 1, 1);
@@ -533,6 +574,36 @@
         fnTest({GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, {1, 0, 0, 0});
     }
 
+    if (getClientMajorVersion() < 3)
+        return;
+
+    constexpr char kVertShaderES3[]    = R"(#version 300 es
+        void main()
+        {
+            gl_PointSize = 1.0;
+            gl_Position = vec4(0, 0, 0, 1);
+        })";
+    constexpr char kFragShader_Ints[]  = R"(#version 300 es
+        precision mediump float;
+        uniform highp isampler2D uTex;
+        out vec4 oFragColor;
+
+        void main()
+        {
+            oFragColor = vec4(texture(uTex, vec2(0,0))) / 8.0;
+        })";
+    constexpr char kFragShader_Uints[] = R"(#version 300 es
+        precision mediump float;
+        uniform highp usampler2D uTex;
+        out vec4 oFragColor;
+
+        void main()
+        {
+            oFragColor = vec4(texture(uTex, vec2(0,0))) / 8.0;
+        })";
+    ANGLE_GL_PROGRAM(intsProg, kVertShaderES3, kFragShader_Ints);
+    ANGLE_GL_PROGRAM(uintsProg, kVertShaderES3, kFragShader_Uints);
+
     // Non-normalized ints
     glUseProgram(intsProg);
 
@@ -541,11 +612,6 @@
         constexpr uint8_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
         ZeroAndCopy(srcBuffer, src);
 
-        fnTest({GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
-        fnTest({GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
-        fnTest({GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
-        fnTest({GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
-
         fnTest({GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, {1, 1, 1, 1});
         fnTest({GL_RGB8I, GL_RGB_INTEGER, GL_BYTE}, {1, 1, 1, 1});
         fnTest({GL_RG8I, GL_RG_INTEGER, GL_BYTE}, {1, 1, 1, 1});
@@ -557,11 +623,6 @@
         constexpr uint16_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
         ZeroAndCopy(srcBuffer, src);
 
-        fnTest({GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
-        fnTest({GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
-        fnTest({GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
-        fnTest({GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
-
         fnTest({GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, {1, 1, 1, 1});
         fnTest({GL_RGB16I, GL_RGB_INTEGER, GL_SHORT}, {1, 1, 1, 1});
         fnTest({GL_RG16I, GL_RG_INTEGER, GL_SHORT}, {1, 1, 1, 1});
@@ -573,17 +634,48 @@
         constexpr uint32_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
         ZeroAndCopy(srcBuffer, src);
 
-        fnTest({GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
-        fnTest({GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
-        fnTest({GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
-        fnTest({GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
-
         fnTest({GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, {1, 1, 1, 1});
         fnTest({GL_RGB32I, GL_RGB_INTEGER, GL_INT}, {1, 1, 1, 1});
         fnTest({GL_RG32I, GL_RG_INTEGER, GL_INT}, {1, 1, 1, 1});
         fnTest({GL_R32I, GL_RED_INTEGER, GL_INT}, {1, 1, 1, 1});
     }
 
+    // Non-normalized uints
+    glUseProgram(uintsProg);
+
+    // RGBA_INTEGER+UNSIGNED_BYTE
+    {
+        constexpr uint8_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
+        ZeroAndCopy(srcBuffer, src);
+
+        fnTest({GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
+        fnTest({GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
+        fnTest({GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
+        fnTest({GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, {1, 1, 1, 1});
+    }
+
+    // RGBA_INTEGER+UNSIGNED_SHORT
+    {
+        constexpr uint16_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
+        ZeroAndCopy(srcBuffer, src);
+
+        fnTest({GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
+        fnTest({GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
+        fnTest({GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
+        fnTest({GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, {1, 1, 1, 1});
+    }
+
+    // RGBA_INTEGER+UNSIGNED_INT
+    {
+        constexpr uint32_t src[4] = {srcIntVals[0], srcIntVals[1], srcIntVals[2], srcIntVals[3]};
+        ZeroAndCopy(srcBuffer, src);
+
+        fnTest({GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
+        fnTest({GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
+        fnTest({GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
+        fnTest({GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, {1, 1, 1, 1});
+    }
+
     // RGBA_INTEGER+UNSIGNED_INT_2_10_10_10_REV
     {
         constexpr uint32_t src[] = {static_cast<uint32_t>(srcIntVals[0] << 0) |
@@ -654,7 +746,7 @@
 
     // UNSIGNED_INT_5_9_9_9_REV
     {
-        const uint32_t src[] = {EncodeRGB9_E5_Rev(srcVals[0], srcVals[1], srcVals[2])};
+        const uint32_t src[] = {RGB9_E5::Encode(srcVals[0], srcVals[1], srcVals[2])};
         ZeroAndCopy(srcBuffer, src);
 
         fnTest({GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, {1, 1, 1, 0});
@@ -675,8 +767,10 @@
 }
 
 ANGLE_INSTANTIATE_TEST(TextureUploadFormatTest,
-                       ES2_D3D11(),
+                       ES3_D3D11(),
                        ES2_D3D11_FL9_3(),
                        ES2_D3D9(),
                        ES2_OPENGL(),
-                       ES2_OPENGLES());
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());