Commit 18c6d628 by Geoff Lang Committed by Commit Bot

GL: Support VAOs without native VAOs.

Share the default VAO state between all frontend VAO when there is no native VAO support. Forcefully sync state every time a new frontend VAO is bound. Bug: angleproject:5577, chromium:1167179 Change-Id: Ieaedb5108ad28fc78e7e58b74495639c5246bb05 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2665266Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarPeng Huang <penghuang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent fe790824
......@@ -529,6 +529,12 @@ struct FeaturesGL : FeatureSetBase
"shift_instanced_array_data_with_offset", FeatureCategory::OpenGLWorkarounds,
"glDrawArraysInstanced is buggy on certain new Mac Intel GPUs", &members,
"http://crbug.com/1144207"};
// ANGLE needs to support devices that have no native VAOs. Sync everything to the default VAO.
Feature syncVertexArraysToDefault = {
"sync_vertex_arrays_to_default", FeatureCategory::OpenGLWorkarounds,
"Only use the default VAO because of missing support or driver bugs", &members,
"http://anglebug.com/5577"};
};
inline FeaturesGL::FeaturesGL() = default;
......
......@@ -256,9 +256,10 @@ BlitGL::~BlitGL()
mScratchFBO = 0;
}
if (mVAO != 0)
if (mOwnsVAOState)
{
mStateManager->deleteVertexArray(mVAO);
SafeDelete(mVAOState);
mVAO = 0;
}
}
......@@ -365,7 +366,7 @@ angle::Result BlitGL::copySubImageToLUMAWorkaroundTexture(const gl::Context *con
ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation, 0));
ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 0));
mStateManager->bindVertexArray(mVAO, 0);
ANGLE_TRY(setVAOState(context));
ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
// Copy the swizzled texture to the destination texture
......@@ -548,7 +549,7 @@ angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context,
mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destFramebuffer);
mStateManager->bindVertexArray(mVAO, 0);
ANGLE_TRY(setVAOState(context));
ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
ANGLE_TRY(scopedState.exit(context));
......@@ -663,7 +664,7 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context,
unpackUnmultiplyAlpha));
}
mStateManager->bindVertexArray(mVAO, 0);
ANGLE_TRY(setVAOState(context));
ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
*copySucceededOut = true;
......@@ -1075,7 +1076,7 @@ angle::Result BlitGL::generateSRGBMipmap(const gl::Context *context,
mStateManager->bindTexture(sourceType, source->getTextureID());
ANGLE_TRY(source->setMinFilter(context, GL_NEAREST));
mStateManager->bindVertexArray(mVAO, 0);
ANGLE_TRY(setVAOState(context));
ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
// Generate mipmaps on the linear texture
......@@ -1133,21 +1134,21 @@ angle::Result BlitGL::initializeResources(const gl::Context *context)
ANGLE_GL_TRY(context, mFunctions->bufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, vertexData,
GL_STATIC_DRAW));
VertexArrayStateGL *defaultVAOState = mStateManager->getDefaultVAOState();
if (!mFeatures.syncVertexArraysToDefault.enabled)
{
ANGLE_GL_TRY(context, mFunctions->genVertexArrays(1, &mVAO));
mStateManager->bindVertexArray(mVAO, 0);
mStateManager->bindBuffer(gl::BufferBinding::Array, mVertexBuffer);
// Enable all attributes with the same buffer so that it doesn't matter what location the
// texcoord attribute is assigned
GLint maxAttributes = 0;
ANGLE_GL_TRY(context, mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttributes));
for (GLint i = 0; i < maxAttributes; i++)
mVAOState = new VertexArrayStateGL(defaultVAOState->attributes.size(),
defaultVAOState->bindings.size());
mOwnsVAOState = true;
ANGLE_TRY(setVAOState(context));
ANGLE_TRY(initializeVAOState(context));
}
else
{
ANGLE_GL_TRY(context, mFunctions->enableVertexAttribArray(i));
ANGLE_GL_TRY(context,
mFunctions->vertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, 0, nullptr));
mVAO = mStateManager->getDefaultVAO();
mVAOState = defaultVAOState;
mOwnsVAOState = false;
}
constexpr GLenum potentialSRGBMipmapGenerationFormats[] = {
......@@ -1227,6 +1228,43 @@ angle::Result BlitGL::setScratchTextureParameter(const gl::Context *context,
return angle::Result::Continue;
}
angle::Result BlitGL::setVAOState(const gl::Context *context)
{
mStateManager->bindVertexArray(mVAO, mVAOState);
if (mFeatures.syncVertexArraysToDefault.enabled)
{
ANGLE_TRY(initializeVAOState(context));
}
return angle::Result::Continue;
}
angle::Result BlitGL::initializeVAOState(const gl::Context *context)
{
mStateManager->bindBuffer(gl::BufferBinding::Array, mVertexBuffer);
ANGLE_GL_TRY(context, mFunctions->enableVertexAttribArray(mTexcoordAttribLocation));
ANGLE_GL_TRY(context, mFunctions->vertexAttribPointer(mTexcoordAttribLocation, 2, GL_FLOAT,
GL_FALSE, 0, nullptr));
VertexAttributeGL &attribute = mVAOState->attributes[mTexcoordAttribLocation];
attribute.enabled = true;
attribute.format = &angle::Format::Get(angle::FormatID::R32G32_FLOAT);
attribute.pointer = nullptr;
VertexBindingGL &binding = mVAOState->bindings[mTexcoordAttribLocation];
binding.stride = 8;
binding.offset = 0;
binding.buffer = mVertexBuffer;
if (mFeatures.syncVertexArraysToDefault.enabled)
{
mStateManager->setDefaultVAOStateDirty();
}
return angle::Result::Continue;
}
angle::Result BlitGL::getBlitProgram(const gl::Context *context,
gl::TextureType sourceTextureType,
GLenum sourceComponentType,
......@@ -1242,6 +1280,7 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context,
// Depending on what types need to be output by the shaders, different versions need to be
// used.
constexpr const char *texcoordAttribName = "a_texcoord";
std::string version;
std::string vsInputVariableQualifier;
std::string vsOutputVariableQualifier;
......@@ -1282,15 +1321,17 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context,
// Compile the vertex shader
std::ostringstream vsSourceStream;
vsSourceStream << "#version " << version << "\n";
vsSourceStream << vsInputVariableQualifier << " vec2 a_texcoord;\n";
vsSourceStream << vsInputVariableQualifier << " vec2 " << texcoordAttribName << ";\n";
vsSourceStream << "uniform vec2 u_scale;\n";
vsSourceStream << "uniform vec2 u_offset;\n";
vsSourceStream << vsOutputVariableQualifier << " vec2 v_texcoord;\n";
vsSourceStream << "\n";
vsSourceStream << "void main()\n";
vsSourceStream << "{\n";
vsSourceStream << " gl_Position = vec4((a_texcoord * 2.0) - 1.0, 0.0, 1.0);\n";
vsSourceStream << " v_texcoord = a_texcoord * u_scale + u_offset;\n";
vsSourceStream << " gl_Position = vec4((" << texcoordAttribName
<< " * 2.0) - 1.0, 0.0, 1.0);\n";
vsSourceStream << " v_texcoord = " << texcoordAttribName
<< " * u_scale + u_offset;\n";
vsSourceStream << "}\n";
std::string vsSourceStr = vsSourceStream.str();
......@@ -1477,6 +1518,8 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context,
ANGLE_GL_TRY(context, mFunctions->deleteShader(fs));
}
ANGLE_GL_TRY(context, mFunctions->bindAttribLocation(
result.program, mTexcoordAttribLocation, texcoordAttribName));
ANGLE_GL_TRY(context, mFunctions->linkProgram(result.program));
ANGLE_TRY(CheckLinkStatus(context, mFunctions, result.program));
......
......@@ -36,6 +36,7 @@ class FunctionsGL;
class RenderbufferGL;
class StateManagerGL;
class TextureGL;
struct VertexArrayStateGL;
class BlitGL : angle::NonCopyable
{
......@@ -168,6 +169,8 @@ class BlitGL : angle::NonCopyable
angle::Result setScratchTextureParameter(const gl::Context *context,
GLenum param,
GLenum value);
angle::Result setVAOState(const gl::Context *context);
angle::Result initializeVAOState(const gl::Context *context);
const FunctionsGL *mFunctions;
const angle::FeaturesGL &mFeatures;
......@@ -195,11 +198,15 @@ class BlitGL : angle::NonCopyable
using BlitProgramType = std::tuple<gl::TextureType, GLenum, GLenum>;
std::map<BlitProgramType, BlitProgram> mBlitPrograms;
GLuint mScratchTextures[2];
GLuint mScratchFBO;
GLuint mScratchTextures[2] = {0};
GLuint mScratchFBO = 0;
GLuint mVAO;
GLuint mVertexBuffer;
GLuint mVAO = 0;
VertexArrayStateGL *mVAOState = nullptr;
bool mOwnsVAOState = false;
const GLuint mTexcoordAttribLocation = 0;
GLuint mVertexBuffer = 0;
nativegl::TexImageFormat mSRGBMipmapGenerationFormat;
};
......
......@@ -115,12 +115,23 @@ BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data)
{
const angle::FeaturesGL &features = getFeaturesGL();
if (features.syncVertexArraysToDefault.enabled)
{
StateManagerGL *stateManager = getStateManager();
return new VertexArrayGL(data, stateManager->getDefaultVAO(),
stateManager->getDefaultVAOState());
}
else
{
const FunctionsGL *functions = getFunctions();
GLuint vao = 0;
functions->genVertexArrays(1, &vao);
return new VertexArrayGL(data, vao);
}
}
QueryImpl *ContextGL::createQuery(gl::QueryType type)
......
......@@ -56,6 +56,17 @@ static void ValidateStateHelper(const FunctionsGL *functions,
} // anonymous namespace
VertexArrayStateGL::VertexArrayStateGL(size_t maxAttribs, size_t maxBindings)
: attributes(std::min<size_t>(maxAttribs, gl::MAX_VERTEX_ATTRIBS)),
bindings(std::min<size_t>(maxBindings, gl::MAX_VERTEX_ATTRIBS))
{
// Set the cached vertex attribute array and vertex attribute binding array size
for (GLuint i = 0; i < attributes.size(); i++)
{
attributes[i].bindingIndex = i;
}
}
StateManagerGL::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}
StateManagerGL::StateManagerGL(const FunctionsGL *functions,
......@@ -67,6 +78,8 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mProgram(0),
mVAO(0),
mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
mDefaultVAOState(rendererCaps.maxVertexAttributes, rendererCaps.maxVertexAttribBindings),
mVAOState(&mDefaultVAOState),
mBuffers(),
mIndexedBuffers(),
mTextureUnitIndex(0),
......@@ -182,9 +195,26 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mFunctions->primitiveRestartIndex(primitiveRestartIndex);
mPrimitiveRestartIndex = primitiveRestartIndex;
}
// It's possible we've enabled the emulated VAO feature for testing but we're on a core profile.
// Use a generated VAO as the default VAO so we can still test.
if (features.syncVertexArraysToDefault.enabled &&
!nativegl::CanUseDefaultVertexArrayObject(mFunctions))
{
ASSERT(nativegl::SupportsVertexArrayObjects(mFunctions));
mFunctions->genVertexArrays(1, &mDefaultVAO);
mFunctions->bindVertexArray(mDefaultVAO);
mVAO = mDefaultVAO;
}
}
StateManagerGL::~StateManagerGL() {}
StateManagerGL::~StateManagerGL()
{
if (mDefaultVAO != 0)
{
mFunctions->deleteVertexArrays(1, &mDefaultVAO);
}
}
void StateManagerGL::deleteProgram(GLuint program)
{
......@@ -205,7 +235,7 @@ void StateManagerGL::deleteVertexArray(GLuint vao)
{
if (mVAO == vao)
{
bindVertexArray(0, 0);
bindVertexArray(0, &mDefaultVAOState);
}
mFunctions->deleteVertexArrays(1, &vao);
}
......@@ -281,6 +311,22 @@ void StateManagerGL::deleteBuffer(GLuint buffer)
}
}
if (mVAOState)
{
if (mVAOState->elementArrayBuffer == buffer)
{
mVAOState->elementArrayBuffer = 0;
}
for (VertexBindingGL &binding : mVAOState->bindings)
{
if (binding.buffer == buffer)
{
binding.buffer = 0;
}
}
}
mFunctions->deleteBuffers(1, &buffer);
}
......@@ -360,12 +406,17 @@ void StateManagerGL::forceUseProgram(GLuint program)
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING);
}
void StateManagerGL::bindVertexArray(GLuint vao, GLuint elementArrayBuffer)
void StateManagerGL::bindVertexArray(GLuint vao, VertexArrayStateGL *vaoState)
{
ASSERT(vaoState);
if (mVAO != vao)
{
ASSERT(!mFeatures.syncVertexArraysToDefault.enabled);
mVAO = vao;
mBuffers[gl::BufferBinding::ElementArray] = elementArrayBuffer;
mVAOState = vaoState;
mBuffers[gl::BufferBinding::ElementArray] = vaoState ? vaoState->elementArrayBuffer : 0;
mFunctions->bindVertexArray(vao);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
......@@ -1957,11 +2008,37 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
{
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID());
VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());
propagateProgramToVAO(context, state.getProgram(),
GetImplAs<VertexArrayGL>(state.getVertexArray()));
if (mFeatures.syncVertexArraysToDefault.enabled)
{
// Re-sync the vertex array because all frontend VAOs share the same backend
// state. Only sync bits that can be set in ES2.0 or 3.0
gl::VertexArray::DirtyBits dirtyBits;
gl::VertexArray::DirtyAttribBitsArray dirtyAttribBits;
gl::VertexArray::DirtyBindingBitsArray dirtBindingBits;
dirtyBits.set(gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
for (size_t attrib = 0; attrib < mDefaultVAOState.attributes.size(); attrib++)
{
dirtyBits.set(gl::VertexArray::DIRTY_BIT_ATTRIB_0 + attrib);
dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_ENABLED);
dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER);
dirtyAttribBits[attrib].set(gl::VertexArray::DIRTY_ATTRIB_POINTER_BUFFER);
}
for (size_t binding = 0; binding < mDefaultVAOState.bindings.size(); binding++)
{
dirtyBits.set(gl::VertexArray::DIRTY_BIT_BINDING_0 + binding);
dirtBindingBits[binding].set(gl::VertexArray::DIRTY_BINDING_DIVISOR);
}
ANGLE_TRY(
vaoGL->syncState(context, dirtyBits, &dirtyAttribBits, &dirtBindingBits));
}
break;
}
case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
......@@ -2422,6 +2499,16 @@ void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
}
}
GLuint StateManagerGL::getDefaultVAO() const
{
return mDefaultVAO;
}
VertexArrayStateGL *StateManagerGL::getDefaultVAOState()
{
return &mDefaultVAOState;
}
void StateManagerGL::validateState() const
{
// Current program
......@@ -3070,4 +3157,9 @@ void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &exte
bindVertexArray(state->vertexArrayBinding, 0);
}
void StateManagerGL::setDefaultVAOStateDirty()
{
mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
}
} // namespace rx
......@@ -115,6 +115,36 @@ struct ExternalContextState
GLenum vertexArrayBinding;
};
struct VertexAttributeGL
{
bool enabled = false;
const angle::Format *format = &angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT);
const void *pointer = nullptr;
GLuint relativeOffset = 0;
GLuint bindingIndex = 0;
};
struct VertexBindingGL
{
GLuint stride = 16;
GLuint divisor = 0;
GLintptr offset = 0;
GLuint buffer = 0;
};
struct VertexArrayStateGL
{
VertexArrayStateGL(size_t maxAttribs, size_t maxBindings);
GLuint elementArrayBuffer = 0;
angle::FixedVector<VertexAttributeGL, gl::MAX_VERTEX_ATTRIBS> attributes;
angle::FixedVector<VertexBindingGL, gl::MAX_VERTEX_ATTRIBS> bindings;
};
class StateManagerGL final : angle::NonCopyable
{
public:
......@@ -135,7 +165,7 @@ class StateManagerGL final : angle::NonCopyable
void useProgram(GLuint program);
void forceUseProgram(GLuint program);
void bindVertexArray(GLuint vao, GLuint elementArrayBuffer);
void bindVertexArray(GLuint vao, VertexArrayStateGL *vaoState);
void bindBuffer(gl::BufferBinding target, GLuint buffer);
void bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer);
void bindBufferRange(gl::BufferBinding target,
......@@ -262,6 +292,10 @@ class StateManagerGL final : angle::NonCopyable
bool getHasSeparateFramebufferBindings() const { return mHasSeparateFramebufferBindings; }
GLuint getDefaultVAO() const;
VertexArrayStateGL *getDefaultVAOState();
void setDefaultVAOStateDirty();
void validateState() const;
void syncFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state);
......@@ -338,6 +372,17 @@ class StateManagerGL final : angle::NonCopyable
GLuint mVAO;
std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues;
GLuint mDefaultVAO = 0;
// The current state of the default VAO is owned by StateManagerGL. It may be shared between
// multiple VertexArrayGL objects if the native driver does not support vertex array objects.
// When this object is shared, StateManagerGL forces VertexArrayGL to resynchronize itself every
// time a new vertex array is bound.
VertexArrayStateGL mDefaultVAOState;
// The state of the currently bound vertex array object so StateManagerGL can know about the
// current element array buffer.
VertexArrayStateGL *mVAOState = nullptr;
angle::PackedEnumMap<gl::BufferBinding, GLuint> mBuffers;
struct IndexedBufferBinding
......
......@@ -20,11 +20,13 @@ namespace rx
class FunctionsGL;
class StateManagerGL;
struct VertexArrayStateGL;
class VertexArrayGL : public VertexArrayImpl
{
public:
VertexArrayGL(const gl::VertexArrayState &data, GLuint id);
VertexArrayGL(const gl::VertexArrayState &data, GLuint id, VertexArrayStateGL *sharedState);
~VertexArrayGL() override;
void destroy(const gl::Context *context) override;
......@@ -44,7 +46,7 @@ class VertexArrayGL : public VertexArrayImpl
const void **outIndices) const;
GLuint getVertexArrayID() const;
GLuint getAppliedElementArrayBufferID() const;
VertexArrayStateGL *getNativeState() const;
angle::Result syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits,
......@@ -123,23 +125,24 @@ class VertexArrayGL : public VertexArrayImpl
const gl::Context *context,
gl::AttributesMask *attributeMask) const;
GLuint mVertexArrayID;
int mAppliedNumViews;
GLuint mVertexArrayID = 0;
int mAppliedNumViews = 1;
// Remember the program's active attrib location mask so that attributes can be enabled/disabled
// based on whether they are active in the program
gl::AttributesMask mProgramActiveAttribLocationsMask;
mutable gl::BindingPointer<gl::Buffer> mAppliedElementArrayBuffer;
bool mOwnsNativeState = false;
VertexArrayStateGL *mNativeState = nullptr;
mutable std::vector<gl::VertexAttribute> mAppliedAttributes;
mutable std::vector<gl::VertexBinding> mAppliedBindings;
mutable gl::BindingPointer<gl::Buffer> mElementArrayBuffer;
mutable std::array<gl::BindingPointer<gl::Buffer>, gl::MAX_VERTEX_ATTRIBS> mArrayBuffers;
mutable size_t mStreamingElementArrayBufferSize;
mutable GLuint mStreamingElementArrayBuffer;
mutable size_t mStreamingElementArrayBufferSize = 0;
mutable GLuint mStreamingElementArrayBuffer = 0;
mutable size_t mStreamingArrayBufferSize;
mutable GLuint mStreamingArrayBuffer;
mutable size_t mStreamingArrayBufferSize = 0;
mutable GLuint mStreamingArrayBuffer = 0;
// Used for Mac Intel instanced draw workaround
mutable gl::AttributesMask mForcedStreamingAttributesForDrawArraysInstancedMask;
......
......@@ -1309,6 +1309,13 @@ void GenerateCaps(const FunctionsGL *functions,
LimitVersion(maxSupportedESVersion, gl::Version(3, 1));
}
if (!nativegl::SupportsVertexArrayObjects(functions) ||
features.syncVertexArraysToDefault.enabled)
{
// ES 3.1 vertex bindings are not emulated on the default vertex array
LimitVersion(maxSupportedESVersion, gl::Version(3, 0));
}
// Extension support
extensions->setTextureExtensionSupport(*textureCapsMap);
extensions->textureCompressionASTCHDRKHR =
......@@ -2080,6 +2087,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
// now.
ANGLE_FEATURE_CONDITION(features, shiftInstancedArrayDataWithExtraOffset,
IsApple() && IsIntel(vendor) && !IsHaswell(device));
ANGLE_FEATURE_CONDITION(features, syncVertexArraysToDefault,
!nativegl::SupportsVertexArrayObjects(functions));
}
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
......@@ -2112,6 +2121,20 @@ void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::Featur
namespace nativegl
{
bool SupportsVertexArrayObjects(const FunctionsGL *functions)
{
return functions->isAtLeastGLES(gl::Version(3, 0)) ||
functions->hasGLESExtension("GL_OES_vertex_array_object") ||
functions->isAtLeastGL(gl::Version(3, 0)) ||
functions->hasGLExtension("GL_ARB_vertex_array_object");
}
bool CanUseDefaultVertexArrayObject(const FunctionsGL *functions)
{
return (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) == 0;
}
bool SupportsCompute(const FunctionsGL *functions)
{
// OpenGL 4.2 is required for GL_ARB_compute_shader, some platform drivers have the extension,
......
......@@ -113,6 +113,8 @@ void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::Featur
namespace nativegl
{
bool SupportsVertexArrayObjects(const FunctionsGL *functions);
bool CanUseDefaultVertexArrayObject(const FunctionsGL *functions);
bool SupportsCompute(const FunctionsGL *functions);
bool SupportsFenceSync(const FunctionsGL *functions);
bool SupportsOcclusionQueries(const FunctionsGL *functions);
......
......@@ -3631,6 +3631,15 @@ void main()
}
}
// VAO emulation fails on Mac but is not used on Mac in the wild. http://anglebug.com/5577
#if !defined(__APPLE__)
# define EMULATED_VAO_CONFIGS \
WithEmulatedVAOs(ES2_OPENGL()), WithEmulatedVAOs(ES2_OPENGLES()), \
WithEmulatedVAOs(ES3_OPENGL()), WithEmulatedVAOs(ES3_OPENGLES()),
#else
# define EMULATED_VAO_CONFIGS
#endif
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
// D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels
......@@ -3642,7 +3651,8 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
/* cheapRenderPass */ true),
WithMetalMemoryBarrierAndCheapRenderPass(ES3_METAL(),
/* hasBarrier */ false,
/* cheapRenderPass */ false));
/* cheapRenderPass */ false),
EMULATED_VAO_CONFIGS);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
VertexAttributeOORTest,
......
......@@ -268,6 +268,11 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
stream << "_NoVulkanViewportFlip";
}
if (pp.eglParameters.emulatedVAOs == EGL_TRUE)
{
stream << "_EmulatedVAOs";
}
return stream;
}
......
......@@ -289,6 +289,14 @@ inline PlatformParameters WithNoVulkanViewportFlip(const PlatformParameters &par
withoutVulkanViewportFlip.eglParameters.supportsVulkanViewportFlip = EGL_FALSE;
return withoutVulkanViewportFlip;
}
inline PlatformParameters WithEmulatedVAOs(const PlatformParameters &params)
{
PlatformParameters emualtedVAOParams = params;
emualtedVAOParams.eglParameters.emulatedVAOs = EGL_TRUE;
return emualtedVAOParams;
}
} // namespace angle
#endif // ANGLE_TEST_CONFIGS_H_
......@@ -64,7 +64,7 @@ struct EGLPlatformParameters
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
robustness, emulatedPrerotation, asyncCommandQueueFeatureVulkan,
hasExplicitMemBarrierFeatureMtl, hasCheapRenderPassFeatureMtl,
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip);
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip, emulatedVAOs);
}
EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
......@@ -86,6 +86,7 @@ struct EGLPlatformParameters
EGLint hasCheapRenderPassFeatureMtl = EGL_DONT_CARE;
EGLint forceBufferGPUStorageFeatureMtl = EGL_DONT_CARE;
EGLint supportsVulkanViewportFlip = EGL_DONT_CARE;
EGLint emulatedVAOs = EGL_DONT_CARE;
angle::PlatformMethods *platformMethods = nullptr;
};
......
......@@ -263,6 +263,11 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
enabledFeatureOverrides.push_back("force_buffer_gpu_storage_mtl");
}
if (params.emulatedVAOs == EGL_TRUE)
{
enabledFeatureOverrides.push_back("sync_vertex_arrays_to_default");
}
const bool hasFeatureControlANGLE =
strstr(extensionString, "EGL_ANGLE_feature_control") != nullptr;
......
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