Commit baf64903 by Tim Van Patten Committed by Commit Bot

Allow small compressed mip level copies

Update ValidateCopyImageSubDataBase() to take into consideration if the entire mip level is being written, even if the size of the mip level is smaller than the compressed block size. This also uncovered a bug in ImageHelper::initializeNonZeroMemory() where the image extents are not at least as large as the compressed format block size: VUID-vkCmdCopyBufferToImage-imageExtent-00207 This CL adds isAllocateNonZeroMemoryEnabled() to allow skipping the test when that feature is enabled while that bug is chased. Bug: angleproject:5592 Bug: angleproject:5634 Bug: angleproject:5643 Test: Texture2DTestES3.CopyCompressedImageMipMaps Change-Id: I0381e0d3490fb148604b61dc3bae8f96ba8b5f8e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2673069 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent a9de5d99
...@@ -2965,16 +2965,15 @@ bool ValidateCompressedRegion(const Context *context, ...@@ -2965,16 +2965,15 @@ bool ValidateCompressedRegion(const Context *context,
GLsizei width, GLsizei width,
GLsizei height) GLsizei height)
{ {
if (formatInfo.compressed) ASSERT(formatInfo.compressed);
// INVALID_VALUE is generated if the image format is compressed and the dimensions of the
// subregion fail to meet the alignment constraints of the format.
if ((width % formatInfo.compressedBlockWidth != 0) ||
(height % formatInfo.compressedBlockHeight != 0))
{ {
// INVALID_VALUE is generated if the image format is compressed and the dimensions of the context->validationError(GL_INVALID_VALUE, kInvalidCompressedRegionSize);
// subregion fail to meet the alignment constraints of the format. return false;
if ((width % formatInfo.compressedBlockWidth != 0) ||
(height % formatInfo.compressedBlockHeight != 0))
{
context->validationError(GL_INVALID_VALUE, kInvalidCompressedRegionSize);
return false;
}
} }
return true; return true;
...@@ -3355,12 +3354,27 @@ bool ValidateCopyImageSubDataBase(const Context *context, ...@@ -3355,12 +3354,27 @@ bool ValidateCopyImageSubDataBase(const Context *context,
return false; return false;
} }
if (!ValidateCompressedRegion(context, srcFormatInfo, srcWidth, srcHeight)) bool fillsEntireMip = false;
gl::Texture *dstTexture = context->getTexture({dstName});
gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget);
// TODO(http://anglebug.com/5643): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) are
// unsupported when used with compressed formats due to gl::PackParam() returning
// TextureTarget::InvalidEnum.
if (dstTargetPacked != gl::TextureTarget::InvalidEnum)
{
const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel);
fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width &&
srcHeight == dstExtents.height && srcDepth == dstExtents.depth;
}
if (srcFormatInfo.compressed && !fillsEntireMip &&
!ValidateCompressedRegion(context, srcFormatInfo, srcWidth, srcHeight))
{ {
return false; return false;
} }
if (!ValidateCompressedRegion(context, dstFormatInfo, dstWidth, dstHeight)) if (dstFormatInfo.compressed && !fillsEntireMip &&
!ValidateCompressedRegion(context, dstFormatInfo, dstWidth, dstHeight))
{ {
return false; return false;
} }
......
...@@ -3870,6 +3870,47 @@ TEST_P(Texture2DTestES3, CopyImage) ...@@ -3870,6 +3870,47 @@ TEST_P(Texture2DTestES3, CopyImage)
EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red); EXPECT_PIXEL_RECT_EQ(0, 0, 2, 4, GLColor::red);
} }
// Test GL_EXT_copy_image compressed texture copy with mipmaps smaller than the block size
TEST_P(Texture2DTestES3, CopyCompressedImageMipMaps)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_copy_image"));
// TODO(http://anglebug.com/5634): Fix calls to vkCmdCopyBufferToImage() with images smaller
// than the compressed format block size.
ANGLE_SKIP_TEST_IF(isAllocateNonZeroMemoryEnabled());
constexpr uint32_t kSize = 4;
constexpr size_t kNumLevels = 3;
const uint8_t CompressedImageETC1[8] = {0x0, 0x0, 0xf8, 0x2, 0xff, 0xff, 0x0, 0x0};
GLTexture srcTexture;
glBindTexture(GL_TEXTURE_2D, srcTexture);
for (size_t level = 0; level < kNumLevels; ++level)
{
glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
kSize >> level, 0, 8, CompressedImageETC1);
EXPECT_GL_NO_ERROR();
}
GLTexture destTexture;
glBindTexture(GL_TEXTURE_2D, destTexture);
for (size_t level = 0; level < kNumLevels; ++level)
{
glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_ETC1_RGB8_OES, kSize >> level,
kSize >> level, 0, 8, nullptr);
EXPECT_GL_NO_ERROR();
}
glBindTexture(GL_TEXTURE_2D, 0);
// copy
for (size_t level = 0; level < kNumLevels; ++level)
{
glCopyImageSubDataEXT(srcTexture, GL_TEXTURE_2D, level, 0, 0, 0, destTexture, GL_TEXTURE_2D,
level, 0, 0, 0, kSize >> level, kSize >> level, 1);
EXPECT_GL_NO_ERROR();
}
}
// Test GL_EXT_copy_image copy with a non-zero base level // Test GL_EXT_copy_image copy with a non-zero base level
TEST_P(Texture2DTestES3, CopyImageBaseLevel1) TEST_P(Texture2DTestES3, CopyImageBaseLevel1)
{ {
......
...@@ -524,6 +524,11 @@ class ANGLETestBase ...@@ -524,6 +524,11 @@ class ANGLETestBase
bool platformSupportsMultithreading() const; bool platformSupportsMultithreading() const;
bool isAllocateNonZeroMemoryEnabled() const
{
return mCurrentParams->getAllocateNonZeroMemoryFeature() == EGL_TRUE;
}
private: private:
void checkD3D11SDKLayersMessages(); void checkD3D11SDKLayersMessages();
......
...@@ -49,6 +49,11 @@ bool PlatformParameters::isSwiftshader() const ...@@ -49,6 +49,11 @@ bool PlatformParameters::isSwiftshader() const
return eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE; return eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
} }
EGLint PlatformParameters::getAllocateNonZeroMemoryFeature() const
{
return eglParameters.allocateNonZeroMemoryFeature;
}
void PlatformParameters::initDefaultParameters() void PlatformParameters::initDefaultParameters()
{ {
// Default debug layers to enabled in tests. // Default debug layers to enabled in tests.
......
...@@ -34,6 +34,7 @@ struct PlatformParameters ...@@ -34,6 +34,7 @@ struct PlatformParameters
EGLint getRenderer() const; EGLint getRenderer() const;
EGLint getDeviceType() const; EGLint getDeviceType() const;
bool isSwiftshader() const; bool isSwiftshader() const;
EGLint getAllocateNonZeroMemoryFeature() const;
void initDefaultParameters(); void initDefaultParameters();
......
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