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