Commit 0b779a7c by Geoff Lang Committed by Commit Bot

GL: Emulate primitive restart when PRIMITIVE_RESTART_FIXED_INDEX is unavailable.

PRIMITIVE_RESTART_FIXED_INDEX isn't available until desktop GL 4.3. When it is not available, emulate it by enabling PRIMITIVE_RESTART and set the primitive restart index before each draw call based on the index type. TEST=deqp/functional/gles3/primitiverestart/* BUG=angleproject:3997 Change-Id: Id736f1056cb07da91c6d592693406333142e6265 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1853885 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com>
parent be1fa7d8
......@@ -355,6 +355,12 @@ struct FeaturesGL : FeatureSetBase
"Mac incorrectly executes both sides of && and || expressions when they should "
"short-circuit.",
&members, "http://anglebug.com/482"};
Feature emulatePrimitiveRestartFixedIndex = {
"emulate_primitive_restart_fixed_index", FeatureCategory::OpenGLWorkarounds,
"When GL_PRIMITIVE_RESTART_FIXED_INDEX is not available, emulate it with "
"GL_PRIMITIVE_RESTART and glPrimitiveRestartIndex.",
&members, "http://anglebug.com/3997"};
};
inline FeaturesGL::FeaturesGL() = default;
......
......@@ -262,6 +262,15 @@ ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *co
*outIndices = indices;
}
const angle::FeaturesGL &features = getFeaturesGL();
if (glState.isPrimitiveRestartEnabled() && features.emulatePrimitiveRestartFixedIndex.enabled)
{
StateManagerGL *stateManager = getStateManager();
GLuint primitiveRestartIndex = nativegl::GetPrimitiveRestartIndexForIndexType(type);
stateManager->setPrimitiveRestartIndex(primitiveRestartIndex);
}
#if defined(ANGLE_STATE_VALIDATION_ENABLED)
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
vaoGL->validateState();
......
......@@ -138,6 +138,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mRasterizerDiscardEnabled(false),
mLineWidth(1.0f),
mPrimitiveRestartEnabled(false),
mPrimitiveRestartIndex(0),
mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
mClearDepth(1.0f),
mClearStencil(0),
......@@ -1438,19 +1439,35 @@ void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
{
mPrimitiveRestartEnabled = enabled;
GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
? GL_PRIMITIVE_RESTART
: GL_PRIMITIVE_RESTART_FIXED_INDEX;
if (mPrimitiveRestartEnabled)
{
mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
mFunctions->enable(cap);
}
else
{
mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
mFunctions->disable(cap);
}
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
}
}
void StateManagerGL::setPrimitiveRestartIndex(GLuint index)
{
if (mPrimitiveRestartIndex != index)
{
mPrimitiveRestartIndex = index;
mFunctions->primitiveRestartIndex(index);
// No dirty bit for this state, it is not exposed to the frontend.
}
}
void StateManagerGL::setClearDepth(float clearDepth)
{
if (mClearDepth != clearDepth)
......
......@@ -122,6 +122,7 @@ class StateManagerGL final : angle::NonCopyable
void setLineWidth(float width);
void setPrimitiveRestartEnabled(bool enabled);
void setPrimitiveRestartIndex(GLuint index);
void setClearColor(const gl::ColorF &clearColor);
void setClearDepth(float clearDepth);
......@@ -328,6 +329,7 @@ class StateManagerGL final : angle::NonCopyable
float mLineWidth;
bool mPrimitiveRestartEnabled;
GLuint mPrimitiveRestartIndex;
gl::ColorF mClearColor;
float mClearDepth;
......
......@@ -1575,7 +1575,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
ANGLE_FEATURE_CONDITION(features, rgbDXT1TexturesSampleZeroAlpha, IsApple());
ANGLE_FEATURE_CONDITION(features, unfoldShortCircuits, IsApple());
ANGLE_FEATURE_CONDITION(
features, emulatePrimitiveRestartFixedIndex,
!functions->isAtLeastGL(gl::Version(4, 3)) && !functions->isAtLeastGLES(gl::Version(3, 0)));
}
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
......@@ -1743,6 +1745,22 @@ std::string GetBufferBindingString(gl::BufferBinding bufferBinding)
return os.str();
}
GLuint GetPrimitiveRestartIndexForIndexType(gl::DrawElementsType type)
{
switch (type)
{
case gl::DrawElementsType::UnsignedByte:
return std::numeric_limits<GLubyte>::max();
case gl::DrawElementsType::UnsignedShort:
return std::numeric_limits<GLushort>::max();
case gl::DrawElementsType::UnsignedInt:
return std::numeric_limits<GLuint>::max();
default:
UNREACHABLE();
return 0;
}
}
} // namespace nativegl
const FunctionsGL *GetFunctionsGL(const gl::Context *context)
......
......@@ -108,6 +108,7 @@ bool UseTexImage3D(gl::TextureType textureType);
GLenum GetTextureBindingQuery(gl::TextureType textureType);
GLenum GetBufferBindingQuery(gl::BufferBinding bufferBinding);
std::string GetBufferBindingString(gl::BufferBinding bufferBinding);
GLuint GetPrimitiveRestartIndexForIndexType(gl::DrawElementsType type);
} // namespace nativegl
bool CanMapBufferForRead(const FunctionsGL *functions);
......
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