Commit 5fd08af4 by James Darpinian Committed by Commit Bot

Sampler state overrides texture state if set

The new validation added in http://crbug.com/809237 failed to consider that sampler object state overrides texture object state if a sampler object is bound. State caching makes this complicated to fix. Fixes WebGL conformance test incompatible-texture-type-for-sampler.html https://github.com/KhronosGroup/WebGL/pull/2823 Bug: 940080, 809237 Change-Id: I26b0fb35c5630c36248edae80f0298a0cb7e14b8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1522364 Commit-Queue: James Darpinian <jdarpinian@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent f7f15ac2
......@@ -1100,6 +1100,7 @@ void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerHandle);
mState.setSamplerBinding(this, textureUnit, sampler);
mSamplerObserverBindings[textureUnit].bind(sampler);
mStateCache.onActiveTextureChange(this);
}
void Context::bindImageTexture(GLuint unit,
......@@ -8015,6 +8016,7 @@ void Context::onSubjectStateChange(const Context *context,
{
ASSERT(index < kSamplerMaxSubjectIndex);
mState.setSamplerDirty(index - kSampler0SubjectIndex);
mState.onActiveTextureStateChange(this, index - kSampler0SubjectIndex);
}
break;
}
......
......@@ -36,9 +36,10 @@ const std::string &Sampler::getLabel() const
return mLabel;
}
void Sampler::setMinFilter(GLenum minFilter)
void Sampler::setMinFilter(const Context *context, GLenum minFilter)
{
mState.setMinFilter(minFilter);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getMinFilter() const
......@@ -46,9 +47,10 @@ GLenum Sampler::getMinFilter() const
return mState.getMinFilter();
}
void Sampler::setMagFilter(GLenum magFilter)
void Sampler::setMagFilter(const Context *context, GLenum magFilter)
{
mState.setMagFilter(magFilter);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getMagFilter() const
......@@ -56,9 +58,10 @@ GLenum Sampler::getMagFilter() const
return mState.getMagFilter();
}
void Sampler::setWrapS(GLenum wrapS)
void Sampler::setWrapS(const Context *context, GLenum wrapS)
{
mState.setWrapS(wrapS);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getWrapS() const
......@@ -66,9 +69,10 @@ GLenum Sampler::getWrapS() const
return mState.getWrapS();
}
void Sampler::setWrapT(GLenum wrapT)
void Sampler::setWrapT(const Context *context, GLenum wrapT)
{
mState.setWrapT(wrapT);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getWrapT() const
......@@ -76,9 +80,10 @@ GLenum Sampler::getWrapT() const
return mState.getWrapT();
}
void Sampler::setWrapR(GLenum wrapR)
void Sampler::setWrapR(const Context *context, GLenum wrapR)
{
mState.setWrapR(wrapR);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getWrapR() const
......@@ -86,9 +91,10 @@ GLenum Sampler::getWrapR() const
return mState.getWrapR();
}
void Sampler::setMaxAnisotropy(float maxAnisotropy)
void Sampler::setMaxAnisotropy(const Context *context, float maxAnisotropy)
{
mState.setMaxAnisotropy(maxAnisotropy);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
float Sampler::getMaxAnisotropy() const
......@@ -96,9 +102,10 @@ float Sampler::getMaxAnisotropy() const
return mState.getMaxAnisotropy();
}
void Sampler::setMinLod(GLfloat minLod)
void Sampler::setMinLod(const Context *context, GLfloat minLod)
{
mState.setMinLod(minLod);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLfloat Sampler::getMinLod() const
......@@ -106,9 +113,10 @@ GLfloat Sampler::getMinLod() const
return mState.getMinLod();
}
void Sampler::setMaxLod(GLfloat maxLod)
void Sampler::setMaxLod(const Context *context, GLfloat maxLod)
{
mState.setMaxLod(maxLod);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLfloat Sampler::getMaxLod() const
......@@ -116,9 +124,10 @@ GLfloat Sampler::getMaxLod() const
return mState.getMaxLod();
}
void Sampler::setCompareMode(GLenum compareMode)
void Sampler::setCompareMode(const Context *context, GLenum compareMode)
{
mState.setCompareMode(compareMode);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getCompareMode() const
......@@ -126,9 +135,10 @@ GLenum Sampler::getCompareMode() const
return mState.getCompareMode();
}
void Sampler::setCompareFunc(GLenum compareFunc)
void Sampler::setCompareFunc(const Context *context, GLenum compareFunc)
{
mState.setCompareFunc(compareFunc);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getCompareFunc() const
......@@ -136,9 +146,10 @@ GLenum Sampler::getCompareFunc() const
return mState.getCompareFunc();
}
void Sampler::setSRGBDecode(GLenum sRGBDecode)
void Sampler::setSRGBDecode(const Context *context, GLenum sRGBDecode)
{
mState.setSRGBDecode(sRGBDecode);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
GLenum Sampler::getSRGBDecode() const
......@@ -146,9 +157,10 @@ GLenum Sampler::getSRGBDecode() const
return mState.getSRGBDecode();
}
void Sampler::setBorderColor(const ColorGeneric &color)
void Sampler::setBorderColor(const Context *context, const ColorGeneric &color)
{
mState.setBorderColor(color);
onStateChange(context, angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
}
const ColorGeneric &Sampler::getBorderColor() const
......
......@@ -35,40 +35,40 @@ class Sampler final : public RefCountObject, public LabeledObject, public angle:
void setLabel(const Context *context, const std::string &label) override;
const std::string &getLabel() const override;
void setMinFilter(GLenum minFilter);
void setMinFilter(const Context *context, GLenum minFilter);
GLenum getMinFilter() const;
void setMagFilter(GLenum magFilter);
void setMagFilter(const Context *context, GLenum magFilter);
GLenum getMagFilter() const;
void setWrapS(GLenum wrapS);
void setWrapS(const Context *context, GLenum wrapS);
GLenum getWrapS() const;
void setWrapT(GLenum wrapT);
void setWrapT(const Context *context, GLenum wrapT);
GLenum getWrapT() const;
void setWrapR(GLenum wrapR);
void setWrapR(const Context *context, GLenum wrapR);
GLenum getWrapR() const;
void setMaxAnisotropy(float maxAnisotropy);
void setMaxAnisotropy(const Context *context, float maxAnisotropy);
float getMaxAnisotropy() const;
void setMinLod(GLfloat minLod);
void setMinLod(const Context *context, GLfloat minLod);
GLfloat getMinLod() const;
void setMaxLod(GLfloat maxLod);
void setMaxLod(const Context *context, GLfloat maxLod);
GLfloat getMaxLod() const;
void setCompareMode(GLenum compareMode);
void setCompareMode(const Context *context, GLenum compareMode);
GLenum getCompareMode() const;
void setCompareFunc(GLenum compareFunc);
void setCompareFunc(const Context *context, GLenum compareFunc);
GLenum getCompareFunc() const;
void setSRGBDecode(GLenum sRGBDecode);
void setSRGBDecode(const Context *context, GLenum sRGBDecode);
GLenum getSRGBDecode() const;
void setBorderColor(const ColorGeneric &color);
void setBorderColor(const Context *context, const ColorGeneric &color);
const ColorGeneric &getBorderColor() const;
const SamplerState &getSamplerState() const;
......
......@@ -540,7 +540,8 @@ ANGLE_INLINE void State::updateActiveTextureState(const Context *context,
mTexturesIncompatibleWithSamplers[textureIndex] =
!texture->getTextureState().compatibleWithSamplerFormat(
mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex));
mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex),
sampler ? sampler->getSamplerState() : texture->getSamplerState());
mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
}
......@@ -1184,6 +1185,7 @@ void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sample
// This is overly conservative as it assumes the sampler has never been bound.
setSamplerDirty(textureUnit);
onActiveTextureChange(context, textureUnit);
onActiveTextureStateChange(context, textureUnit);
}
void State::detachSampler(const Context *context, GLuint sampler)
......@@ -1192,12 +1194,11 @@ void State::detachSampler(const Context *context, GLuint sampler)
// If a sampler object that is currently bound to one or more texture units is
// deleted, it is as though BindSampler is called once for each texture unit to
// which the sampler is bound, with unit set to the texture unit and sampler set to zero.
for (BindingPointer<Sampler> &samplerBinding : mSamplers)
for (size_t i = 0; i < mSamplers.size(); i++)
{
if (samplerBinding.id() == sampler)
if (mSamplers[i].id() == sampler)
{
samplerBinding.set(context, nullptr);
mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
setSamplerBinding(context, i, nullptr);
}
}
}
......
......@@ -108,6 +108,7 @@ TextureState::TextureState(TextureType type)
mGenerateMipmapHint(GL_FALSE),
mInitState(InitState::MayNeedInit),
mCachedSamplerFormat(SamplerFormat::InvalidEnum),
mCachedSamplerCompareMode(GL_NONE),
mCachedSamplerFormatValid(false)
{}
......@@ -241,12 +242,12 @@ GLenum TextureState::getGenerateMipmapHint() const
return mGenerateMipmapHint;
}
SamplerFormat TextureState::computeRequiredSamplerFormat() const
SamplerFormat TextureState::computeRequiredSamplerFormat(const SamplerState &samplerState) const
{
const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
if ((baseImageDesc.format.info->format == GL_DEPTH_COMPONENT ||
baseImageDesc.format.info->format == GL_DEPTH_STENCIL) &&
mSamplerState.getCompareMode() != GL_NONE)
samplerState.getCompareMode() != GL_NONE)
{
return SamplerFormat::Shadow;
}
......
......@@ -111,11 +111,14 @@ class TextureState final : private angle::NonCopyable
bool isCubeComplete() const;
ANGLE_INLINE bool compatibleWithSamplerFormat(SamplerFormat format) const
ANGLE_INLINE bool compatibleWithSamplerFormat(SamplerFormat format,
const SamplerState &samplerState) const
{
if (!mCachedSamplerFormatValid)
if (!mCachedSamplerFormatValid ||
mCachedSamplerCompareMode != samplerState.getCompareMode())
{
mCachedSamplerFormat = computeRequiredSamplerFormat();
mCachedSamplerFormat = computeRequiredSamplerFormat(samplerState);
mCachedSamplerCompareMode = samplerState.getCompareMode();
mCachedSamplerFormatValid = true;
}
// Incomplete textures are compatible with any sampler format.
......@@ -152,7 +155,7 @@ class TextureState final : private angle::NonCopyable
bool computeSamplerCompleteness(const SamplerState &samplerState, const State &data) const;
bool computeMipmapCompleteness() const;
bool computeLevelCompleteness(TextureTarget target, size_t level) const;
SamplerFormat computeRequiredSamplerFormat() const;
SamplerFormat computeRequiredSamplerFormat(const SamplerState &samplerState) const;
TextureTarget getBaseImageTarget() const;
......@@ -200,6 +203,7 @@ class TextureState final : private angle::NonCopyable
InitState mInitState;
mutable SamplerFormat mCachedSamplerFormat;
mutable GLenum mCachedSamplerCompareMode;
mutable bool mCachedSamplerFormatValid;
};
......
......@@ -454,40 +454,40 @@ void SetSamplerParameterBase(Context *context,
switch (pname)
{
case GL_TEXTURE_WRAP_S:
sampler->setWrapS(ConvertToGLenum(pname, params[0]));
sampler->setWrapS(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_WRAP_T:
sampler->setWrapT(ConvertToGLenum(pname, params[0]));
sampler->setWrapT(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_WRAP_R:
sampler->setWrapR(ConvertToGLenum(pname, params[0]));
sampler->setWrapR(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_MIN_FILTER:
sampler->setMinFilter(ConvertToGLenum(pname, params[0]));
sampler->setMinFilter(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_MAG_FILTER:
sampler->setMagFilter(ConvertToGLenum(pname, params[0]));
sampler->setMagFilter(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
sampler->setMaxAnisotropy(CastQueryValueTo<GLfloat>(pname, params[0]));
sampler->setMaxAnisotropy(context, CastQueryValueTo<GLfloat>(pname, params[0]));
break;
case GL_TEXTURE_COMPARE_MODE:
sampler->setCompareMode(ConvertToGLenum(pname, params[0]));
sampler->setCompareMode(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_COMPARE_FUNC:
sampler->setCompareFunc(ConvertToGLenum(pname, params[0]));
sampler->setCompareFunc(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_MIN_LOD:
sampler->setMinLod(CastQueryValueTo<GLfloat>(pname, params[0]));
sampler->setMinLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
break;
case GL_TEXTURE_MAX_LOD:
sampler->setMaxLod(CastQueryValueTo<GLfloat>(pname, params[0]));
sampler->setMaxLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
sampler->setSRGBDecode(ConvertToGLenum(pname, params[0]));
sampler->setSRGBDecode(context, ConvertToGLenum(pname, params[0]));
break;
case GL_TEXTURE_BORDER_COLOR:
sampler->setBorderColor(ConvertToColor<isPureInteger>(params));
sampler->setBorderColor(context, ConvertToColor<isPureInteger>(params));
break;
default:
UNREACHABLE();
......
......@@ -2733,6 +2733,11 @@ const char *ValidateDrawStates(Context *context)
// Do some additonal WebGL-specific validation
if (extensions.webglCompatibility)
{
if (!state.validateSamplerFormats())
{
return kSamplerFormatMismatch;
}
const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
transformFeedbackObject->buffersBoundForOtherUse())
......
......@@ -3087,8 +3087,6 @@ void main()
// Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
{
// TODO(jdarpinian): Re-enable this test when fixing http://crbug.com/940080
ANGLE_SKIP_TEST_IF(true);
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
uniform sampler2D sampler;
......
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