Optimize ValidateBindTexture type check.

This switch can be cached in a very fast packed map. The map contents
only change if different extensions are exposed. This reduces the
number of instructions we hit in ValidateBindTexture.

Bug: angleproject:2763
Change-Id: I6ba8a4124d85e4c193d0dee3e03e50713d51b1f4
Reviewed-on: https://chromium-review.googlesource.com/c/1262739
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@google.com>
This commit is contained in:
Jamie Madill 2018-10-09 18:30:01 -04:00 коммит произвёл Commit Bot
Родитель 31116738ad
Коммит ac66f9822f
4 изменённых файлов: 96 добавлений и 55 удалений

Просмотреть файл

@ -110,8 +110,18 @@ class PackedEnumMap
constexpr bool empty() const noexcept { return mPrivateData.empty(); }
// element access:
reference operator[](E n) { return mPrivateData[static_cast<UnderlyingType>(n)]; }
const_reference operator[](E n) const { return mPrivateData[static_cast<UnderlyingType>(n)]; }
reference operator[](E n)
{
ASSERT(static_cast<size_t>(n) < mPrivateData.size());
return mPrivateData[static_cast<UnderlyingType>(n)];
}
const_reference operator[](E n) const
{
ASSERT(static_cast<size_t>(n) < mPrivateData.size());
return mPrivateData[static_cast<UnderlyingType>(n)];
}
const_reference at(E n) const { return mPrivateData.at(static_cast<UnderlyingType>(n)); }
reference at(E n) { return mPrivateData.at(static_cast<UnderlyingType>(n)); }

Просмотреть файл

@ -361,7 +361,6 @@ Context::Context(rx::EGLImplFactory *implFactory,
mWebGLContext(GetWebGLContext(attribs)),
mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
mMemoryProgramCache(memoryProgramCache),
mStateCache(this),
mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
@ -3430,6 +3429,9 @@ void Context::updateCaps()
}
mThreadPool = angle::WorkerThreadPool::Create(mExtensions.parallelShaderCompile);
// Reinitialize state cache after extension changes.
mStateCache.initialize(this);
}
void Context::initWorkarounds()
@ -7987,17 +7989,22 @@ GLenum ErrorSet::popError()
}
// StateCache implementation.
StateCache::StateCache(Context *context)
StateCache::StateCache()
: mCachedHasAnyEnabledClientAttrib(false),
mCachedNonInstancedVertexElementLimit(0),
mCachedInstancedVertexElementLimit(0),
mCachedBasicDrawStatesError(kInvalidPointer)
{
updateValidDrawModes(context);
}
StateCache::~StateCache() = default;
void StateCache::initialize(Context *context)
{
updateValidDrawModes(context);
updateValidBindTextureTypes(context);
}
void StateCache::updateActiveAttribsMask(Context *context)
{
bool isGLES1 = context->isGLES1();
@ -8209,4 +8216,24 @@ void StateCache::updateValidDrawModes(Context *context)
}};
}
}
void StateCache::updateValidBindTextureTypes(Context *context)
{
const Extensions &exts = context->getExtensions();
bool isGLES3 = context->getClientMajorVersion() >= 3;
bool isGLES31 = context->getClientVersion() >= Version(3, 1);
mCachedValidBindTextureTypes = {{
true, /* _2D */
isGLES3, /* _2DArray */
isGLES31, /* _2DMultisample */
exts.textureStorageMultisample2DArray, /* _2DMultisampleArray */
isGLES3, /* _3D */
exts.eglImageExternal || exts.eglStreamConsumerExternal, /* External */
exts.textureRectangle, /* Rectangle */
true, /* CubeMap */
false, /* InvalidEnum */
}};
}
} // namespace gl

Просмотреть файл

