Commit c1551dc2 by Till Rathmann Committed by Commit Bot

D3D11 fix: Mipmapping was used although disabled via Sampler

When using a sampler the texture was created as if it has mipmaps, regardless what you specified in GL_TEXTURE_MIN_FILTER via glSamplerParameteri() -- mistakenly the default value GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was evaluated. If you didn't provide mipmaps and didn't let the driver generate them this led to not sampling your texture data when minification occurred. BUG=angleproject:2772 TEST=angle_end2end_tests.Texture2DTestES3.MinificationWithSamplerNoMipmapping Change-Id: I195147e208129c6fa8686bb0d9aea6931b2f20b1 Reviewed-on: https://chromium-review.googlesource.com/1175910 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 21e5e85a
......@@ -53,3 +53,4 @@ Andrei Volykhin
Jérôme Duval
Руслан Ижбулатов
Thomas Miller
Till Rathmann
......@@ -101,6 +101,7 @@ Sebastian Bergstein
James Ross-Gowan
Andrei Volykhin
Jérôme Duval
Till Rathmann
Microsoft Corporation
Cooper Partin
......
......@@ -2392,7 +2392,7 @@ angle::Result StateManager11::applyTextures(const gl::Context *context, gl::Shad
samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture, samplerState));
}
else
{
......@@ -2405,7 +2405,8 @@ angle::Result StateManager11::applyTextures(const gl::Context *context, gl::Shad
ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture,
incompleteTexture->getSamplerState()));
}
}
......@@ -2491,7 +2492,8 @@ angle::Result StateManager11::setSamplerState(const gl::Context *context,
angle::Result StateManager11::setTexture(const gl::Context *context,
gl::ShaderType type,
int index,
gl::Texture *texture)
gl::Texture *texture,
const gl::SamplerState &sampler)
{
ASSERT(type != gl::ShaderType::Compute);
const d3d11::SharedSRV *textureSRV = nullptr;
......@@ -2508,7 +2510,8 @@ angle::Result StateManager11::setTexture(const gl::Context *context,
TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
ANGLE_TRY(storage11->getSRVForSampler(context, texture->getTextureState(), &textureSRV));
ANGLE_TRY(
storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));
// If we get an invalid SRV here, something went wrong in the texture class and we're
// unexpectedly missing the shader resource view.
......
......@@ -300,7 +300,8 @@ class StateManager11 final : angle::NonCopyable
angle::Result setTexture(const gl::Context *context,
gl::ShaderType type,
int index,
gl::Texture *texture);
gl::Texture *texture,
const gl::SamplerState &sampler);
angle::Result setTextureForImage(const gl::Context *context,
gl::ShaderType type,
int index,
......
......@@ -210,12 +210,13 @@ UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
const gl::TextureState &textureState,
const gl::SamplerState &sampler,
const d3d11::SharedSRV **outSRV)
{
// Make sure to add the level offset for our tiny compressed texture workaround
const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
bool swizzleRequired = textureState.swizzleRequired();
bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState());
const bool swizzleRequired = textureState.swizzleRequired();
const bool mipmapping = gl::IsMipmapFiltered(sampler);
unsigned int mipLevels =
mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
......@@ -242,16 +243,16 @@ angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
// We drop the stencil when sampling from the SRV if three conditions hold:
// 1. the drop stencil workaround is enabled.
bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
const bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
// 2. this is a stencil texture.
bool hasStencil = (mFormatInfo.format().stencilBits > 0);
const bool hasStencil = (mFormatInfo.format().stencilBits > 0);
// 3. the texture has a 1x1 or 2x2 mip.
int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
bool hasSmallMips =
const int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
const bool hasSmallMips =
(getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
bool useDropStencil = (workaround && hasStencil && hasSmallMips);
SamplerKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
const bool useDropStencil = (workaround && hasStencil && hasSmallMips);
const SamplerKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
if (useDropStencil)
{
// Ensure drop texture gets created.
......@@ -260,7 +261,7 @@ angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
// Clear the SRV cache if necessary.
// TODO(jmadill): Re-use find query result.
auto srvEntry = mSrvCacheForSampler.find(key);
const auto srvEntry = mSrvCacheForSampler.find(key);
if (result == DropStencil::CREATED && srvEntry != mSrvCacheForSampler.end())
{
mSrvCacheForSampler.erase(key);
......@@ -1638,10 +1639,11 @@ angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
angle::Result TextureStorage11_EGLImage::getSRVForSampler(const gl::Context *context,
const gl::TextureState &textureState,
const gl::SamplerState &sampler,
const d3d11::SharedSRV **outSRV)
{
ANGLE_TRY(checkForUpdatedRenderTarget(context));
return TextureStorage11::getSRVForSampler(context, textureState, outSRV);
return TextureStorage11::getSRVForSampler(context, textureState, sampler, outSRV);
}
angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
......
......@@ -95,6 +95,7 @@ class TextureStorage11 : public TextureStorage
virtual angle::Result getSRVForSampler(const gl::Context *context,
const gl::TextureState &textureState,
const gl::SamplerState &sampler,
const d3d11::SharedSRV **outSRV);
angle::Result getSRVForImage(const gl::Context *context,
const gl::ImageUnit &imageUnit,
......@@ -393,6 +394,7 @@ class TextureStorage11_EGLImage final : public TextureStorage11
const TextureHelper11 **outResource) override;
angle::Result getSRVForSampler(const gl::Context *context,
const gl::TextureState &textureState,
const gl::SamplerState &sampler,
const d3d11::SharedSRV **outSRV) override;
angle::Result getMippedResource(const gl::Context *context,
const TextureHelper11 **outResource) override;
......
......@@ -1594,11 +1594,7 @@ TEST_P(Texture2DTest, TextureNPOT_GL_ALPHA_UBYTE)
glGenTextures(1, &tex2D);
glBindTexture(GL_TEXTURE_2D, tex2D);
std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize);
for (size_t pixelId = 0; pixelId < npotTexSize * npotTexSize; ++pixelId)
{
pixels[pixelId] = 64;
}
const std::vector<GLubyte> pixels(1 * npotTexSize * npotTexSize, 64);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
......@@ -3754,6 +3750,58 @@ TEST_P(Texture2DTestES3, GenerateMipmapAndBaseLevelLUMA)
EXPECT_PIXEL_COLOR_EQ(0, 0, angle::GLColor::white);
}
// Covers a bug in the D3D11 backend: http://anglebug.com/2772
// When using a sampler the texture was created as if it has mipmaps,
// regardless what you specified in GL_TEXTURE_MIN_FILTER via
// glSamplerParameteri() -- mistakenly the default value
// GL_NEAREST_MIPMAP_LINEAR or the value set via glTexParameteri() was
// evaluated.
// If you didn't provide mipmaps and didn't let the driver generate them
// this led to not sampling your texture data when minification occurred.
TEST_P(Texture2DTestES3, MinificationWithSamplerNoMipmapping)
{
const std::string vs =
"#version 300 es\n"
"out vec2 texcoord;\n"
"in vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.xy * 0.1, 0.0, 1.0);\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
"}\n";
const std::string fs =
"#version 300 es\n"
"precision highp float;\n"
"uniform highp sampler2D tex;\n"
"in vec2 texcoord;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
" fragColor = texture(tex, texcoord);\n"
"}\n";
ANGLE_GL_PROGRAM(program, vs, fs);
GLSampler sampler;
glBindSampler(0, sampler);
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
const GLsizei texWidth = getWindowWidth();
const GLsizei texHeight = getWindowHeight();
const std::vector<GLColor> whiteData(texWidth * texHeight, GLColor::white);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
whiteData.data());
EXPECT_GL_NO_ERROR();
drawQuad(program, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, angle::GLColor::white);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(Texture2DTest,
......
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