Warning, /graphics/krita/3rdparty/ext_googleangle/0001-D3D-Initialize-storage-after-generating-mipmap-image.patch is written in an unsupported language. File is not indexed.
0001 From 459c367ed5a524ce0aad1877c1e39e82126f2707 Mon Sep 17 00:00:00 2001
0002 From: Geoff Lang <geofflang@chromium.org>
0003 Date: Fri, 21 Jan 2022 10:02:33 -0500
0004 Subject: [PATCH] D3D: Initialize storage after generating mipmap images.
0005
0006 When TextureD3D generates mipmaps without a storage present, it
0007 initializes all the images and then generates mipmaps on the CPU.
0008 Attempt to generate a storage after initializing all the mip images
0009 so that the mipmap generation can be done on the GPU.
0010
0011 Fix several edge cases where texture storage was not copied back
0012 to images when redefining for mipmap generation. This resulted in
0013 the newly generated mipmaps not using the correct data.
0014
0015 Bug: chromium:1256340
0016 Change-Id: I76122d36385450d973bf00f7d07402a1f975492c
0017 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3406643
0018 Reviewed-by: Kenneth Russell <kbr@chromium.org>
0019 Commit-Queue: Geoff Lang <geofflang@chromium.org>
0020 Reviewed-by: Jamie Madill <jmadill@chromium.org>
0021 ---
0022 src/libANGLE/renderer/d3d/TextureD3D.cpp | 147 +++++++++++++++++------
0023 src/libANGLE/renderer/d3d/TextureD3D.h | 3 +-
0024 src/tests/gl_tests/TextureTest.cpp | 29 +++--
0025 3 files changed, 129 insertions(+), 50 deletions(-)
0026
0027 diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
0028 index 32a398bd3..098b17393 100644
0029 --- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
0030 +++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
0031 @@ -521,6 +521,10 @@ angle::Result TextureD3D::generateMipmapUsingImages(const gl::Context *context,
0032 // CPU-side mipmap generation, or something else.
0033 bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() &&
0034 !(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled));
0035 + if (renderableStorage)
0036 + {
0037 + ANGLE_TRY(updateStorage(context));
0038 + }
0039
0040 for (GLint layer = 0; layer < layerCount; ++layer)
0041 {
0042 @@ -691,7 +695,7 @@ angle::Result TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLe
0043 }
0044 }
0045
0046 - ANGLE_TRY(releaseTexStorage(context));
0047 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0048 }
0049
0050 return angle::Result::Continue;
0051 @@ -713,13 +717,37 @@ angle::Result TextureD3D::syncState(const gl::Context *context,
0052 return angle::Result::Continue;
0053 }
0054
0055 -angle::Result TextureD3D::releaseTexStorage(const gl::Context *context)
0056 +angle::Result TextureD3D::releaseTexStorage(const gl::Context *context,
0057 + const gl::TexLevelMask ©StorageToImagesMask)
0058 {
0059 if (!mTexStorage)
0060 {
0061 return angle::Result::Continue;
0062 }
0063
0064 + if (mTexStorage->isRenderTarget())
0065 + {
0066 + const GLenum storageFormat = getBaseLevelInternalFormat();
0067 + const size_t storageLevels = mTexStorage->getLevelCount();
0068 +
0069 + gl::ImageIndexIterator iterator = imageIterator();
0070 + while (iterator.hasNext())
0071 + {
0072 + const gl::ImageIndex index = iterator.next();
0073 + ImageD3D *image = getImage(index);
0074 + const int storageWidth = std::max(1, getLevelZeroWidth() >> index.getLevelIndex());
0075 + const int storageHeight = std::max(1, getLevelZeroHeight() >> index.getLevelIndex());
0076 + if (image && isImageComplete(index) && image->getWidth() == storageWidth &&
0077 + image->getHeight() == storageHeight &&
0078 + image->getInternalFormat() == storageFormat &&
0079 + index.getLevelIndex() < static_cast<int>(storageLevels) &&
0080 + copyStorageToImagesMask[index.getLevelIndex()])
0081 + {
0082 + ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
0083 + }
0084 + }
0085 + }
0086 +
0087 onStateChange(angle::SubjectMessage::StorageReleased);
0088
0089 auto err = mTexStorage->onDestroy(context);
0090 @@ -729,7 +757,7 @@ angle::Result TextureD3D::releaseTexStorage(const gl::Context *context)
0091
0092 void TextureD3D::onDestroy(const gl::Context *context)
0093 {
0094 - (void)releaseTexStorage(context);
0095 + (void)releaseTexStorage(context, gl::TexLevelMask());
0096 }
0097
0098 angle::Result TextureD3D::initializeContents(const gl::Context *context,
0099 @@ -1340,7 +1368,7 @@ angle::Result TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surfa
0100 gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
0101 ANGLE_TRY(redefineImage(context, 0, internalformat, size, true));
0102
0103 - ANGLE_TRY(releaseTexStorage(context));
0104 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0105
0106 SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
0107 ASSERT(surfaceD3D);
0108 @@ -1358,7 +1386,7 @@ angle::Result TextureD3D_2D::releaseTexImage(const gl::Context *context)
0109 {
0110 if (mTexStorage)
0111 {
0112 - ANGLE_TRY(releaseTexStorage(context));
0113 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0114 }
0115
0116 for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
0117 @@ -1386,7 +1414,7 @@ angle::Result TextureD3D_2D::setEGLImageTarget(const gl::Context *context,
0118 ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
0119 }
0120
0121 - ANGLE_TRY(releaseTexStorage(context));
0122 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0123 mImageArray[0]->markClean();
0124
0125 // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
0126 @@ -1413,6 +1441,10 @@ angle::Result TextureD3D_2D::initMipmapImages(const gl::Context *context)
0127
0128 ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
0129 }
0130 +
0131 + // We should be mip-complete now so generate the storage.
0132 + ANGLE_TRY(initializeStorage(context, true));
0133 +
0134 return angle::Result::Continue;
0135 }
0136
0137 @@ -1559,7 +1591,10 @@ angle::Result TextureD3D_2D::setCompleteTexStorage(const gl::Context *context,
0138 }
0139 }
0140
0141 - ANGLE_TRY(releaseTexStorage(context));
0142 + gl::TexLevelMask copyImageMask;
0143 + copyImageMask.set();
0144 +
0145 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0146 mTexStorage = newCompleteTexStorage;
0147 mTexStorageObserverBinding.bind(mTexStorage);
0148
0149 @@ -1617,9 +1652,6 @@ angle::Result TextureD3D_2D::redefineImage(const gl::Context *context,
0150 const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
0151 const GLenum storageFormat = getBaseLevelInternalFormat();
0152
0153 - mImageArray[level]->redefine(gl::TextureType::_2D, internalformat, size, forceRelease);
0154 - mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
0155 -
0156 if (mTexStorage)
0157 {
0158 const size_t storageLevels = mTexStorage->getLevelCount();
0159 @@ -1636,11 +1668,18 @@ angle::Result TextureD3D_2D::redefineImage(const gl::Context *context,
0160 size.height != storageHeight || internalformat != storageFormat ||
0161 mEGLImageTarget) // Discard mismatched storage
0162 {
0163 - ANGLE_TRY(releaseTexStorage(context));
0164 + gl::TexLevelMask copyImageMask;
0165 + copyImageMask.set();
0166 + copyImageMask.set(level, false);
0167 +
0168 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0169 markAllImagesDirty();
0170 }
0171 }
0172
0173 + mImageArray[level]->redefine(gl::TextureType::_2D, internalformat, size, forceRelease);
0174 + mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
0175 +
0176 // Can't be an EGL image target after being redefined
0177 mEGLImageTarget = false;
0178
0179 @@ -2132,6 +2171,10 @@ angle::Result TextureD3D_Cube::initMipmapImages(const gl::Context *context)
0180 gl::Extents(faceLevelSize, faceLevelSize, 1), false));
0181 }
0182 }
0183 +
0184 + // We should be mip-complete now so generate the storage.
0185 + ANGLE_TRY(initializeStorage(context, true));
0186 +
0187 return angle::Result::Continue;
0188 }
0189
0190 @@ -2231,7 +2274,10 @@ angle::Result TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context,
0191 }
0192 }
0193
0194 - ANGLE_TRY(releaseTexStorage(context));
0195 + gl::TexLevelMask copyImageMask;
0196 + copyImageMask.set();
0197 +
0198 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0199 mTexStorage = newCompleteTexStorage;
0200 mTexStorageObserverBinding.bind(mTexStorage);
0201
0202 @@ -2343,10 +2389,6 @@ angle::Result TextureD3D_Cube::redefineImage(const gl::Context *context,
0203 const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
0204 const GLenum storageFormat = getBaseLevelInternalFormat();
0205
0206 - mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalformat, size,
0207 - forceRelease);
0208 - mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();
0209 -
0210 if (mTexStorage)
0211 {
0212 const int storageLevels = mTexStorage->getLevelCount();
0213 @@ -2356,10 +2398,19 @@ angle::Result TextureD3D_Cube::redefineImage(const gl::Context *context,
0214 internalformat != storageFormat) // Discard mismatched storage
0215 {
0216 markAllImagesDirty();
0217 - ANGLE_TRY(releaseTexStorage(context));
0218 +
0219 + gl::TexLevelMask copyImageMask;
0220 + copyImageMask.set();
0221 + copyImageMask.set(level, false);
0222 +
0223 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0224 }
0225 }
0226
0227 + mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalformat, size,
0228 + forceRelease);
0229 + mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();
0230 +
0231 return angle::Result::Continue;
0232 }
0233
0234 @@ -2820,6 +2871,9 @@ angle::Result TextureD3D_3D::initMipmapImages(const gl::Context *context)
0235 ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
0236 }
0237
0238 + // We should be mip-complete now so generate the storage.
0239 + ANGLE_TRY(initializeStorage(context, true));
0240 +
0241 return angle::Result::Continue;
0242 }
0243
0244 @@ -2899,7 +2953,10 @@ angle::Result TextureD3D_3D::createCompleteStorage(const gl::Context *context,
0245 angle::Result TextureD3D_3D::setCompleteTexStorage(const gl::Context *context,
0246 TextureStorage *newCompleteTexStorage)
0247 {
0248 - ANGLE_TRY(releaseTexStorage(context));
0249 + gl::TexLevelMask copyImageMask;
0250 + copyImageMask.set();
0251 +
0252 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0253 mTexStorage = newCompleteTexStorage;
0254 mTexStorageObserverBinding.bind(mTexStorage);
0255 mDirtyImages = true;
0256 @@ -3018,9 +3075,6 @@ angle::Result TextureD3D_3D::redefineImage(const gl::Context *context,
0257 const int storageDepth = std::max(1, getLevelZeroDepth() >> level);
0258 const GLenum storageFormat = getBaseLevelInternalFormat();
0259
0260 - mImageArray[level]->redefine(gl::TextureType::_3D, internalformat, size, forceRelease);
0261 - mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
0262 -
0263 if (mTexStorage)
0264 {
0265 const int storageLevels = mTexStorage->getLevelCount();
0266 @@ -3030,10 +3084,18 @@ angle::Result TextureD3D_3D::redefineImage(const gl::Context *context,
0267 internalformat != storageFormat) // Discard mismatched storage
0268 {
0269 markAllImagesDirty();
0270 - ANGLE_TRY(releaseTexStorage(context));
0271 +
0272 + gl::TexLevelMask copyImageMask;
0273 + copyImageMask.set();
0274 + copyImageMask.set(level, false);
0275 +
0276 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0277 }
0278 }
0279
0280 + mImageArray[level]->redefine(gl::TextureType::_3D, internalformat, size, forceRelease);
0281 + mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
0282 +
0283 return angle::Result::Continue;
0284 }
0285
0286 @@ -3560,6 +3622,9 @@ angle::Result TextureD3D_2DArray::initMipmapImages(const gl::Context *context)
0287 ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false));
0288 }
0289
0290 + // We should be mip-complete now so generate the storage.
0291 + ANGLE_TRY(initializeStorage(context, true));
0292 +
0293 return angle::Result::Continue;
0294 }
0295
0296 @@ -3629,7 +3694,10 @@ angle::Result TextureD3D_2DArray::createCompleteStorage(const gl::Context *conte
0297 angle::Result TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context,
0298 TextureStorage *newCompleteTexStorage)
0299 {
0300 - ANGLE_TRY(releaseTexStorage(context));
0301 + gl::TexLevelMask copyImageMask;
0302 + copyImageMask.set();
0303 +
0304 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0305 mTexStorage = newCompleteTexStorage;
0306 mTexStorageObserverBinding.bind(mTexStorage);
0307 mDirtyImages = true;
0308 @@ -3796,17 +3864,6 @@ angle::Result TextureD3D_2DArray::redefineImage(const gl::Context *context,
0309 }
0310 }
0311
0312 - if (size.depth > 0)
0313 - {
0314 - for (int layer = 0; layer < mLayerCounts[level]; layer++)
0315 - {
0316 - mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalformat,
0317 - gl::Extents(size.width, size.height, 1),
0318 - forceRelease);
0319 - mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
0320 - }
0321 - }
0322 -
0323 if (mTexStorage)
0324 {
0325 const int storageLevels = mTexStorage->getLevelCount();
0326 @@ -3816,7 +3873,23 @@ angle::Result TextureD3D_2DArray::redefineImage(const gl::Context *context,
0327 internalformat != storageFormat) // Discard mismatched storage
0328 {
0329 markAllImagesDirty();
0330 - ANGLE_TRY(releaseTexStorage(context));
0331 +
0332 + gl::TexLevelMask copyImageMask;
0333 + copyImageMask.set();
0334 + copyImageMask.set(level, false);
0335 +
0336 + ANGLE_TRY(releaseTexStorage(context, copyImageMask));
0337 + }
0338 + }
0339 +
0340 + if (size.depth > 0)
0341 + {
0342 + for (int layer = 0; layer < mLayerCounts[level]; layer++)
0343 + {
0344 + mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalformat,
0345 + gl::Extents(size.width, size.height, 1),
0346 + forceRelease);
0347 + mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
0348 }
0349 }
0350
0351 @@ -3978,7 +4051,7 @@ angle::Result TextureD3D_External::setImageExternal(const gl::Context *context,
0352 {
0353 ASSERT(type == gl::TextureType::External);
0354
0355 - ANGLE_TRY(releaseTexStorage(context));
0356 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0357
0358 // If the stream is null, the external image is unbound and we release the storage
0359 if (stream != nullptr)
0360 @@ -3999,7 +4072,7 @@ angle::Result TextureD3D_External::setEGLImageTarget(const gl::Context *context,
0361 RenderTargetD3D *renderTargetD3D = nullptr;
0362 ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
0363
0364 - ANGLE_TRY(releaseTexStorage(context));
0365 + ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
0366 mTexStorage =
0367 mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D, mState.getLabel());
0368
0369 diff --git a/src/libANGLE/renderer/d3d/TextureD3D.h b/src/libANGLE/renderer/d3d/TextureD3D.h
0370 index 4db8dfab8..3b4cf3da4 100644
0371 --- a/src/libANGLE/renderer/d3d/TextureD3D.h
0372 +++ b/src/libANGLE/renderer/d3d/TextureD3D.h
0373 @@ -186,7 +186,8 @@ class TextureD3D : public TextureImpl, public angle::ObserverInterface
0374 const gl::ImageIndex &index,
0375 const gl::Box ®ion);
0376
0377 - angle::Result releaseTexStorage(const gl::Context *context);
0378 + angle::Result releaseTexStorage(const gl::Context *context,
0379 + const gl::TexLevelMask ©StorageToImagesMask);
0380
0381 GLuint getBaseLevel() const { return mBaseLevel; }
0382
0383 diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
0384 index d84f2c4ca..5aa4b5090 100644
0385 --- a/src/tests/gl_tests/TextureTest.cpp
0386 +++ b/src/tests/gl_tests/TextureTest.cpp
0387 @@ -2058,6 +2058,11 @@ TEST_P(Texture2DTestWithDrawScale, MipmapsTwice)
0388 pixelsBlue.data());
0389 glGenerateMipmap(GL_TEXTURE_2D);
0390
0391 + drawQuad(mProgram, "position", 0.5f);
0392 +
0393 + EXPECT_GL_NO_ERROR();
0394 + EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::blue);
0395 +
0396 std::vector<GLColor> pixelsGreen(16u * 16u, GLColor::green);
0397
0398 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
0399 @@ -4208,24 +4213,24 @@ void Texture2DBaseMaxTestES3::testGenerateMipmapAfterRebase(bool immutable)
0400 drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
0401 if (lod == 0)
0402 {
0403 - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
0404 - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
0405 - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
0406 - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
0407 + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
0408 + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
0409 + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
0410 + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
0411 }
0412 else if (lod == kMipCount - 1)
0413 {
0414 - EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]);
0415 - EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]);
0416 - EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]);
0417 - EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]);
0418 + EXPECT_PIXEL_COLOR_EQ(0, 0, kMipColors[lod]) << "lod " << lod;
0419 + EXPECT_PIXEL_COLOR_EQ(w, 0, kMipColors[lod]) << "lod " << lod;
0420 + EXPECT_PIXEL_COLOR_EQ(0, h, kMipColors[lod]) << "lod " << lod;
0421 + EXPECT_PIXEL_COLOR_EQ(w, h, kMipColors[lod]) << "lod " << lod;
0422 }
0423 else
0424 {
0425 - EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor);
0426 - EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor);
0427 - EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor);
0428 - EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor);
0429 + EXPECT_PIXEL_COLOR_EQ(0, 0, kNewMipColor) << "lod " << lod;
0430 + EXPECT_PIXEL_COLOR_EQ(w, 0, kNewMipColor) << "lod " << lod;
0431 + EXPECT_PIXEL_COLOR_EQ(0, h, kNewMipColor) << "lod " << lod;
0432 + EXPECT_PIXEL_COLOR_EQ(w, h, kNewMipColor) << "lod " << lod;
0433 }
0434 }
0435 }
0436 --
0437 2.23.0.windows.1
0438