@ -92,9 +92,11 @@ class ErrorSet : angle::NonCopyable
class StateCache final : angle::NonCopyable
{
public:
StateCache(Context *context);
StateCache();
~StateCache();
void initialize(Context *context);
// Places that can trigger updateActiveAttribsMask:
// 1. onVertexArrayBindingChange.
// 2. onProgramExecutableChange.
@ -150,6 +152,12 @@ class StateCache final : angle::NonCopyable
return mCachedValidDrawModes[primitiveMode];
}
// Cannot change except on Context/Extension init.
bool isValidBindTextureType(TextureType type) const
{
return mCachedValidBindTextureTypes[type];
}
// State change notifications.
void onVertexArrayBindingChange(Context *context);
void onProgramExecutableChange(Context *context);
@ -174,6 +182,7 @@ class StateCache final : angle::NonCopyable
void updateVertexElementLimits(Context *context);
void updateBasicDrawStatesError();
void updateValidDrawModes(Context *context);
void updateValidBindTextureTypes(Context *context);
intptr_t getBasicDrawStatesErrorImpl(Context *context) const;
@ -187,9 +196,11 @@ class StateCache final : angle::NonCopyable
GLint64 mCachedInstancedVertexElementLimit;
mutable intptr_t mCachedBasicDrawStatesError;
// Reserve an extra slot at the end of the map for invalid enum.
// Reserve an extra slot at the end of these maps for invalid enum.
angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1>
mCachedValidDrawModes;
angle::PackedEnumMap<TextureType, bool, angle::EnumSize<TextureType>() + 1>
mCachedValidBindTextureTypes;
};
class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface

Просмотреть файл

@ -1110,6 +1110,44 @@ bool ValidDstBlendFunc(const Context *context, GLenum val)
return false;
}
void RecordBindTextureTypeError(Context *context, TextureType target)
{
ASSERT(!context->getStateCache().isValidBindTextureType(target));
switch (target)
{
case TextureType::Rectangle:
ASSERT(!context->getExtensions().textureRectangle);
context->handleError(InvalidEnum()
<< "Context does not support GL_ANGLE_texture_rectangle");
break;
case TextureType::_3D:
case TextureType::_2DArray:
ASSERT(context->getClientMajorVersion() < 3);
ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
break;
case TextureType::_2DMultisample:
ASSERT(context->getClientVersion() < Version(3, 1));
ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
break;
case TextureType::_2DMultisampleArray:
ASSERT(!context->getExtensions().textureStorageMultisample2DArray);
ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
break;
case TextureType::External:
ASSERT(!context->getExtensions().eglImageExternal &&
!context->getExtensions().eglStreamConsumerExternal);
context->handleError(InvalidEnum() << "External texture extension not enabled");
break;
default:
ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
}
}
} // anonymous namespace
bool ValidateES2TexImageParameters(Context *context,
@ -3044,54 +3082,9 @@ bool ValidateFlushMappedBufferRangeEXT(Context *context,
bool ValidateBindTexture(Context *context, TextureType target, GLuint texture)
{
switch (target)
if (!context->getStateCache().isValidBindTextureType(target))
{
case TextureType::_2D:
case TextureType::CubeMap:
break;
case TextureType::Rectangle:
if (!context->getExtensions().textureRectangle)
{
context->handleError(InvalidEnum()
<< "Context does not support GL_ANGLE_texture_rectangle");
return false;
}
break;
case TextureType::_3D:
case TextureType::_2DArray:
if (context->getClientMajorVersion() < 3)
{
ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
return false;
}
break;
case TextureType::_2DMultisample:
if (context->getClientVersion() < Version(3, 1))
{
ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
return false;
}
break;
case TextureType::_2DMultisampleArray:
if (!context->getExtensions().textureStorageMultisample2DArray)
{
ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
return false;
}
break;
case TextureType::External:
if (!context->getExtensions().eglImageExternal &&
!context->getExtensions().eglStreamConsumerExternal)
{
context->handleError(InvalidEnum() << "External texture extension not enabled");
return false;
}
break;
default:
ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
RecordBindTextureTypeError(context, target);
return false;
}