Commit 215b37a6 by Austin Kinross Committed by Jamie Madill

Work around zero-LOD mipmap issue on D3D11 Feature Level 9_3

In OpenGL ES, it is possible to sample from level 0 of a mipmapped texture by setting GL_TEXTURE_MIN_FILTER to GL_NEAREST. This is possible in D3D9 and D3D11 Feature Level 10_0+ via various methods. It's not possible in D3D11 Feature Level 9_3, though. This change works around this restriction by creating two copies of each texture on 9_3. The textures are identical, except one has mipmaps and one doesn't. The D3D11 renderer figures out which texture to use at the right time, and keeps the textures in sync with each other as necessary. Note: each texture is only created when it's needed. It's possible that only one (or even neither) D3D texture will be created for a given GL texture. Change-Id: I3c17137b4f63b9158b3abf067ad8e5d5c49d2191 Reviewed-on: https://chromium-review.googlesource.com/234522Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent be0facc6
...@@ -27,11 +27,19 @@ struct Workarounds ...@@ -27,11 +27,19 @@ struct Workarounds
{ {
Workarounds() Workarounds()
: mrtPerfWorkaround(false), : mrtPerfWorkaround(false),
setDataFasterThanImageUpload(false) setDataFasterThanImageUpload(false),
zeroMaxLodWorkaround(false)
{} {}
bool mrtPerfWorkaround; bool mrtPerfWorkaround;
bool setDataFasterThanImageUpload; bool setDataFasterThanImageUpload;
// Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero, and ignore the other levels).
// D3D11 Feature Level 10+ does this by setting MaxLOD to 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE.
// There is no equivalent to this in D3D11 Feature Level 9_3.
// This causes problems when (for example) an application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST (i.e disables mipmaps).
// To work around this, D3D11 FL9_3 has to create two copies of the texture. The textures' level zeros are identical, but only one texture has mips.
bool zeroMaxLodWorkaround;
}; };
} }
......
...@@ -133,7 +133,7 @@ class RendererD3D : public Renderer ...@@ -133,7 +133,7 @@ class RendererD3D : public Renderer
virtual Image *createImage() = 0; virtual Image *createImage() = 0;
virtual gl::Error generateMipmap(Image *dest, Image *source) = 0; virtual gl::Error generateMipmap(Image *dest, Image *source) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 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) = 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;
......
...@@ -355,6 +355,16 @@ gl::Error TextureD3D::generateMipmaps() ...@@ -355,6 +355,16 @@ gl::Error TextureD3D::generateMipmaps()
// Set up proper mipmap chain in our Image array. // Set up proper mipmap chain in our Image array.
initMipmapsImages(); initMipmapsImages();
if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// Switch to using the mipmapped texture.
gl::Error error = getNativeTexture()->useLevelZeroWorkaroundTexture(false);
if (error.isError())
{
return error;
}
}
// 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));
...@@ -390,7 +400,12 @@ gl::Error TextureD3D::generateMipmaps() ...@@ -390,7 +400,12 @@ gl::Error TextureD3D::generateMipmaps()
} }
} }
bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget()); // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround.
// The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture.
// As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work.
// The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter).
// Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else.
bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround));
for (GLint layer = 0; layer < layerCount; ++layer) for (GLint layer = 0; layer < layerCount; ++layer)
{ {
...@@ -815,7 +830,7 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna ...@@ -815,7 +830,7 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna
// 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->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels); TextureStorage *storage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels, false);
gl::Error error = setCompleteTexStorage(storage); gl::Error error = setCompleteTexStorage(storage);
if (error.isError()) if (error.isError())
...@@ -1010,8 +1025,22 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage ...@@ -1010,8 +1025,22 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage
// 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(width, height, 1)); GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
bool hintLevelZeroOnly = false;
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// 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)
{
hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
level += 1;
}
}
// TODO(geofflang): Determine if the texture creation succeeded // TODO(geofflang): Determine if the texture creation succeeded
*outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -51,6 +51,9 @@ class TextureStorage ...@@ -51,6 +51,9 @@ class TextureStorage
unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const;
unsigned int getTextureSerial() const; unsigned int getTextureSerial() const;
// This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it.
virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); }
protected: protected:
void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride);
......
...@@ -422,6 +422,16 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState ...@@ -422,6 +422,16 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState
samplerDesc.MinLOD = samplerState.minLod; samplerDesc.MinLOD = samplerState.minLod;
samplerDesc.MaxLOD = samplerState.maxLod; samplerDesc.MaxLOD = samplerState.maxLod;
if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
{
// Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX.
// Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves.
ASSERT(samplerState.maxLod >= 999.9f);
// Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this.
samplerDesc.MaxLOD = FLT_MAX;
}
ID3D11SamplerState *dx11SamplerState = NULL; ID3D11SamplerState *dx11SamplerState = NULL;
HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
if (FAILED(result) || !dx11SamplerState) if (FAILED(result) || !dx11SamplerState)
......
...@@ -2785,9 +2785,9 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) ...@@ -2785,9 +2785,9 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
return new TextureStorage11_2D(this, swapChain11); return new TextureStorage11_2D(this, swapChain11);
} }
TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
{ {
return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); 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)
...@@ -3306,7 +3306,7 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC ...@@ -3306,7 +3306,7 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC
Workarounds Renderer11::generateWorkarounds() const Workarounds Renderer11::generateWorkarounds() const
{ {
return d3d11::GenerateWorkarounds(); return d3d11::GenerateWorkarounds(mFeatureLevel);
} }
void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
......
...@@ -154,7 +154,7 @@ class Renderer11 : public RendererD3D ...@@ -154,7 +154,7 @@ class Renderer11 : public RendererD3D
virtual Image *createImage(); virtual Image *createImage();
gl::Error generateMipmap(Image *dest, Image *source) override; gl::Error generateMipmap(Image *dest, Image *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); 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);
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);
......
...@@ -77,6 +77,9 @@ class TextureStorage11 : public TextureStorage ...@@ -77,6 +77,9 @@ class TextureStorage11 : public TextureStorage
int getLevelHeight(int mipLevel) const; int getLevelHeight(int mipLevel) const;
int getLevelDepth(int mipLevel) const; int getLevelDepth(int mipLevel) const;
// Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV);
...@@ -142,23 +145,30 @@ class TextureStorage11_2D : public TextureStorage11 ...@@ -142,23 +145,30 @@ class TextureStorage11_2D : public TextureStorage11
{ {
public: public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
virtual ~TextureStorage11_2D(); virtual ~TextureStorage11_2D();
static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
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, RenderTarget **outRT); virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **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_2D); DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
...@@ -168,6 +178,20 @@ class TextureStorage11_2D : public TextureStorage11 ...@@ -168,6 +178,20 @@ class TextureStorage11_2D : public TextureStorage11
ID3D11Texture2D *mTexture; ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
// These are members related to the zero max-LOD workaround.
// D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero).
// These members are used to work around this limitation.
// Usually only mTexture XOR mLevelZeroTexture will exist.
// For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture.
// However, in some scenarios, both textures have to be created. This incurs additional memory overhead.
// One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture.
// A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap
// TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory.
ID3D11Texture2D *mLevelZeroTexture;
RenderTarget11 *mLevelZeroRenderTarget;
bool mUseLevelZeroTexture;
// Swizzle-related variables
ID3D11Texture2D *mSwizzleTexture; ID3D11Texture2D *mSwizzleTexture;
ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
......
...@@ -1136,11 +1136,12 @@ gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, ...@@ -1136,11 +1136,12 @@ gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment,
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
Workarounds GenerateWorkarounds() Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
{ {
Workarounds workarounds; Workarounds workarounds;
workarounds.mrtPerfWorkaround = true; workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = true; workarounds.setDataFasterThanImageUpload = true;
workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
return workarounds; return workarounds;
} }
......
...@@ -180,7 +180,7 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu ...@@ -180,7 +180,7 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu
gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT);
Workarounds GenerateWorkarounds(); Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel);
} }
......
...@@ -2826,7 +2826,7 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) ...@@ -2826,7 +2826,7 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
return new TextureStorage9_2D(this, swapChain9); return new TextureStorage9_2D(this, swapChain9);
} }
TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
{ {
return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
} }
......
...@@ -163,7 +163,7 @@ class Renderer9 : public RendererD3D ...@@ -163,7 +163,7 @@ class Renderer9 : public RendererD3D
virtual Image *createImage(); virtual Image *createImage();
gl::Error generateMipmap(Image *dest, Image *source) override; gl::Error generateMipmap(Image *dest, Image *source) override;
virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); 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);
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);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
'<(angle_path)/tests/angle_tests/InstancingTest.cpp', '<(angle_path)/tests/angle_tests/InstancingTest.cpp',
'<(angle_path)/tests/angle_tests/LineLoopTest.cpp', '<(angle_path)/tests/angle_tests/LineLoopTest.cpp',
'<(angle_path)/tests/angle_tests/MaxTextureSizeTest.cpp', '<(angle_path)/tests/angle_tests/MaxTextureSizeTest.cpp',
'<(angle_path)/tests/angle_tests/MipmapTest.cpp',
'<(angle_path)/tests/angle_tests/media/pixel.inl', '<(angle_path)/tests/angle_tests/media/pixel.inl',
'<(angle_path)/tests/angle_tests/OcclusionQueriesTest.cpp', '<(angle_path)/tests/angle_tests/OcclusionQueriesTest.cpp',
'<(angle_path)/tests/angle_tests/PBOExtensionTest.cpp', '<(angle_path)/tests/angle_tests/PBOExtensionTest.cpp',
......
...@@ -112,87 +112,6 @@ protected: ...@@ -112,87 +112,6 @@ protected:
GLint mTextureScaleUniformLocation; GLint mTextureScaleUniformLocation;
}; };
ANGLE_TYPED_TEST_CASE(TextureTestES3, ES3_D3D11);
template<typename T>
class TextureTestES3 : public TextureTest<T>
{
protected:
virtual void SetUp()
{
TextureTest::SetUp();
glGenTextures(1, &mTextureArray);
EXPECT_GL_NO_ERROR();
ASSERT_GL_NO_ERROR();
const std::string vertexShaderSource = SHADER_SOURCE
( #version 300 es\n
precision highp float;
in vec4 position;
out vec2 texcoord;
uniform vec2 textureScale;
void main()
{
gl_Position = vec4(position.xy * textureScale, 0.0, 1.0);
texcoord = (position.xy * 0.5) + 0.5;
}
);
const std::string fragmentShaderSourceArray = SHADER_SOURCE
( #version 300 es\n
precision highp float;
uniform sampler2DArray tex;
uniform int slice;
in vec2 texcoord;
out vec4 out_FragColor;
void main()
{
out_FragColor = texture(tex, vec3(texcoord, float(slice)));
}
);
mArrayProgram = CompileProgram(vertexShaderSource, fragmentShaderSourceArray);
if (mArrayProgram == 0)
{
FAIL() << "shader compilation failed.";
}
mTextureArrayUniformLocation = glGetUniformLocation(mArrayProgram, "tex");
ASSERT_NE(-1, mTextureArrayUniformLocation);
mTextureArrayScaleUniformLocation = glGetUniformLocation(mArrayProgram, "textureScale");
ASSERT_NE(-1, mTextureArrayScaleUniformLocation);
mTextureArraySliceUniformLocation = glGetUniformLocation(mArrayProgram, "slice");
ASSERT_NE(-1, mTextureArraySliceUniformLocation);
glUseProgram(mArrayProgram);
glUniform2f(mTextureArrayScaleUniformLocation, 1.0f, 1.0f);
glUseProgram(0);
ASSERT_GL_NO_ERROR();
}
virtual void TearDown()
{
glDeleteTextures(1, &mTextureArray);
glDeleteProgram(mArrayProgram);
TextureTest::TearDown();
}
GLuint mTextureArray;
GLuint mArrayProgram;
GLint mTextureArrayUniformLocation;
GLint mTextureArrayScaleUniformLocation;
GLint mTextureArraySliceUniformLocation;
};
TYPED_TEST(TextureTest, NegativeAPISubImage) TYPED_TEST(TextureTest, NegativeAPISubImage)
{ {
glBindTexture(GL_TEXTURE_2D, mTexture2D); glBindTexture(GL_TEXTURE_2D, mTexture2D);
...@@ -306,89 +225,6 @@ TYPED_TEST(TextureTest, MipmapsTwice) ...@@ -306,89 +225,6 @@ TYPED_TEST(TextureTest, MipmapsTwice)
EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255); EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
} }
// Creates a mipmapped 2D array texture with three layers, and calls ANGLE's GenerateMipmap.
// Then tests if the mipmaps are rendered correctly for all three layers.
TYPED_TEST(TextureTestES3, MipmapsForTextureArray)
{
int px = getWindowWidth() / 2;
int py = getWindowHeight() / 2;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, mTextureArray);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 5, GL_RGBA8, 16, 16, 3);
// Fill the first layer with red
std::vector<GLubyte> pixels(4 * 16 * 16);
for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
{
pixels[pixelId * 4 + 0] = 255;
pixels[pixelId * 4 + 1] = 0;
pixels[pixelId * 4 + 2] = 0;
pixels[pixelId * 4 + 3] = 255;
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
// Fill the second layer with green
for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
{
pixels[pixelId * 4 + 0] = 0;
pixels[pixelId * 4 + 1] = 255;
pixels[pixelId * 4 + 2] = 0;
pixels[pixelId * 4 + 3] = 255;
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
// Fill the third layer with blue
for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
{
pixels[pixelId * 4 + 0] = 0;
pixels[pixelId * 4 + 1] = 0;
pixels[pixelId * 4 + 2] = 255;
pixels[pixelId * 4 + 3] = 255;
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
EXPECT_GL_NO_ERROR();
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
EXPECT_GL_NO_ERROR();
glUseProgram(mArrayProgram);
glUniform1i(mTextureArrayUniformLocation, 0);
glUniform2f(mTextureScaleUniformLocation, 0.0625f, 0.0625f);
EXPECT_GL_NO_ERROR();
// Draw the first slice
glUseProgram(mArrayProgram);
glUniform1i(mTextureArraySliceUniformLocation, 0);
drawQuad(mArrayProgram, "position", 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(px, py, 255, 0, 0, 255);
// Draw the second slice
glUseProgram(mArrayProgram);
glUniform1i(mTextureArraySliceUniformLocation, 1);
drawQuad(mArrayProgram, "position", 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(px, py, 0, 255, 0, 255);
// Draw the third slice
glUseProgram(mArrayProgram);
glUniform1i(mTextureArraySliceUniformLocation, 2);
drawQuad(mArrayProgram, "position", 0.5f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(px, py, 0, 0, 255, 255);
}
// Test creating a FBO with a cube map render target, to test an ANGLE bug // Test creating a FBO with a cube map render target, to test an ANGLE bug
// https://code.google.com/p/angleproject/issues/detail?id=849 // https://code.google.com/p/angleproject/issues/detail?id=849
TYPED_TEST(TextureTest, CubeMapFBO) TYPED_TEST(TextureTest, CubeMapFBO)
......
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