Commit 62815bf4 by Austin Kinross Committed by Geoff Lang

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/241944Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 398c5a2a
......@@ -135,7 +135,7 @@ class RendererD3D : public Renderer
virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0;
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
......
......@@ -352,9 +352,6 @@ gl::Error TextureD3D::generateMipmaps()
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 @@ gl::Error TextureD3D::generateMipmaps()
}
}
// 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::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectan
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::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Off
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 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage
// 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 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter
// 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 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora
// 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);
}
......
......@@ -2829,9 +2829,9 @@ TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool r
return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly);
}
TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
{
return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels);
return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
}
TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
......
......@@ -155,7 +155,7 @@ class Renderer11 : public RendererD3D
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
......
......@@ -50,7 +50,7 @@ class TextureStorage11 : public TextureStorage
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
virtual int getLevelCount() const;
UINT getSubresourceIndex(const gl::ImageIndex &index) const;
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
void invalidateSwizzleCacheLevel(int mipLevel);
......@@ -201,23 +201,32 @@ class TextureStorage11_2D : public TextureStorage11
class TextureStorage11_Cube : public TextureStorage11
{
public:
TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual ~TextureStorage11_Cube();
static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
virtual gl::Error getResource(ID3D11Resource **outResource);
virtual gl::Error getMippedResource(ID3D11Resource **outResource);
virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual gl::Error copyToStorage(TextureStorage *destStorage);
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error ensureTextureExists(int mipLevels);
private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
......@@ -229,6 +238,11 @@ class TextureStorage11_Cube : public TextureStorage11
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
// Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
ID3D11Texture2D *mLevelZeroTexture;
RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
bool mUseLevelZeroTexture;
ID3D11Texture2D *mSwizzleTexture;
ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
......
......@@ -2832,9 +2832,9 @@ TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool re
return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
}
TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
{
return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels);
return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
}
TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
......
......@@ -164,7 +164,7 @@ class Renderer9 : public RendererD3D
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
......
......@@ -286,7 +286,7 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
return gl::Error(GL_NO_ERROR);
}
TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
: TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
mTexture = NULL;
......
......@@ -88,7 +88,7 @@ class TextureStorage9_2D : public TextureStorage9
class TextureStorage9_Cube : public TextureStorage9
{
public:
TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual ~TextureStorage9_Cube();
static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
......
#include "ANGLETest.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(CubeMapTextureTest, ES2_D3D11);
ANGLE_TYPED_TEST_CASE(CubeMapTextureTest, ES2_D3D11, ES2_D3D11_FL9_3);
template<typename T>
class CubeMapTextureTest : public ANGLETest
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment