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 ...@@ -355,6 +355,12 @@ struct FeaturesGL : FeatureSetBase
"Mac incorrectly executes both sides of && and || expressions when they should " "Mac incorrectly executes both sides of && and || expressions when they should "
"short-circuit.", "short-circuit.",
&members, "http://anglebug.com/482"}; &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; inline FeaturesGL::FeaturesGL() = default;
......
...@@ -262,6 +262,15 @@ ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *co ...@@ -262,6 +262,15 @@ ANGLE_INLINE angle::Result ContextGL::setDrawElementsState(const gl::Context *co
*outIndices = indices; *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) #if defined(ANGLE_STATE_VALIDATION_ENABLED)
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao); const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
vaoGL->validateState(); vaoGL->validateState();
......
...@@ -138,6 +138,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -138,6 +138,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mRasterizerDiscardEnabled(false), mRasterizerDiscardEnabled(false),
mLineWidth(1.0f), mLineWidth(1.0f),
mPrimitiveRestartEnabled(false), mPrimitiveRestartEnabled(false),
mPrimitiveRestartIndex(0),
mClearColor(0.0f, 0.0f, 0.0f, 0.0f), mClearColor(0.0f, 0.0f, 0.0f, 0.0f),
mClearDepth(1.0f), mClearDepth(1.0f),
mClearStencil(0), mClearStencil(0),
...@@ -1438,19 +1439,35 @@ void StateManagerGL::setPrimitiveRestartEnabled(bool enabled) ...@@ -1438,19 +1439,35 @@ void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
{ {
mPrimitiveRestartEnabled = enabled; mPrimitiveRestartEnabled = enabled;
GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
? GL_PRIMITIVE_RESTART
: GL_PRIMITIVE_RESTART_FIXED_INDEX;
if (mPrimitiveRestartEnabled) if (mPrimitiveRestartEnabled)
{ {
mFunctions->enable(GL_PRIMITIVE_RESTART_FIXED_INDEX); mFunctions->enable(cap);
} }
else else
{ {
mFunctions->disable(GL_PRIMITIVE_RESTART_FIXED_INDEX); mFunctions->disable(cap);
} }
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED); 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) void StateManagerGL::setClearDepth(float clearDepth)
{ {
if (mClearDepth != clearDepth) if (mClearDepth != clearDepth)
......
...@@ -122,6 +122,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -122,6 +122,7 @@ class StateManagerGL final : angle::NonCopyable
void setLineWidth(float width); void setLineWidth(float width);
void setPrimitiveRestartEnabled(bool enabled); void setPrimitiveRestartEnabled(bool enabled);
void setPrimitiveRestartIndex(GLuint index);
void setClearColor(const gl::ColorF &clearColor); void setClearColor(const gl::ColorF &clearColor);
void setClearDepth(float clearDepth); void setClearDepth(float clearDepth);
...@@ -328,6 +329,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -328,6 +329,7 @@ class StateManagerGL final : angle::NonCopyable
float mLineWidth; float mLineWidth;
bool mPrimitiveRestartEnabled; bool mPrimitiveRestartEnabled;
GLuint mPrimitiveRestartIndex;
gl::ColorF mClearColor; gl::ColorF mClearColor;
float mClearDepth; float mClearDepth;
......
...@@ -1575,7 +1575,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ...@@ -1575,7 +1575,9 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
ANGLE_FEATURE_CONDITION(features, rgbDXT1TexturesSampleZeroAlpha, IsApple()); 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) void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
...@@ -1743,6 +1745,22 @@ std::string GetBufferBindingString(gl::BufferBinding bufferBinding) ...@@ -1743,6 +1745,22 @@ std::string GetBufferBindingString(gl::BufferBinding bufferBinding)
return os.str(); 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 } // namespace nativegl
const FunctionsGL *GetFunctionsGL(const gl::Context *context) const FunctionsGL *GetFunctionsGL(const gl::Context *context)
......
...@@ -108,6 +108,7 @@ bool UseTexImage3D(gl::TextureType textureType); ...@@ -108,6 +108,7 @@ bool UseTexImage3D(gl::TextureType textureType);
GLenum GetTextureBindingQuery(gl::TextureType textureType); GLenum GetTextureBindingQuery(gl::TextureType textureType);
GLenum GetBufferBindingQuery(gl::BufferBinding bufferBinding); GLenum GetBufferBindingQuery(gl::BufferBinding bufferBinding);
std::string GetBufferBindingString(gl::BufferBinding bufferBinding); std::string GetBufferBindingString(gl::BufferBinding bufferBinding);
GLuint GetPrimitiveRestartIndexForIndexType(gl::DrawElementsType type);
} // namespace nativegl } // namespace nativegl
bool CanMapBufferForRead(const FunctionsGL *functions); 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