Hash :
36439d9c
Author :
Date :
2023-10-12T00:00:00
Metal: Fix PBO uploads of PVRTC1 textures Do not override row pitch values for PVRTC1 textures during internal backend operations. Instead, set bytesPerRow to 0 before calling replaceRegion just to pass Metal Validation. Enforce CPU path for PBO uploads until GPU block linearization is implemented. Bug: angleproject:8376 Change-Id: I80b9ec69364d55cd9f51005f4d1a180e05e71c2c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4949350 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Alexey Knyazev <lexa.knyazev@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
//
// Copyright 2023 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// PVRTCCompressedTextureTest.cpp: Sampling tests for PVRTC texture formats
// Invalid usage errors are covered by CompressedTextureFormatsTest.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
class PVRTCCompressedTextureTestES3 : public ANGLETest<>
{
static constexpr int kDim = 128;
protected:
PVRTCCompressedTextureTestES3()
{
setWindowWidth(kDim);
setWindowHeight(kDim);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void testSetUp() override
{
// Prepare some filler data.
// The test only asserts that direct and PBO texture uploads produce
// identical results, so the decoded values do not matter here.
for (size_t i = 0; i < mTextureData.size(); ++i)
{
mTextureData[i] = static_cast<uint8_t>(i + i / 8 + i / 2048);
}
}
void test(GLenum format, GLsizei dimension)
{
// Placeholder for the decoded color values from a directly uploaded texture.
std::array<GLColor, kDim * kDim> controlData;
GLsizei imageSize = 0;
switch (format)
{
case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
imageSize = (std::max(dimension, 8) * std::max(dimension, 8) * 4 + 7) / 8;
break;
case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
imageSize = (std::max(dimension, 16) * std::max(dimension, 8) * 2 + 7) / 8;
break;
}
ASSERT_GT(imageSize, 0);
// Directly upload compressed data and remember the decoded values.
{
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, dimension, dimension, 0, imageSize,
mTextureData.data());
ASSERT_GL_NO_ERROR();
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
glReadPixels(0, 0, kDim, kDim, GL_RGBA, GL_UNSIGNED_BYTE, controlData.data());
ASSERT_GL_NO_ERROR();
}
// Upload the same compressed data using a PBO with different
// offsets and check that it is sampled correctly each time.
for (size_t offset = 0; offset <= 8; ++offset)
{
std::vector<GLubyte> bufferData(offset);
std::copy(mTextureData.begin(), mTextureData.end(), std::back_inserter(bufferData));
ASSERT_EQ(bufferData.size(), mTextureData.size() + offset);
GLBuffer buffer;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferData.size(), bufferData.data(),
GL_STATIC_READ);
ASSERT_GL_NO_ERROR();
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, dimension, dimension, 0, imageSize,
reinterpret_cast<void *>(offset));
ASSERT_GL_NO_ERROR();
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
std::array<GLColor, kDim * kDim> readData;
glReadPixels(0, 0, kDim, kDim, GL_RGBA, GL_UNSIGNED_BYTE, readData.data());
ASSERT_GL_NO_ERROR();
// Check only one screen pixel for each texture pixel.
for (GLsizei x = 0; x < dimension; ++x)
{
for (GLsizei y = 0; y < dimension; ++y)
{
// Tested texture sizes are multiples of the window dimensions.
const size_t xScaled = x * kDim / dimension;
const size_t yScaled = y * kDim / dimension;
const size_t position = yScaled * kDim + xScaled;
EXPECT_EQ(readData[position], controlData[position])
<< "(" << x << ", " << y << ")"
<< " of " << dimension << "x" << dimension << " texture with PBO offset "
<< offset;
}
}
}
}
void run(GLenum format)
{
mProgram.makeRaster(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
for (auto dimension : {1, 2, 4, 8, 16, 32, 64, 128})
{
test(format, dimension);
}
}
private:
std::array<GLubyte, 8192> mTextureData;
GLProgram mProgram;
};
// Test uploading texture data from a PBO to an RGB_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, RGB_PVRTC_4BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
run(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
}
// Test uploading texture data from a PBO to an RGBA_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, RGBA_PVRTC_4BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
run(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG);
}
// Test uploading texture data from a PBO to an RGB_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, RGB_PVRTC_2BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
run(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG);
}
// Test uploading texture data from a PBO to an RGBA_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, RGBA_PVRTC_2BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
run(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG);
}
// Test uploading texture data from a PBO to an SRGB_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, SRGB_PVRTC_4BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
run(GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT);
}
// Test uploading texture data from a PBO to an SRGB_ALPHA_PVRTC_4BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, SRGB_ALPHA_PVRTC_4BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
run(GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT);
}
// Test uploading texture data from a PBO to an SRGB_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, SRGB_PVRTC_2BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
run(GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT);
}
// Test uploading texture data from a PBO to an SRGB_ALPHA_PVRTC_2BPPV1 texture.
TEST_P(PVRTCCompressedTextureTestES3, SRGB_ALPHA_PVRTC_2BPPV1)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_IMG_texture_compression_pvrtc"));
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_pvrtc_sRGB"));
run(GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PVRTCCompressedTextureTestES3);
ANGLE_INSTANTIATE_TEST_ES3(PVRTCCompressedTextureTestES3);