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 &copyStorageToImagesMask)
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 &region);
0376  
0377 -    angle::Result releaseTexStorage(const gl::Context *context);
0378 +    angle::Result releaseTexStorage(const gl::Context *context,
0379 +                                    const gl::TexLevelMask &copyStorageToImagesMask);
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