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 ...@@ -135,7 +135,7 @@ class RendererD3D : public Renderer
virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0; virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 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 *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 *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; virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
......
...@@ -352,9 +352,6 @@ gl::Error TextureD3D::generateMipmaps() ...@@ -352,9 +352,6 @@ gl::Error TextureD3D::generateMipmaps()
return gl::Error(GL_NO_ERROR); // no-op return gl::Error(GL_NO_ERROR); // no-op
} }
// Set up proper mipmap chain in our Image array.
initMipmapsImages();
if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround) if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{ {
// Switch to using the mipmapped texture. // Switch to using the mipmapped texture.
...@@ -365,6 +362,9 @@ gl::Error TextureD3D::generateMipmaps() ...@@ -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 // We know that all layers have the same dimension, for the texture to be complete
GLint layerCount = static_cast<GLint>(getLayerCount(0)); GLint layerCount = static_cast<GLint>(getLayerCount(0));
...@@ -728,7 +728,9 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectan ...@@ -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::ImageIndex index = gl::ImageIndex::Make2D(level);
gl::Offset destOffset(0, 0, 0); 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); gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError()) if (error.isError())
...@@ -771,7 +773,9 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Off ...@@ -771,7 +773,9 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Off
gl::ImageIndex index = gl::ImageIndex::Make2D(level); 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); gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError()) if (error.isError())
...@@ -1030,11 +1034,9 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage ...@@ -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. // 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. // Otherwise, it should use the level-zero-only texture.
hintLevelZeroOnly = true; hintLevelZeroOnly = true;
int level = 1; for (int level = 1; level < levels && hintLevelZeroOnly; level++)
while (hintLevelZeroOnly && level < levels)
{ {
hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(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 ...@@ -1381,7 +1383,8 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter
// TODO(geofflang): Verify storage creation had no errors // TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage); 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); gl::Error error = setCompleteTexStorage(storage);
if (error.isError()) if (error.isError())
...@@ -1524,8 +1527,23 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora ...@@ -1524,8 +1527,23 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora
// use existing storage level count, when previously specified by TexStorage*D // use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); 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 // 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); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -2829,9 +2829,9 @@ TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool r ...@@ -2829,9 +2829,9 @@ TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool r
return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); 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) TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
......
...@@ -155,7 +155,7 @@ class Renderer11 : public RendererD3D ...@@ -155,7 +155,7 @@ class Renderer11 : public RendererD3D
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); 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 *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); virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
......
...@@ -50,7 +50,7 @@ class TextureStorage11 : public TextureStorage ...@@ -50,7 +50,7 @@ class TextureStorage11 : public TextureStorage
virtual bool isRenderTarget() const; virtual bool isRenderTarget() const;
virtual bool isManaged() const; virtual bool isManaged() const;
virtual int getLevelCount() 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); gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
void invalidateSwizzleCacheLevel(int mipLevel); void invalidateSwizzleCacheLevel(int mipLevel);
...@@ -201,23 +201,32 @@ class TextureStorage11_2D : public TextureStorage11 ...@@ -201,23 +201,32 @@ class TextureStorage11_2D : public TextureStorage11
class TextureStorage11_Cube : public TextureStorage11 class TextureStorage11_Cube : public TextureStorage11
{ {
public: 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(); virtual ~TextureStorage11_Cube();
static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
virtual gl::Error getResource(ID3D11Resource **outResource); 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 getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual gl::Error copyToStorage(TextureStorage *destStorage);
virtual void associateImage(Image11* image, const gl::ImageIndex &index); virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
virtual bool isAssociatedImageValid(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 releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
protected: protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error ensureTextureExists(int mipLevels);
private: private:
DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
...@@ -229,6 +238,11 @@ class TextureStorage11_Cube : public TextureStorage11 ...@@ -229,6 +238,11 @@ class TextureStorage11_Cube : public TextureStorage11
ID3D11Texture2D *mTexture; ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; 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; ID3D11Texture2D *mSwizzleTexture;
ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
......
...@@ -2832,9 +2832,9 @@ TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool re ...@@ -2832,9 +2832,9 @@ TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool re
return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); 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) TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
......
...@@ -164,7 +164,7 @@ class Renderer9 : public RendererD3D ...@@ -164,7 +164,7 @@ class Renderer9 : public RendererD3D
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); 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 *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); 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) ...@@ -286,7 +286,7 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
return gl::Error(GL_NO_ERROR); 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)) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{ {
mTexture = NULL; mTexture = NULL;
......
...@@ -88,7 +88,7 @@ class TextureStorage9_2D : public TextureStorage9 ...@@ -88,7 +88,7 @@ class TextureStorage9_2D : public TextureStorage9
class TextureStorage9_Cube : public TextureStorage9 class TextureStorage9_Cube : public TextureStorage9
{ {
public: 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(); virtual ~TextureStorage9_Cube();
static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
......
#include "ANGLETest.h" #include "ANGLETest.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // 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> template<typename T>
class CubeMapTextureTest : public ANGLETest 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