Improve D3D11 FL9_3 zero-LOD workaround (e.g. TextureCubes)
D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped
texture, and sample from level zero of it. A previous commit
added a workaround for this in ANGLE to Texture2Ds. This
commit fixes some minor issues in that commit, and extends
the workaround to apply to TextureCubes too.
Change-Id: Ic97321af6f8bbf7ad5d96e58655c342db3978a6a
Reviewed-on: https://chromium-review.googlesource.com/241944
Tested-by: Austin Kinross <aukinros@microsoft.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 2173462..7b7c822 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -352,9 +352,6 @@
return gl::Error(GL_NO_ERROR); // no-op
}
- // Set up proper mipmap chain in our Image array.
- initMipmapsImages();
-
if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// Switch to using the mipmapped texture.
@@ -365,6 +362,9 @@
}
}
+ // Set up proper mipmap chain in our Image array.
+ initMipmapsImages();
+
// We know that all layers have the same dimension, for the texture to be complete
GLint layerCount = static_cast<GLint>(getLayerCount(0));
@@ -728,7 +728,9 @@
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
gl::Offset destOffset(0, 0, 0);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError())
@@ -771,7 +773,9 @@
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError())
@@ -1030,11 +1034,9 @@
// If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with.
// Otherwise, it should use the level-zero-only texture.
hintLevelZeroOnly = true;
- int level = 1;
- while (hintLevelZeroOnly && level < levels)
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
{
hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
- level += 1;
}
}
@@ -1381,7 +1383,8 @@
// TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels);
+
+ TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels, false);
gl::Error error = setCompleteTexStorage(storage);
if (error.isError())
@@ -1524,8 +1527,23 @@
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
+ bool hintLevelZeroOnly = false;
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with.
+ // Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++)
+ {
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+ {
+ hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level));
+ }
+ }
+ }
+
// TODO (geofflang): detect if storage creation succeeded
- *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
+ *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
return gl::Error(GL_NO_ERROR);
}