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 ...@@ -529,6 +529,12 @@ struct FeaturesGL : FeatureSetBase
"shift_instanced_array_data_with_offset", FeatureCategory::OpenGLWorkarounds, "shift_instanced_array_data_with_offset", FeatureCategory::OpenGLWorkarounds,
"glDrawArraysInstanced is buggy on certain new Mac Intel GPUs", &members, "glDrawArraysInstanced is buggy on certain new Mac Intel GPUs", &members,
"http://crbug.com/1144207"}; "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; inline FeaturesGL::FeaturesGL() = default;
......
...@@ -256,9 +256,10 @@ BlitGL::~BlitGL() ...@@ -256,9 +256,10 @@ BlitGL::~BlitGL()
mScratchFBO = 0; mScratchFBO = 0;
} }
if (mVAO != 0) if (mOwnsVAOState)
{ {
mStateManager->deleteVertexArray(mVAO); mStateManager->deleteVertexArray(mVAO);
SafeDelete(mVAOState);
mVAO = 0; mVAO = 0;
} }
} }
...@@ -365,7 +366,7 @@ angle::Result BlitGL::copySubImageToLUMAWorkaroundTexture(const gl::Context *con ...@@ -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->multiplyAlphaLocation, 0));
ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 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)); ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
// Copy the swizzled texture to the destination texture // Copy the swizzled texture to the destination texture
...@@ -548,7 +549,7 @@ angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context, ...@@ -548,7 +549,7 @@ angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context,
mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destFramebuffer); 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_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
ANGLE_TRY(scopedState.exit(context)); ANGLE_TRY(scopedState.exit(context));
...@@ -663,7 +664,7 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context, ...@@ -663,7 +664,7 @@ angle::Result BlitGL::copySubTexture(const gl::Context *context,
unpackUnmultiplyAlpha)); unpackUnmultiplyAlpha));
} }
mStateManager->bindVertexArray(mVAO, 0); ANGLE_TRY(setVAOState(context));
ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3)); ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
*copySucceededOut = true; *copySucceededOut = true;
...@@ -1075,7 +1076,7 @@ angle::Result BlitGL::generateSRGBMipmap(const gl::Context *context, ...@@ -1075,7 +1076,7 @@ angle::Result BlitGL::generateSRGBMipmap(const gl::Context *context,
mStateManager->bindTexture(sourceType, source->getTextureID()); mStateManager->bindTexture(sourceType, source->getTextureID());
ANGLE_TRY(source->setMinFilter(context, GL_NEAREST)); 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)); ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
// Generate mipmaps on the linear texture // Generate mipmaps on the linear texture
...@@ -1133,21 +1134,21 @@ angle::Result BlitGL::initializeResources(const gl::Context *context) ...@@ -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, ANGLE_GL_TRY(context, mFunctions->bufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, vertexData,
GL_STATIC_DRAW)); GL_STATIC_DRAW));
ANGLE_GL_TRY(context, mFunctions->genVertexArrays(1, &mVAO)); VertexArrayStateGL *defaultVAOState = mStateManager->getDefaultVAOState();
if (!mFeatures.syncVertexArraysToDefault.enabled)
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++)
{ {
ANGLE_GL_TRY(context, mFunctions->enableVertexAttribArray(i)); ANGLE_GL_TRY(context, mFunctions->genVertexArrays(1, &mVAO));
ANGLE_GL_TRY(context, mVAOState = new VertexArrayStateGL(defaultVAOState->attributes.size(),
mFunctions->vertexAttribPointer(i, 2, GL_FLOAT, GL_FALSE, 0, nullptr)); defaultVAOState->bindings.size());
mOwnsVAOState = true;
ANGLE_TRY(setVAOState(context));
ANGLE_TRY(initializeVAOState(context));
}
else
{
mVAO = mStateManager->getDefaultVAO();
mVAOState = defaultVAOState;
mOwnsVAOState = false;
} }
constexpr GLenum potentialSRGBMipmapGenerationFormats[] = { constexpr GLenum potentialSRGBMipmapGenerationFormats[] = {
...@@ -1227,6 +1228,43 @@ angle::Result BlitGL::setScratchTextureParameter(const gl::Context *context, ...@@ -1227,6 +1228,43 @@ angle::Result BlitGL::setScratchTextureParameter(const gl::Context *context,
return angle::Result::Continue; 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, angle::Result BlitGL::getBlitProgram(const gl::Context *context,
gl::TextureType sourceTextureType, gl::TextureType sourceTextureType,
GLenum sourceComponentType, GLenum sourceComponentType,
...@@ -1242,6 +1280,7 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context, ...@@ -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 // Depending on what types need to be output by the shaders, different versions need to be
// used. // used.
constexpr const char *texcoordAttribName = "a_texcoord";
std::string version; std::string version;
std::string vsInputVariableQualifier; std::string vsInputVariableQualifier;
std::string vsOutputVariableQualifier; std::string vsOutputVariableQualifier;
...@@ -1282,15 +1321,17 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context, ...@@ -1282,15 +1321,17 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context,
// Compile the vertex shader // Compile the vertex shader
std::ostringstream vsSourceStream; std::ostringstream vsSourceStream;
vsSourceStream << "#version " << version << "\n"; 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_scale;\n";
vsSourceStream << "uniform vec2 u_offset;\n"; vsSourceStream << "uniform vec2 u_offset;\n";
vsSourceStream << vsOutputVariableQualifier << " vec2 v_texcoord;\n"; vsSourceStream << vsOutputVariableQualifier << " vec2 v_texcoord;\n";
vsSourceStream << "\n"; vsSourceStream << "\n";
vsSourceStream << "void main()\n"; vsSourceStream << "void main()\n";
vsSourceStream << "{\n"; vsSourceStream << "{\n";
vsSourceStream << " gl_Position = vec4((a_texcoord * 2.0) - 1.0, 0.0, 1.0);\n"; vsSourceStream << " gl_Position = vec4((" << texcoordAttribName
vsSourceStream << " v_texcoord = a_texcoord * u_scale + u_offset;\n"; << " * 2.0) - 1.0, 0.0, 1.0);\n";
vsSourceStream << " v_texcoord = " << texcoordAttribName
<< " * u_scale + u_offset;\n";
vsSourceStream << "}\n"; vsSourceStream << "}\n";
std::string vsSourceStr = vsSourceStream.str(); std::string vsSourceStr = vsSourceStream.str();
...@@ -1477,6 +1518,8 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context, ...@@ -1477,6 +1518,8 @@ angle::Result BlitGL::getBlitProgram(const gl::Context *context,
ANGLE_GL_TRY(context, mFunctions->deleteShader(fs)); 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_GL_TRY(context, mFunctions->linkProgram(result.program));
ANGLE_TRY(CheckLinkStatus(context, mFunctions, result.program)); ANGLE_TRY(CheckLinkStatus(context, mFunctions, result.program));
......
...@@ -36,6 +36,7 @@ class FunctionsGL; ...@@ -36,6 +36,7 @@ class FunctionsGL;
class RenderbufferGL; class RenderbufferGL;
class StateManagerGL; class StateManagerGL;
class TextureGL; class TextureGL;
struct VertexArrayStateGL;
class BlitGL : angle::NonCopyable class BlitGL : angle::NonCopyable
{ {
...@@ -168,6 +169,8 @@ class BlitGL : angle::NonCopyable ...@@ -168,6 +169,8 @@ class BlitGL : angle::NonCopyable
angle::Result setScratchTextureParameter(const gl::Context *context, angle::Result setScratchTextureParameter(const gl::Context *context,
GLenum param, GLenum param,
GLenum value); GLenum value);
angle::Result setVAOState(const gl::Context *context);
angle::Result initializeVAOState(const gl::Context *context);
const FunctionsGL *mFunctions; const FunctionsGL *mFunctions;
const angle::FeaturesGL &mFeatures; const angle::FeaturesGL &mFeatures;
...@@ -195,11 +198,15 @@ class BlitGL : angle::NonCopyable ...@@ -195,11 +198,15 @@ class BlitGL : angle::NonCopyable
using BlitProgramType = std::tuple<gl::TextureType, GLenum, GLenum>; using BlitProgramType = std::tuple<gl::TextureType, GLenum, GLenum>;
std::map<BlitProgramType, BlitProgram> mBlitPrograms; std::map<BlitProgramType, BlitProgram> mBlitPrograms;
GLuint mScratchTextures[2]; GLuint mScratchTextures[2] = {0};
GLuint mScratchFBO; GLuint mScratchFBO = 0;
GLuint mVAO; GLuint mVAO = 0;
GLuint mVertexBuffer; VertexArrayStateGL *mVAOState = nullptr;
bool mOwnsVAOState = false;
const GLuint mTexcoordAttribLocation = 0;
GLuint mVertexBuffer = 0;
nativegl::TexImageFormat mSRGBMipmapGenerationFormat; nativegl::TexImageFormat mSRGBMipmapGenerationFormat;
}; };
......
...@@ -115,12 +115,23 @@ BufferImpl *ContextGL::createBuffer(const gl::BufferState &state) ...@@ -115,12 +115,23 @@ BufferImpl *ContextGL::createBuffer(const gl::BufferState &state)
VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data) VertexArrayImpl *ContextGL::createVertexArray(const gl::VertexArrayState &data)
{ {
const FunctionsGL *functions = getFunctions(); const angle::FeaturesGL &features = getFeaturesGL();
if (features.syncVertexArraysToDefault.enabled)
{
StateManagerGL *stateManager = getStateManager();
GLuint vao = 0; return new VertexArrayGL(data, stateManager->getDefaultVAO(),
functions->genVertexArrays(1, &vao); stateManager->getDefaultVAOState());
}
else
{
const FunctionsGL *functions = getFunctions();
return new VertexArrayGL(data, vao); GLuint vao = 0;
functions->genVertexArrays(1, &vao);
return new VertexArrayGL(data, vao);
}
} }
QueryImpl *ContextGL::createQuery(gl::QueryType type) QueryImpl *ContextGL::createQuery(gl::QueryType type)
......
...@@ -56,6 +56,17 @@ static void ValidateStateHelper(const FunctionsGL *functions, ...@@ -56,6 +56,17 @@ static void ValidateStateHelper(const FunctionsGL *functions,
} // anonymous namespace } // 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::IndexedBufferBinding::IndexedBufferBinding() : offset(0), size(0), buffer(0) {}
StateManagerGL::StateManagerGL(const FunctionsGL *functions, StateManagerGL::StateManagerGL(const FunctionsGL *functions,
...@@ -67,6 +78,8 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -67,6 +78,8 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mProgram(0), mProgram(0),
mVAO(0), mVAO(0),
mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes), mVertexAttribCurrentValues(rendererCaps.maxVertexAttributes),
mDefaultVAOState(rendererCaps.maxVertexAttributes, rendererCaps.maxVertexAttribBindings),
mVAOState(&mDefaultVAOState),
mBuffers(), mBuffers(),
mIndexedBuffers(), mIndexedBuffers(),
mTextureUnitIndex(0), mTextureUnitIndex(0),
...@@ -182,9 +195,26 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions, ...@@ -182,9 +195,26 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
mFunctions->primitiveRestartIndex(primitiveRestartIndex); mFunctions->primitiveRestartIndex(primitiveRestartIndex);
mPrimitiveRestartIndex = 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) void StateManagerGL::deleteProgram(GLuint program)
{ {
...@@ -205,7 +235,7 @@ void StateManagerGL::deleteVertexArray(GLuint vao) ...@@ -205,7 +235,7 @@ void StateManagerGL::deleteVertexArray(GLuint vao)
{ {
if (mVAO == vao) if (mVAO == vao)
{ {
bindVertexArray(0, 0); bindVertexArray(0, &mDefaultVAOState);
} }
mFunctions->deleteVertexArrays(1, &vao); mFunctions->deleteVertexArrays(1, &vao);
} }
...@@ -281,6 +311,22 @@ void StateManagerGL::deleteBuffer(GLuint buffer) ...@@ -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); mFunctions->deleteBuffers(1, &buffer);
} }
...@@ -360,12 +406,17 @@ void StateManagerGL::forceUseProgram(GLuint program) ...@@ -360,12 +406,17 @@ void StateManagerGL::forceUseProgram(GLuint program)
mLocalDirtyBits.set(gl::State::DIRTY_BIT_PROGRAM_BINDING); 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) if (mVAO != vao)
{ {
ASSERT(!mFeatures.syncVertexArraysToDefault.enabled);
mVAO = vao; mVAO = vao;
mBuffers[gl::BufferBinding::ElementArray] = elementArrayBuffer; mVAOState = vaoState;
mBuffers[gl::BufferBinding::ElementArray] = vaoState ? vaoState->elementArrayBuffer : 0;
mFunctions->bindVertexArray(vao); mFunctions->bindVertexArray(vao);
mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING); mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
...@@ -1957,11 +2008,37 @@ angle::Result StateManagerGL::syncState(const gl::Context *context, ...@@ -1957,11 +2008,37 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
break; break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
{ {
const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray()); VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getAppliedElementArrayBufferID()); bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());
propagateProgramToVAO(context, state.getProgram(), propagateProgramToVAO(context, state.getProgram(),
GetImplAs<VertexArrayGL>(state.getVertexArray())); 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; break;
} }
case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
...@@ -2422,6 +2499,16 @@ void StateManagerGL::syncTransformFeedbackState(const gl::Context *context) ...@@ -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 void StateManagerGL::validateState() const
{ {
// Current program // Current program
...@@ -3070,4 +3157,9 @@ void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &exte ...@@ -3070,4 +3157,9 @@ void StateManagerGL::restoreVertexArraysNativeContext(const gl::Extensions &exte
bindVertexArray(state->vertexArrayBinding, 0); bindVertexArray(state->vertexArrayBinding, 0);
} }
void StateManagerGL::setDefaultVAOStateDirty()
{
mLocalDirtyBits.set(gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING);
}
} // namespace rx } // namespace rx
...@@ -115,6 +115,36 @@ struct ExternalContextState ...@@ -115,6 +115,36 @@ struct ExternalContextState
GLenum vertexArrayBinding; 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 class StateManagerGL final : angle::NonCopyable
{ {
public: public:
...@@ -135,7 +165,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -135,7 +165,7 @@ class StateManagerGL final : angle::NonCopyable
void useProgram(GLuint program); void useProgram(GLuint program);
void forceUseProgram(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 bindBuffer(gl::BufferBinding target, GLuint buffer);
void bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer); void bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer);
void bindBufferRange(gl::BufferBinding target, void bindBufferRange(gl::BufferBinding target,
...@@ -262,6 +292,10 @@ class StateManagerGL final : angle::NonCopyable ...@@ -262,6 +292,10 @@ class StateManagerGL final : angle::NonCopyable
bool getHasSeparateFramebufferBindings() const { return mHasSeparateFramebufferBindings; } bool getHasSeparateFramebufferBindings() const { return mHasSeparateFramebufferBindings; }
GLuint getDefaultVAO() const;
VertexArrayStateGL *getDefaultVAOState();
void setDefaultVAOStateDirty();
void validateState() const; void validateState() const;
void syncFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state); void syncFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state);
...@@ -338,6 +372,17 @@ class StateManagerGL final : angle::NonCopyable ...@@ -338,6 +372,17 @@ class StateManagerGL final : angle::NonCopyable
GLuint mVAO; GLuint mVAO;
std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues; 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; angle::PackedEnumMap<gl::BufferBinding, GLuint> mBuffers;
struct IndexedBufferBinding struct IndexedBufferBinding
......
...@@ -28,15 +28,26 @@ namespace rx ...@@ -28,15 +28,26 @@ namespace rx
{ {
namespace namespace
{ {
bool SameVertexAttribFormat(const VertexAttribute &a, const VertexAttribute &b)
GLuint GetNativeBufferID(const gl::Buffer *frontendBuffer)
{
return frontendBuffer ? GetImplAs<BufferGL>(frontendBuffer)->getBufferID() : 0;
}
bool SameVertexAttribFormat(const VertexAttributeGL &a, const VertexAttribute &b)
{ {
return a.format == b.format && a.relativeOffset == b.relativeOffset; return a.format == b.format && a.relativeOffset == b.relativeOffset;
} }
bool SameVertexBuffer(const VertexBinding &a, const VertexBinding &b) bool SameVertexBuffer(const VertexBindingGL &a, const VertexBinding &b)
{ {
return a.getStride() == b.getStride() && a.getOffset() == b.getOffset() && return a.stride == b.getStride() && a.offset == b.getOffset() &&
a.getBuffer().get() == b.getBuffer().get(); a.buffer == GetNativeBufferID(b.getBuffer().get());
}
bool SameIndexBuffer(const VertexArrayStateGL *a, const gl::Buffer *frontendBuffer)
{
return a->elementArrayBuffer == GetNativeBufferID(frontendBuffer);
} }
bool IsVertexAttribPointerSupported(size_t attribIndex, const VertexAttribute &attrib) bool IsVertexAttribPointerSupported(size_t attribIndex, const VertexAttribute &attrib)
...@@ -83,26 +94,23 @@ static void ValidateStateHelperGetVertexAttribiv(const FunctionsGL *functions, ...@@ -83,26 +94,23 @@ static void ValidateStateHelperGetVertexAttribiv(const FunctionsGL *functions,
// ASSERT(false); // ASSERT(false);
} }
} }
} // anonymous namespace } // anonymous namespace
VertexArrayGL::VertexArrayGL(const VertexArrayState &state, GLuint id) VertexArrayGL::VertexArrayGL(const VertexArrayState &state, GLuint id)
: VertexArrayImpl(state), : VertexArrayImpl(state),
mVertexArrayID(id), mVertexArrayID(id),
mAppliedNumViews(1), mOwnsNativeState(true),
mAppliedElementArrayBuffer(), mNativeState(new VertexArrayStateGL(state.getMaxAttribs(), state.getMaxBindings()))
mAppliedBindings(state.getMaxBindings()),
mStreamingElementArrayBufferSize(0),
mStreamingElementArrayBuffer(0),
mStreamingArrayBufferSize(0),
mStreamingArrayBuffer(0)
{ {
// Set the cached vertex attribute array and vertex attribute binding array size mForcedStreamingAttributesFirstOffsets.fill(0);
GLuint maxVertexAttribs = static_cast<GLuint>(state.getMaxAttribs()); }
for (GLuint i = 0; i < maxVertexAttribs; i++)
{ VertexArrayGL::VertexArrayGL(const gl::VertexArrayState &state,
mAppliedAttributes.emplace_back(i); GLuint id,
} VertexArrayStateGL *sharedState)
: VertexArrayImpl(state), mVertexArrayID(id), mOwnsNativeState(false), mNativeState(sharedState)
{
ASSERT(mNativeState);
mForcedStreamingAttributesFirstOffsets.fill(0); mForcedStreamingAttributesFirstOffsets.fill(0);
} }
...@@ -112,10 +120,19 @@ void VertexArrayGL::destroy(const gl::Context *context) ...@@ -112,10 +120,19 @@ void VertexArrayGL::destroy(const gl::Context *context)
{ {
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
stateManager->deleteVertexArray(mVertexArrayID); if (mOwnsNativeState)
{
stateManager->deleteVertexArray(mVertexArrayID);
}
mVertexArrayID = 0; mVertexArrayID = 0;
mAppliedNumViews = 1; mAppliedNumViews = 1;
mElementArrayBuffer.set(context, nullptr);
for (gl::BindingPointer<gl::Buffer> &binding : mArrayBuffers)
{
binding.set(context, nullptr);
}
stateManager->deleteBuffer(mStreamingElementArrayBuffer); stateManager->deleteBuffer(mStreamingElementArrayBuffer);
mStreamingElementArrayBufferSize = 0; mStreamingElementArrayBufferSize = 0;
mStreamingElementArrayBuffer = 0; mStreamingElementArrayBuffer = 0;
...@@ -124,11 +141,11 @@ void VertexArrayGL::destroy(const gl::Context *context) ...@@ -124,11 +141,11 @@ void VertexArrayGL::destroy(const gl::Context *context)
mStreamingArrayBufferSize = 0; mStreamingArrayBufferSize = 0;
mStreamingArrayBuffer = 0; mStreamingArrayBuffer = 0;
mAppliedElementArrayBuffer.set(context, nullptr); if (mOwnsNativeState)
for (auto &binding : mAppliedBindings)
{ {
binding.setBuffer(context, nullptr); delete mNativeState;
} }
mNativeState = nullptr;
} }
angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context, angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context,
...@@ -144,12 +161,14 @@ angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context, ...@@ -144,12 +161,14 @@ angle::Result VertexArrayGL::syncClientSideData(const gl::Context *context,
void VertexArrayGL::updateElementArrayBufferBinding(const gl::Context *context) const void VertexArrayGL::updateElementArrayBufferBinding(const gl::Context *context) const
{ {
gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
if (elementArrayBuffer != nullptr && elementArrayBuffer != mAppliedElementArrayBuffer.get()) if (!SameIndexBuffer(mNativeState, elementArrayBuffer))
{ {
GLuint elementArrayBufferId = GetNativeBufferID(elementArrayBuffer);
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer); stateManager->bindBuffer(gl::BufferBinding::ElementArray, elementArrayBufferId);
stateManager->bindBuffer(gl::BufferBinding::ElementArray, bufferGL->getBufferID()); mElementArrayBuffer.set(context, elementArrayBuffer);
mAppliedElementArrayBuffer.set(context, elementArrayBuffer); mNativeState->elementArrayBuffer = elementArrayBufferId;
} }
} }
...@@ -242,9 +261,9 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context, ...@@ -242,9 +261,9 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context,
gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer(); gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer();
// Need to check the range of indices if attributes need to be streamed // Need to check the range of indices if attributes need to be streamed
if (elementArrayBuffer != nullptr) if (elementArrayBuffer)
{ {
ASSERT(elementArrayBuffer == mAppliedElementArrayBuffer.get()); ASSERT(SameIndexBuffer(mNativeState, elementArrayBuffer));
// Only compute the index range if the attributes also need to be streamed // Only compute the index range if the attributes also need to be streamed
if (attributesNeedStreaming) if (attributesNeedStreaming)
{ {
...@@ -279,10 +298,11 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context, ...@@ -279,10 +298,11 @@ angle::Result VertexArrayGL::syncIndexData(const gl::Context *context,
mStreamingElementArrayBufferSize = 0; mStreamingElementArrayBufferSize = 0;
} }
stateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); stateManager->bindVertexArray(mVertexArrayID, mNativeState);
stateManager->bindBuffer(gl::BufferBinding::ElementArray, mStreamingElementArrayBuffer); stateManager->bindBuffer(gl::BufferBinding::ElementArray, mStreamingElementArrayBuffer);
mAppliedElementArrayBuffer.set(context, nullptr); mElementArrayBuffer.set(context, nullptr);
mNativeState->elementArrayBuffer = mStreamingElementArrayBuffer;
// Make sure the element array buffer is large enough // Make sure the element array buffer is large enough
const GLuint indexTypeBytes = gl::GetDrawElementsTypeSize(type); const GLuint indexTypeBytes = gl::GetDrawElementsTypeSize(type);
...@@ -381,7 +401,7 @@ angle::Result VertexArrayGL::streamAttributes( ...@@ -381,7 +401,7 @@ angle::Result VertexArrayGL::streamAttributes(
mStreamingArrayBufferSize = requiredBufferSize; mStreamingArrayBufferSize = requiredBufferSize;
} }
stateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); stateManager->bindVertexArray(mVertexArrayID, mNativeState);
// Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
// somehow (such as by a screen change), retry writing the data a few times and return // somehow (such as by a screen change), retry writing the data a few times and return
...@@ -500,14 +520,15 @@ angle::Result VertexArrayGL::streamAttributes( ...@@ -500,14 +520,15 @@ angle::Result VertexArrayGL::streamAttributes(
static_cast<GLintptr>(vertexStartOffset)); static_cast<GLintptr>(vertexStartOffset));
// Update the state to track the streamed attribute // Update the state to track the streamed attribute
mAppliedAttributes[idx].format = attrib.format; mNativeState->attributes[idx].format = attrib.format;
mAppliedAttributes[idx].relativeOffset = 0; mNativeState->attributes[idx].relativeOffset = 0;
mAppliedAttributes[idx].bindingIndex = static_cast<GLuint>(idx); mNativeState->attributes[idx].bindingIndex = static_cast<GLuint>(idx);
mAppliedBindings[idx].setStride(static_cast<GLsizei>(destStride)); mNativeState->bindings[idx].stride = static_cast<GLsizei>(destStride);
mAppliedBindings[idx].setOffset(static_cast<GLintptr>(vertexStartOffset)); mNativeState->bindings[idx].offset = static_cast<GLintptr>(vertexStartOffset);
mAppliedBindings[idx].setBuffer(context, nullptr); mArrayBuffers[idx].set(context, nullptr);
mNativeState->bindings[idx].buffer = mStreamingArrayBuffer;
// There's maxAttributeDataSize * indexRange.start of empty space allocated for each // There's maxAttributeDataSize * indexRange.start of empty space allocated for each
// streaming attributes // streaming attributes
...@@ -541,7 +562,7 @@ void VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced( ...@@ -541,7 +562,7 @@ void VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced(
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
stateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); stateManager->bindVertexArray(mVertexArrayID, mNativeState);
const auto &attribs = mState.getVertexAttributes(); const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings(); const auto &bindings = mState.getVertexBindings();
...@@ -559,14 +580,15 @@ void VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced( ...@@ -559,14 +580,15 @@ void VertexArrayGL::recoverForcedStreamingAttributesForDrawArraysInstanced(
static_cast<GLintptr>(binding.getOffset())); static_cast<GLintptr>(binding.getOffset()));
// Restore the state to track their original buffers // Restore the state to track their original buffers
mAppliedAttributes[idx].format = attrib.format; mNativeState->attributes[idx].format = attrib.format;
mAppliedAttributes[idx].relativeOffset = 0; mNativeState->attributes[idx].relativeOffset = 0;
mAppliedAttributes[idx].bindingIndex = static_cast<GLuint>(attrib.bindingIndex); mNativeState->attributes[idx].bindingIndex = static_cast<GLuint>(attrib.bindingIndex);
mAppliedBindings[idx].setStride(binding.getStride()); mNativeState->bindings[idx].stride = binding.getStride();
mAppliedBindings[idx].setOffset(binding.getOffset()); mNativeState->bindings[idx].offset = binding.getOffset();
mAppliedBindings[idx].setBuffer(context, binding.getBuffer().get()); mArrayBuffers[idx].set(context, binding.getBuffer().get());
mNativeState->bindings[idx].buffer = buffer->getBufferID();
} }
attributeMask->reset(); attributeMask->reset();
...@@ -578,21 +600,16 @@ GLuint VertexArrayGL::getVertexArrayID() const ...@@ -578,21 +600,16 @@ GLuint VertexArrayGL::getVertexArrayID() const
return mVertexArrayID; return mVertexArrayID;
} }
GLuint VertexArrayGL::getAppliedElementArrayBufferID() const rx::VertexArrayStateGL *VertexArrayGL::getNativeState() const
{ {
if (mAppliedElementArrayBuffer.get() == nullptr) return mNativeState;
{
return mStreamingElementArrayBuffer;
}
return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
} }
void VertexArrayGL::updateAttribEnabled(const gl::Context *context, size_t attribIndex) void VertexArrayGL::updateAttribEnabled(const gl::Context *context, size_t attribIndex)
{ {
const bool enabled = mState.getVertexAttribute(attribIndex).enabled & const bool enabled = mState.getVertexAttribute(attribIndex).enabled &
mProgramActiveAttribLocationsMask.test(attribIndex); mProgramActiveAttribLocationsMask.test(attribIndex);
if (mAppliedAttributes[attribIndex].enabled == enabled) if (mNativeState->attributes[attribIndex].enabled == enabled)
{ {
return; return;
} }
...@@ -608,7 +625,7 @@ void VertexArrayGL::updateAttribEnabled(const gl::Context *context, size_t attri ...@@ -608,7 +625,7 @@ void VertexArrayGL::updateAttribEnabled(const gl::Context *context, size_t attri
functions->disableVertexAttribArray(static_cast<GLuint>(attribIndex)); functions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
} }
mAppliedAttributes[attribIndex].enabled = enabled; mNativeState->attributes[attribIndex].enabled = enabled;
} }
void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attribIndex) void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attribIndex)
...@@ -626,21 +643,23 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri ...@@ -626,21 +643,23 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
// - Skip the attribute whose buffer is detached by BindVertexBuffer. Since it cannot have a // - Skip the attribute whose buffer is detached by BindVertexBuffer. Since it cannot have a
// client memory pointer either, it must be disabled and shouldn't affect the draw. // client memory pointer either, it must be disabled and shouldn't affect the draw.
const auto &bindingBuffer = binding.getBuffer(); const auto &bindingBuffer = binding.getBuffer();
const Buffer *arrayBuffer = bindingBuffer.get(); gl::Buffer *arrayBuffer = bindingBuffer.get();
if (arrayBuffer == nullptr) if (arrayBuffer == nullptr)
{ {
// Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if // Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if
// it starts to use a buffer later, there is no chance that the caching will skip it. // it starts to use a buffer later, there is no chance that the caching will skip it.
mAppliedBindings[attribIndex].setBuffer(context, nullptr);
mArrayBuffers[attribIndex].set(context, nullptr);
mNativeState->bindings[attribIndex].buffer = 0;
return; return;
} }
// We do not need to compare attrib.pointer because when we use a different client memory // We do not need to compare attrib.pointer because when we use a different client memory
// pointer, we don't need to update mAttributesNeedStreaming by binding.buffer and we won't // pointer, we don't need to update mAttributesNeedStreaming by binding.buffer and we won't
// update attribPointer in this function. // update attribPointer in this function.
if ((SameVertexAttribFormat(mAppliedAttributes[attribIndex], attrib)) && if ((SameVertexAttribFormat(mNativeState->attributes[attribIndex], attrib)) &&
(mAppliedAttributes[attribIndex].bindingIndex == attrib.bindingIndex) && (mNativeState->attributes[attribIndex].bindingIndex == attrib.bindingIndex) &&
(SameVertexBuffer(mAppliedBindings[attribIndex], binding))) (SameVertexBuffer(mNativeState->bindings[attribIndex], binding)))
{ {
return; return;
} }
...@@ -651,24 +670,25 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri ...@@ -651,24 +670,25 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
// zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument // zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument
// is not NULL. // is not NULL.
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer); GLuint bufferId = GetNativeBufferID(arrayBuffer);
stateManager->bindBuffer(gl::BufferBinding::Array, arrayBufferGL->getBufferID()); stateManager->bindBuffer(gl::BufferBinding::Array, bufferId);
callVertexAttribPointer(context, static_cast<GLuint>(attribIndex), attrib, binding.getStride(), callVertexAttribPointer(context, static_cast<GLuint>(attribIndex), attrib, binding.getStride(),
binding.getOffset()); binding.getOffset());
mAppliedAttributes[attribIndex].format = attrib.format; mNativeState->attributes[attribIndex].format = attrib.format;
// After VertexAttribPointer, attrib.relativeOffset is set to 0 and attrib.bindingIndex is set // After VertexAttribPointer, attrib.relativeOffset is set to 0 and attrib.bindingIndex is set
// to attribIndex in driver. If attrib.relativeOffset != 0 or attrib.bindingIndex != // to attribIndex in driver. If attrib.relativeOffset != 0 or attrib.bindingIndex !=
// attribIndex, they should be set in updateAttribFormat and updateAttribBinding. The cache // attribIndex, they should be set in updateAttribFormat and updateAttribBinding. The cache
// should be consistent with driver so that we won't miss anything. // should be consistent with driver so that we won't miss anything.
mAppliedAttributes[attribIndex].relativeOffset = 0; mNativeState->attributes[attribIndex].relativeOffset = 0;
mAppliedAttributes[attribIndex].bindingIndex = static_cast<GLuint>(attribIndex); mNativeState->attributes[attribIndex].bindingIndex = static_cast<GLuint>(attribIndex);
mAppliedBindings[attribIndex].setStride(binding.getStride()); mNativeState->bindings[attribIndex].stride = binding.getStride();
mAppliedBindings[attribIndex].setOffset(binding.getOffset()); mNativeState->bindings[attribIndex].offset = binding.getOffset();
mAppliedBindings[attribIndex].setBuffer(context, binding.getBuffer().get()); mArrayBuffers[attribIndex].set(context, arrayBuffer);
mNativeState->bindings[attribIndex].buffer = bufferId;
} }
void VertexArrayGL::callVertexAttribPointer(const gl::Context *context, void VertexArrayGL::callVertexAttribPointer(const gl::Context *context,
...@@ -696,9 +716,13 @@ void VertexArrayGL::callVertexAttribPointer(const gl::Context *context, ...@@ -696,9 +716,13 @@ void VertexArrayGL::callVertexAttribPointer(const gl::Context *context,
bool VertexArrayGL::supportVertexAttribBinding(const gl::Context *context) const bool VertexArrayGL::supportVertexAttribBinding(const gl::Context *context) const
{ {
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
const angle::FeaturesGL &features = GetFeaturesGL(context);
ASSERT(functions); ASSERT(functions);
return (functions->vertexAttribBinding != nullptr); // Vertex attrib bindings are not supported on the default VAO so if we're syncing to the
// default VAO due to the feature, disable bindings.
return (functions->vertexAttribBinding != nullptr) &&
!features.syncVertexArraysToDefault.enabled;
} }
void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attribIndex) void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attribIndex)
...@@ -706,7 +730,7 @@ void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attrib ...@@ -706,7 +730,7 @@ void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attrib
ASSERT(supportVertexAttribBinding(context)); ASSERT(supportVertexAttribBinding(context));
const VertexAttribute &attrib = mState.getVertexAttribute(attribIndex); const VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
if (SameVertexAttribFormat(mAppliedAttributes[attribIndex], attrib)) if (SameVertexAttribFormat(mNativeState->attributes[attribIndex], attrib))
{ {
return; return;
} }
...@@ -728,8 +752,8 @@ void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attrib ...@@ -728,8 +752,8 @@ void VertexArrayGL::updateAttribFormat(const gl::Context *context, size_t attrib
attrib.relativeOffset); attrib.relativeOffset);
} }
mAppliedAttributes[attribIndex].format = attrib.format; mNativeState->attributes[attribIndex].format = attrib.format;
mAppliedAttributes[attribIndex].relativeOffset = attrib.relativeOffset; mNativeState->attributes[attribIndex].relativeOffset = attrib.relativeOffset;
} }
void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attribIndex) void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attribIndex)
...@@ -737,7 +761,7 @@ void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attri ...@@ -737,7 +761,7 @@ void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attri
ASSERT(supportVertexAttribBinding(context)); ASSERT(supportVertexAttribBinding(context));
GLuint bindingIndex = mState.getVertexAttribute(attribIndex).bindingIndex; GLuint bindingIndex = mState.getVertexAttribute(attribIndex).bindingIndex;
if (mAppliedAttributes[attribIndex].bindingIndex == bindingIndex) if (mNativeState->attributes[attribIndex].bindingIndex == bindingIndex)
{ {
return; return;
} }
...@@ -745,7 +769,7 @@ void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attri ...@@ -745,7 +769,7 @@ void VertexArrayGL::updateAttribBinding(const gl::Context *context, size_t attri
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
functions->vertexAttribBinding(static_cast<GLuint>(attribIndex), bindingIndex); functions->vertexAttribBinding(static_cast<GLuint>(attribIndex), bindingIndex);
mAppliedAttributes[attribIndex].bindingIndex = bindingIndex; mNativeState->attributes[attribIndex].bindingIndex = bindingIndex;
} }
void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindingIndex) void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindingIndex)
...@@ -753,32 +777,29 @@ void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindi ...@@ -753,32 +777,29 @@ void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindi
ASSERT(supportVertexAttribBinding(context)); ASSERT(supportVertexAttribBinding(context));
const VertexBinding &binding = mState.getVertexBinding(bindingIndex); const VertexBinding &binding = mState.getVertexBinding(bindingIndex);
if (SameVertexBuffer(mAppliedBindings[bindingIndex], binding)) if (SameVertexBuffer(mNativeState->bindings[bindingIndex], binding))
{ {
return; return;
} }
const Buffer *arrayBuffer = binding.getBuffer().get(); gl::Buffer *arrayBuffer = binding.getBuffer().get();
GLuint bufferId = 0; GLuint bufferId = GetNativeBufferID(arrayBuffer);
if (arrayBuffer != nullptr)
{
bufferId = GetImplAs<BufferGL>(arrayBuffer)->getBufferID();
}
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
functions->bindVertexBuffer(static_cast<GLuint>(bindingIndex), bufferId, binding.getOffset(), functions->bindVertexBuffer(static_cast<GLuint>(bindingIndex), bufferId, binding.getOffset(),
binding.getStride()); binding.getStride());
mAppliedBindings[bindingIndex].setStride(binding.getStride()); mNativeState->bindings[bindingIndex].stride = binding.getStride();
mAppliedBindings[bindingIndex].setOffset(binding.getOffset()); mNativeState->bindings[bindingIndex].offset = binding.getOffset();
mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get()); mArrayBuffers[bindingIndex].set(context, arrayBuffer);
mNativeState->bindings[bindingIndex].buffer = bufferId;
} }
void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bindingIndex) void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bindingIndex)
{ {
GLuint adjustedDivisor = GLuint adjustedDivisor =
GetAdjustedDivisor(mAppliedNumViews, mState.getVertexBinding(bindingIndex).getDivisor()); GetAdjustedDivisor(mAppliedNumViews, mState.getVertexBinding(bindingIndex).getDivisor());
if (mAppliedBindings[bindingIndex].getDivisor() == adjustedDivisor) if (mNativeState->bindings[bindingIndex].divisor == adjustedDivisor)
{ {
return; return;
} }
...@@ -795,8 +816,6 @@ void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bind ...@@ -795,8 +816,6 @@ void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bind
functions->vertexAttribDivisor(static_cast<GLuint>(bindingIndex), adjustedDivisor); functions->vertexAttribDivisor(static_cast<GLuint>(bindingIndex), adjustedDivisor);
} }
mAppliedBindings[bindingIndex].setDivisor(adjustedDivisor);
if (adjustedDivisor > 0) if (adjustedDivisor > 0)
{ {
mInstancedAttributesMask.set(bindingIndex); mInstancedAttributesMask.set(bindingIndex);
...@@ -806,6 +825,8 @@ void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bind ...@@ -806,6 +825,8 @@ void VertexArrayGL::updateBindingDivisor(const gl::Context *context, size_t bind
// divisor is reset to 0 // divisor is reset to 0
mInstancedAttributesMask.reset(bindingIndex); mInstancedAttributesMask.reset(bindingIndex);
} }
mNativeState->bindings[bindingIndex].divisor = adjustedDivisor;
} }
void VertexArrayGL::syncDirtyAttrib(const gl::Context *context, void VertexArrayGL::syncDirtyAttrib(const gl::Context *context,
...@@ -892,7 +913,7 @@ angle::Result VertexArrayGL::syncState(const gl::Context *context, ...@@ -892,7 +913,7 @@ angle::Result VertexArrayGL::syncState(const gl::Context *context,
gl::VertexArray::DirtyBindingBitsArray *bindingBits) gl::VertexArray::DirtyBindingBitsArray *bindingBits)
{ {
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
stateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); stateManager->bindVertexArray(mVertexArrayID, mNativeState);
for (size_t dirtyBit : dirtyBits) for (size_t dirtyBit : dirtyBits)
{ {
...@@ -923,9 +944,9 @@ void VertexArrayGL::applyNumViewsToDivisor(const gl::Context *context, int numVi ...@@ -923,9 +944,9 @@ void VertexArrayGL::applyNumViewsToDivisor(const gl::Context *context, int numVi
if (numViews != mAppliedNumViews) if (numViews != mAppliedNumViews)
{ {
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
stateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID()); stateManager->bindVertexArray(mVertexArrayID, mNativeState);
mAppliedNumViews = numViews; mAppliedNumViews = numViews;
for (size_t index = 0u; index < mAppliedBindings.size(); ++index) for (size_t index = 0u; index < mNativeState->bindings.size(); ++index)
{ {
updateBindingDivisor(context, index); updateBindingDivisor(context, index);
} }
...@@ -959,41 +980,31 @@ void VertexArrayGL::validateState(const gl::Context *context) const ...@@ -959,41 +980,31 @@ void VertexArrayGL::validateState(const gl::Context *context) const
"mVertexArrayID", "GL_VERTEX_ARRAY_BINDING"); "mVertexArrayID", "GL_VERTEX_ARRAY_BINDING");
// Element array buffer // Element array buffer
if (mAppliedElementArrayBuffer.get() == nullptr) ValidateStateHelperGetIntegerv(
{ functions, mNativeState->elementArrayBuffer, GL_ELEMENT_ARRAY_BUFFER_BINDING,
ValidateStateHelperGetIntegerv( "mNativeState->elementArrayBuffer", "GL_ELEMENT_ARRAY_BUFFER_BINDING");
functions, mStreamingElementArrayBuffer, GL_ELEMENT_ARRAY_BUFFER_BINDING,
"mAppliedElementArrayBuffer", "GL_ELEMENT_ARRAY_BUFFER_BINDING");
}
else
{
const BufferGL *bufferGL = GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get());
ValidateStateHelperGetIntegerv(
functions, bufferGL->getBufferID(), GL_ELEMENT_ARRAY_BUFFER_BINDING,
"mAppliedElementArrayBuffer", "GL_ELEMENT_ARRAY_BUFFER_BINDING");
}
// ValidateStateHelperGetIntegerv but with > comparison instead of != // ValidateStateHelperGetIntegerv but with > comparison instead of !=
GLint queryValue; GLint queryValue;
functions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &queryValue); functions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &queryValue);
if (mAppliedAttributes.size() > static_cast<GLuint>(queryValue)) if (mNativeState->attributes.size() > static_cast<GLuint>(queryValue))
{ {
WARN() << "mAppliedAttributes.size() (" << mAppliedAttributes.size() WARN() << "mNativeState->attributes.size() (" << mNativeState->attributes.size()
<< ") > GL_MAX_VERTEX_ATTRIBS (" << queryValue << ")"; << ") > GL_MAX_VERTEX_ATTRIBS (" << queryValue << ")";
// Re-add ASSERT: http://anglebug.com/3900 // Re-add ASSERT: http://anglebug.com/3900
// ASSERT(false); // ASSERT(false);
} }
// Check each applied attribute/binding // Check each applied attribute/binding
for (GLuint index = 0; index < mAppliedAttributes.size(); index++) for (GLuint index = 0; index < mNativeState->attributes.size(); index++)
{ {
VertexAttribute &attribute = mAppliedAttributes[index]; VertexAttributeGL &attribute = mNativeState->attributes[index];
ASSERT(attribute.bindingIndex < mAppliedBindings.size()); ASSERT(attribute.bindingIndex < mNativeState->bindings.size());
VertexBinding &binding = mAppliedBindings[attribute.bindingIndex]; VertexBindingGL &binding = mNativeState->bindings[attribute.bindingIndex];
ValidateStateHelperGetVertexAttribiv( ValidateStateHelperGetVertexAttribiv(
functions, index, attribute.enabled, GL_VERTEX_ATTRIB_ARRAY_ENABLED, functions, index, attribute.enabled, GL_VERTEX_ATTRIB_ARRAY_ENABLED,
"mAppliedAttributes.enabled", "GL_VERTEX_ATTRIB_ARRAY_ENABLED"); "mNativeState->attributes.enabled", "GL_VERTEX_ATTRIB_ARRAY_ENABLED");
if (attribute.enabled) if (attribute.enabled)
{ {
...@@ -1001,7 +1012,7 @@ void VertexArrayGL::validateState(const gl::Context *context) const ...@@ -1001,7 +1012,7 @@ void VertexArrayGL::validateState(const gl::Context *context) const
ASSERT(attribute.format); ASSERT(attribute.format);
ValidateStateHelperGetVertexAttribiv( ValidateStateHelperGetVertexAttribiv(
functions, index, ToGLenum(attribute.format->vertexAttribType), functions, index, ToGLenum(attribute.format->vertexAttribType),
GL_VERTEX_ATTRIB_ARRAY_TYPE, "mAppliedAttributes.format->vertexAttribType", GL_VERTEX_ATTRIB_ARRAY_TYPE, "mNativeState->attributes.format->vertexAttribType",
"GL_VERTEX_ATTRIB_ARRAY_TYPE"); "GL_VERTEX_ATTRIB_ARRAY_TYPE");
ValidateStateHelperGetVertexAttribiv( ValidateStateHelperGetVertexAttribiv(
functions, index, attribute.format->channelCount, GL_VERTEX_ATTRIB_ARRAY_SIZE, functions, index, attribute.format->channelCount, GL_VERTEX_ATTRIB_ARRAY_SIZE,
...@@ -1023,26 +1034,17 @@ void VertexArrayGL::validateState(const gl::Context *context) const ...@@ -1023,26 +1034,17 @@ void VertexArrayGL::validateState(const gl::Context *context) const
} }
// Applied bindings // Applied bindings
if (binding.getBuffer().get() == nullptr) ValidateStateHelperGetVertexAttribiv(
{ functions, index, binding.buffer, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
ValidateStateHelperGetVertexAttribiv( "binding.buffer", "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING");
functions, index, mStreamingArrayBuffer, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, if (binding.buffer != 0)
"mAppliedBindings.bufferID", "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING");
}
else
{ {
const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(binding.getBuffer().get());
ASSERT(arrayBufferGL);
ValidateStateHelperGetVertexAttribiv(functions, index, arrayBufferGL->getBufferID(),
GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
"mAppliedBindings.bufferID",
"GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING");
ValidateStateHelperGetVertexAttribiv( ValidateStateHelperGetVertexAttribiv(
functions, index, binding.getStride(), GL_VERTEX_ATTRIB_ARRAY_STRIDE, functions, index, binding.stride, GL_VERTEX_ATTRIB_ARRAY_STRIDE,
"binding.getStride()", "GL_VERTEX_ATTRIB_ARRAY_STRIDE"); "binding.stride", "GL_VERTEX_ATTRIB_ARRAY_STRIDE");
ValidateStateHelperGetVertexAttribiv( ValidateStateHelperGetVertexAttribiv(
functions, index, binding.getDivisor(), GL_VERTEX_ATTRIB_ARRAY_DIVISOR, functions, index, binding.divisor, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,
"binding.getDivisor()", "GL_VERTEX_ATTRIB_ARRAY_DIVISOR"); "binding.divisor", "GL_VERTEX_ATTRIB_ARRAY_DIVISOR");
} }
} }
} }
......
...@@ -20,11 +20,13 @@ namespace rx ...@@ -20,11 +20,13 @@ namespace rx
class FunctionsGL; class FunctionsGL;
class StateManagerGL; class StateManagerGL;
struct VertexArrayStateGL;
class VertexArrayGL : public VertexArrayImpl class VertexArrayGL : public VertexArrayImpl
{ {
public: public:
VertexArrayGL(const gl::VertexArrayState &data, GLuint id); VertexArrayGL(const gl::VertexArrayState &data, GLuint id);
VertexArrayGL(const gl::VertexArrayState &data, GLuint id, VertexArrayStateGL *sharedState);
~VertexArrayGL() override; ~VertexArrayGL() override;
void destroy(const gl::Context *context) override; void destroy(const gl::Context *context) override;
...@@ -44,7 +46,7 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -44,7 +46,7 @@ class VertexArrayGL : public VertexArrayImpl
const void **outIndices) const; const void **outIndices) const;
GLuint getVertexArrayID() const; GLuint getVertexArrayID() const;
GLuint getAppliedElementArrayBufferID() const; VertexArrayStateGL *getNativeState() const;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits, const gl::VertexArray::DirtyBits &dirtyBits,
...@@ -123,23 +125,24 @@ class VertexArrayGL : public VertexArrayImpl ...@@ -123,23 +125,24 @@ class VertexArrayGL : public VertexArrayImpl
const gl::Context *context, const gl::Context *context,
gl::AttributesMask *attributeMask) const; gl::AttributesMask *attributeMask) const;
GLuint mVertexArrayID; GLuint mVertexArrayID = 0;
int mAppliedNumViews; int mAppliedNumViews = 1;
// Remember the program's active attrib location mask so that attributes can be enabled/disabled // Remember the program's active attrib location mask so that attributes can be enabled/disabled
// based on whether they are active in the program // based on whether they are active in the program
gl::AttributesMask mProgramActiveAttribLocationsMask; gl::AttributesMask mProgramActiveAttribLocationsMask;
mutable gl::BindingPointer<gl::Buffer> mAppliedElementArrayBuffer; bool mOwnsNativeState = false;
VertexArrayStateGL *mNativeState = nullptr;
mutable std::vector<gl::VertexAttribute> mAppliedAttributes; mutable gl::BindingPointer<gl::Buffer> mElementArrayBuffer;
mutable std::vector<gl::VertexBinding> mAppliedBindings; mutable std::array<gl::BindingPointer<gl::Buffer>, gl::MAX_VERTEX_ATTRIBS> mArrayBuffers;
mutable size_t mStreamingElementArrayBufferSize; mutable size_t mStreamingElementArrayBufferSize = 0;
mutable GLuint mStreamingElementArrayBuffer; mutable GLuint mStreamingElementArrayBuffer = 0;
mutable size_t mStreamingArrayBufferSize; mutable size_t mStreamingArrayBufferSize = 0;
mutable GLuint mStreamingArrayBuffer; mutable GLuint mStreamingArrayBuffer = 0;
// Used for Mac Intel instanced draw workaround // Used for Mac Intel instanced draw workaround
mutable gl::AttributesMask mForcedStreamingAttributesForDrawArraysInstancedMask; mutable gl::AttributesMask mForcedStreamingAttributesForDrawArraysInstancedMask;
......
...@@ -1309,6 +1309,13 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -1309,6 +1309,13 @@ void GenerateCaps(const FunctionsGL *functions,
LimitVersion(maxSupportedESVersion, gl::Version(3, 1)); 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 // Extension support
extensions->setTextureExtensionSupport(*textureCapsMap); extensions->setTextureExtensionSupport(*textureCapsMap);
extensions->textureCompressionASTCHDRKHR = extensions->textureCompressionASTCHDRKHR =
...@@ -2080,6 +2087,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature ...@@ -2080,6 +2087,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
// now. // now.
ANGLE_FEATURE_CONDITION(features, shiftInstancedArrayDataWithExtraOffset, ANGLE_FEATURE_CONDITION(features, shiftInstancedArrayDataWithExtraOffset,
IsApple() && IsIntel(vendor) && !IsHaswell(device)); IsApple() && IsIntel(vendor) && !IsHaswell(device));
ANGLE_FEATURE_CONDITION(features, syncVertexArraysToDefault,
!nativegl::SupportsVertexArrayObjects(functions));
} }
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features) void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
...@@ -2112,6 +2121,20 @@ void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::Featur ...@@ -2112,6 +2121,20 @@ void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::Featur
namespace nativegl 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) bool SupportsCompute(const FunctionsGL *functions)
{ {
// OpenGL 4.2 is required for GL_ARB_compute_shader, some platform drivers have the extension, // 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 ...@@ -113,6 +113,8 @@ void ReInitializeFeaturesAtGPUSwitch(const FunctionsGL *functions, angle::Featur
namespace nativegl namespace nativegl
{ {
bool SupportsVertexArrayObjects(const FunctionsGL *functions);
bool CanUseDefaultVertexArrayObject(const FunctionsGL *functions);
bool SupportsCompute(const FunctionsGL *functions); bool SupportsCompute(const FunctionsGL *functions);
bool SupportsFenceSync(const FunctionsGL *functions); bool SupportsFenceSync(const FunctionsGL *functions);
bool SupportsOcclusionQueries(const FunctionsGL *functions); bool SupportsOcclusionQueries(const FunctionsGL *functions);
......
...@@ -3631,6 +3631,15 @@ void main() ...@@ -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 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
// D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels // 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( ...@@ -3642,7 +3651,8 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
/* cheapRenderPass */ true), /* cheapRenderPass */ true),
WithMetalMemoryBarrierAndCheapRenderPass(ES3_METAL(), WithMetalMemoryBarrierAndCheapRenderPass(ES3_METAL(),
/* hasBarrier */ false, /* hasBarrier */ false,
/* cheapRenderPass */ false)); /* cheapRenderPass */ false),
EMULATED_VAO_CONFIGS);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND( ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
VertexAttributeOORTest, VertexAttributeOORTest,
......
...@@ -268,6 +268,11 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp) ...@@ -268,6 +268,11 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
stream << "_NoVulkanViewportFlip"; stream << "_NoVulkanViewportFlip";
} }
if (pp.eglParameters.emulatedVAOs == EGL_TRUE)
{
stream << "_EmulatedVAOs";
}
return stream; return stream;
} }
......
...@@ -289,6 +289,14 @@ inline PlatformParameters WithNoVulkanViewportFlip(const PlatformParameters &par ...@@ -289,6 +289,14 @@ inline PlatformParameters WithNoVulkanViewportFlip(const PlatformParameters &par
withoutVulkanViewportFlip.eglParameters.supportsVulkanViewportFlip = EGL_FALSE; withoutVulkanViewportFlip.eglParameters.supportsVulkanViewportFlip = EGL_FALSE;
return withoutVulkanViewportFlip; return withoutVulkanViewportFlip;
} }
inline PlatformParameters WithEmulatedVAOs(const PlatformParameters &params)
{
PlatformParameters emualtedVAOParams = params;
emualtedVAOParams.eglParameters.emulatedVAOs = EGL_TRUE;
return emualtedVAOParams;
}
} // namespace angle } // namespace angle
#endif // ANGLE_TEST_CONFIGS_H_ #endif // ANGLE_TEST_CONFIGS_H_
...@@ -64,7 +64,7 @@ struct EGLPlatformParameters ...@@ -64,7 +64,7 @@ struct EGLPlatformParameters
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods, shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
robustness, emulatedPrerotation, asyncCommandQueueFeatureVulkan, robustness, emulatedPrerotation, asyncCommandQueueFeatureVulkan,
hasExplicitMemBarrierFeatureMtl, hasCheapRenderPassFeatureMtl, hasExplicitMemBarrierFeatureMtl, hasCheapRenderPassFeatureMtl,
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip); forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip, emulatedVAOs);
} }
EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; EGLint renderer = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
...@@ -86,6 +86,7 @@ struct EGLPlatformParameters ...@@ -86,6 +86,7 @@ struct EGLPlatformParameters
EGLint hasCheapRenderPassFeatureMtl = EGL_DONT_CARE; EGLint hasCheapRenderPassFeatureMtl = EGL_DONT_CARE;
EGLint forceBufferGPUStorageFeatureMtl = EGL_DONT_CARE; EGLint forceBufferGPUStorageFeatureMtl = EGL_DONT_CARE;
EGLint supportsVulkanViewportFlip = EGL_DONT_CARE; EGLint supportsVulkanViewportFlip = EGL_DONT_CARE;
EGLint emulatedVAOs = EGL_DONT_CARE;
angle::PlatformMethods *platformMethods = nullptr; angle::PlatformMethods *platformMethods = nullptr;
}; };
......
...@@ -263,6 +263,11 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow, ...@@ -263,6 +263,11 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
enabledFeatureOverrides.push_back("force_buffer_gpu_storage_mtl"); enabledFeatureOverrides.push_back("force_buffer_gpu_storage_mtl");
} }
if (params.emulatedVAOs == EGL_TRUE)
{
enabledFeatureOverrides.push_back("sync_vertex_arrays_to_default");
}
const bool hasFeatureControlANGLE = const bool hasFeatureControlANGLE =
strstr(extensionString, "EGL_ANGLE_feature_control") != nullptr; 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