Browse Source

GL: expand Texture3D compressed subimage upload to investigate a NV bug.

Nope, unfixable. I don't even know how many days I have lost on trying
to figure out bugs with compressed textures on NVidia. Ugh.
pull/680/head
Vladimír Vondruš 10 months ago
parent
commit
ab05558ee2
  1. 148
      src/Magnum/GL/Test/TextureGLTest.cpp

148
src/Magnum/GL/Test/TextureGLTest.cpp

@ -451,6 +451,61 @@ const struct {
Containers::arrayView(CompressedData3D), 16*4} Containers::arrayView(CompressedData3D), 16*4}
#endif #endif
}; };
/* Combination of CompressedZero3D (defined below) and CompressedData3D */
constexpr UnsignedByte CompressedSubData3DComplete[]{
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 224, 128, 3, 80, 0, 129, 170,
84, 253, 73, 36, 109, 100, 107, 255,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 232, 161, 135, 94, 244, 129, 170,
84, 253, 65, 34, 109, 100, 107, 255,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 240, 194, 11, 47, 248, 130, 170,
84, 253, 65, 34, 109, 100, 107, 251,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 247, 223, 143, 63, 252, 131, 170,
84, 253, 73, 34, 109, 100, 91, 251,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
const struct {
const char* name;
CompressedPixelStorage storage;
Vector3i size, offset;
Containers::ArrayView<const UnsignedByte> dataSparse;
} CompressedSubImage3DData[]{
{"upload full image at zero offset, default pixel storage",
{}, {12, 4, 4}, {},
Containers::arrayView(CompressedSubData3DComplete)},
#ifndef MAGNUM_TARGET_GLES
{"upload full image at zero offset, redundant row length & image height",
CompressedPixelStorage{}
.setRowLength(12)
.setImageHeight(4), {12, 4, 4}, {},
Containers::arrayView(CompressedSubData3DComplete)},
{"upload a slice of full image at zero offset, row length & image height",
CompressedPixelStorage{}
.setRowLength(12)
.setImageHeight(4), {8, 4, 4}, {},
Containers::arrayView(CompressedSubData3DComplete)},
#endif
{"upload a smaller image at offset, default pixel storage",
{}, {4, 4, 4}, {4, 0, 0},
Containers::arrayView(CompressedData3D).exceptPrefix(16*4)},
#ifndef MAGNUM_TARGET_GLES
{"upload a smaller image at offset, skip Z",
CompressedPixelStorage{}
.setSkip({0, 0, 4}), {4, 4, 4}, {4, 0, 0},
Containers::arrayView(CompressedData3D)}
#endif
};
#endif #endif
TextureGLTest::TextureGLTest() { TextureGLTest::TextureGLTest() {
@ -664,17 +719,23 @@ TextureGLTest::TextureGLTest() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&TextureGLTest::compressedImage3DQueryView, &TextureGLTest::compressedImage3DQueryView,
#endif #endif
}, Containers::arraySize(CompressedPixelStorage3DData));
addInstancedTests({
&TextureGLTest::compressedSubImage3D, &TextureGLTest::compressedSubImage3D,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&TextureGLTest::compressedSubImage3DBuffer, &TextureGLTest::compressedSubImage3DBuffer,
#endif #endif
#ifndef MAGNUM_TARGET_GLES }, Containers::arraySize(CompressedSubImage3DData));
#ifndef MAGNUM_TARGET_GLES
addInstancedTests({
&TextureGLTest::compressedSubImage3DQuery, &TextureGLTest::compressedSubImage3DQuery,
&TextureGLTest::compressedSubImage3DQueryView, &TextureGLTest::compressedSubImage3DQueryView,
&TextureGLTest::compressedSubImage3DQueryBuffer &TextureGLTest::compressedSubImage3DQueryBuffer
#endif
}, Containers::arraySize(CompressedPixelStorage3DData)); }, Containers::arraySize(CompressedPixelStorage3DData));
#endif #endif
#endif
addTests({ addTests({
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -2871,33 +2932,8 @@ constexpr UnsignedByte CompressedZero3D[3*4*16]{
}; };
#endif #endif
#ifndef MAGNUM_TARGET_GLES
/* Combination of CompressedZero3D and CompressedData3D */
constexpr UnsignedByte CompressedSubData3DComplete[]{
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 224, 128, 3, 80, 0, 129, 170,
84, 253, 73, 36, 109, 100, 107, 255,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 232, 161, 135, 94, 244, 129, 170,
84, 253, 65, 34, 109, 100, 107, 255,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 240, 194, 11, 47, 248, 130, 170,
84, 253, 65, 34, 109, 100, 107, 251,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 247, 223, 143, 63, 252, 131, 170,
84, 253, 73, 34, 109, 100, 91, 251,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
void TextureGLTest::compressedSubImage3D() { void TextureGLTest::compressedSubImage3D() {
auto&& data = CompressedPixelStorage3DData[testCaseInstanceId()]; auto&& data = CompressedSubImage3DData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
#if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
@ -2916,8 +2952,8 @@ void TextureGLTest::compressedSubImage3D() {
Texture3D texture; Texture3D texture;
texture.setCompressedImage(0, CompressedImageView3D{CompressedPixelFormat::RGBABptcUnorm, texture.setCompressedImage(0, CompressedImageView3D{CompressedPixelFormat::RGBABptcUnorm,
{12, 4, 4}, CompressedZero3D}); {12, 4, 4}, CompressedZero3D});
texture.setCompressedSubImage(0, {4, 0, 0}, CompressedImageView3D{data.storage, texture.setCompressedSubImage(0, data.offset, CompressedImageView3D{data.storage,
CompressedPixelFormat::RGBABptcUnorm, Vector3i{4}, CompressedPixelFormat::RGBABptcUnorm, data.size,
data.dataSparse}); data.dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
@ -2931,8 +2967,43 @@ void TextureGLTest::compressedSubImage3D() {
CORRADE_COMPARE(image.size(), (Vector3i{12, 4, 4})); CORRADE_COMPARE(image.size(), (Vector3i{12, 4, 4}));
{ {
CORRADE_EXPECT_FAIL_IF(data.storage != CompressedPixelStorage{} && (Context::current().detectedDriver() & Context::DetectedDriver::NVidia), /* This "works" if running the test cases that have a default pixel
"Compressed 3D pixel storage behaves weirdly with BPTC compression on NVidia."); storage as the first ever, i.e. with no test before setting
GL_UNPACK_COMPRESSED_BLOCK_WIDTH etc. Which used to be the common
case back when compressed block properties were meant to be
specified manually in CompressedPixelStorage, and so this particular
test case seemed to pass on NVidia and seemed to only behave weird
with the Z skip.
But the block properties are now taken implicitly from the format
and set internally almost always, thus resulting in this test being
broken in almost all cases. I tried many different things, including
uploading slice-by-slice (and thus avoiding the need to set Z skip),
but as soon as the block size state is non-zero, only the very first
slice uploaded, no other. Using setStorage() instead of setImage()
didn't make any difference, although such a change is known to work
around certain bugs in cube maps.
One option I refuse to try out is reverting the change in
https://github.com/mosra/magnum/commit/214dd5dbadf4bba8884e2cafed1eced838cda977
-- i.e., it seems that NV treats 3D BPTC blocks as cubes, being
4x4x4 instead of 4x4x1, and then uploads them as such, which might
*partially* explain what's going on in here. But even if reordering
data in such a way would make some more tests pass, it'd still limit
the upload to be only possible with multiples of four slices, which
isn't really any better.
Thus, I fear, it's unfixable. Fortunately it's only the case of 3D
textures, which only support BPTC / BC7. 2D arrays or cubemaps don't
seem to exhibit any similar bug. 3D ASTC formats would theoretically
be another format that works with 3D textures, but even 2D ASTC
still isn't exposed by NVidia even in 2025, so that's out of
question. The workaround is shown in the passing tests, i.e.
uploading whole slices. */
Int pixelStoreBlockPropertiesSet = 0;
glGetIntegerv(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, &pixelStoreBlockPropertiesSet);
CORRADE_EXPECT_FAIL_IF((pixelStoreBlockPropertiesSet || data.storage != CompressedPixelStorage{}) && data.size != (Vector3i{12, 4, 4}) && (Context::current().detectedDriver() & Context::DetectedDriver::NVidia),
"Compressed 3D texture upload behaves weirdly on NVidia if non-default pixel storage is used and not uploading the whole image.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()), CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(image.data()),
Containers::arrayView(CompressedSubData3DComplete), Containers::arrayView(CompressedSubData3DComplete),
TestSuite::Compare::Container); TestSuite::Compare::Container);
@ -2943,7 +3014,7 @@ void TextureGLTest::compressedSubImage3D() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void TextureGLTest::compressedSubImage3DBuffer() { void TextureGLTest::compressedSubImage3DBuffer() {
auto&& data = CompressedPixelStorage3DData[testCaseInstanceId()]; auto&& data = CompressedSubImage3DData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -2959,8 +3030,8 @@ void TextureGLTest::compressedSubImage3DBuffer() {
Texture3D texture; Texture3D texture;
texture.setCompressedImage(0, CompressedImageView3D{CompressedPixelFormat::RGBABptcUnorm, texture.setCompressedImage(0, CompressedImageView3D{CompressedPixelFormat::RGBABptcUnorm,
{12, 4, 4}, CompressedZero3D}); {12, 4, 4}, CompressedZero3D});
texture.setCompressedSubImage(0, {4, 0, 0}, CompressedImageView3D{data.storage, texture.setCompressedSubImage(0, data.offset, CompressedImageView3D{data.storage,
CompressedPixelFormat::RGBABptcUnorm, Vector3i{4}, CompressedPixelFormat::RGBABptcUnorm, data.size,
data.dataSparse}); data.dataSparse});
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
@ -2975,8 +3046,11 @@ void TextureGLTest::compressedSubImage3DBuffer() {
CORRADE_COMPARE(image.size(), (Vector3i{12, 4, 4})); CORRADE_COMPARE(image.size(), (Vector3i{12, 4, 4}));
{ {
CORRADE_EXPECT_FAIL_IF(data.storage != CompressedPixelStorage{} && (Context::current().detectedDriver() & Context::DetectedDriver::NVidia), /* Same as in compressedSubImage3D(), see comment there for details */
"Compressed 3D pixel storage behaves weirdly with BPTC compression on NVidia."); Int pixelStoreBlockPropertiesSet = 0;
glGetIntegerv(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, &pixelStoreBlockPropertiesSet);
CORRADE_EXPECT_FAIL_IF((pixelStoreBlockPropertiesSet || data.storage != CompressedPixelStorage{}) && data.size != (Vector3i{12, 4, 4}) && (Context::current().detectedDriver() & Context::DetectedDriver::NVidia),
"Compressed 3D texture upload behaves weirdly on NVidia if non-default pixel storage is used and not uploading the whole image.");
CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(imageData), CORRADE_COMPARE_AS(Containers::arrayCast<UnsignedByte>(imageData),
Containers::arrayView(CompressedSubData3DComplete), Containers::arrayView(CompressedSubData3DComplete),
TestSuite::Compare::Container); TestSuite::Compare::Container);

Loading…
Cancel
Save