Commit 9bf86f07 by Geoff Lang Committed by Commit Bot

Don't sync the read framebuffer on draw calls.

The read framebuffer may not be complete and be incapable of syncing. Removed the generate syncDirtyObjects method so each caller must make sure they are only syncing objects that are known to be valid for the operation. BUG=angleproject:2737 Change-Id: Ia8edf3fca3a8369aa813be46ba99f6b50a36b2e6 Reviewed-on: https://chromium-review.googlesource.com/1151621 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 03d132eb
...@@ -449,6 +449,14 @@ void Context::initialize() ...@@ -449,6 +449,14 @@ void Context::initialize()
} }
// Initialize dirty bit masks // Initialize dirty bit masks
mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_TEXTURES);
mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE); mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE);
mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING); mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
// No dirty objects. // No dirty objects.
...@@ -2295,8 +2303,7 @@ void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask) ...@@ -2295,8 +2303,7 @@ void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask)
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilFillPath(pathObj, fillMode, mask); mImplementation->stencilFillPath(pathObj, fillMode, mask);
} }
...@@ -2307,8 +2314,7 @@ void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask) ...@@ -2307,8 +2314,7 @@ void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask)
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilStrokePath(pathObj, reference, mask); mImplementation->stencilStrokePath(pathObj, reference, mask);
} }
...@@ -2319,8 +2325,7 @@ void Context::coverFillPath(GLuint path, GLenum coverMode) ...@@ -2319,8 +2325,7 @@ void Context::coverFillPath(GLuint path, GLenum coverMode)
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->coverFillPath(pathObj, coverMode); mImplementation->coverFillPath(pathObj, coverMode);
} }
...@@ -2331,8 +2336,7 @@ void Context::coverStrokePath(GLuint path, GLenum coverMode) ...@@ -2331,8 +2336,7 @@ void Context::coverStrokePath(GLuint path, GLenum coverMode)
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->coverStrokePath(pathObj, coverMode); mImplementation->coverStrokePath(pathObj, coverMode);
} }
...@@ -2343,8 +2347,7 @@ void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask ...@@ -2343,8 +2347,7 @@ void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode); mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
} }
...@@ -2358,8 +2361,7 @@ void Context::stencilThenCoverStrokePath(GLuint path, ...@@ -2358,8 +2361,7 @@ void Context::stencilThenCoverStrokePath(GLuint path,
if (!pathObj) if (!pathObj)
return; return;
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode); mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
} }
...@@ -2374,8 +2376,7 @@ void Context::coverFillPathInstanced(GLsizei numPaths, ...@@ -2374,8 +2376,7 @@ void Context::coverFillPathInstanced(GLsizei numPaths,
{ {
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues); mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
} }
...@@ -2391,7 +2392,7 @@ void Context::coverStrokePathInstanced(GLsizei numPaths, ...@@ -2391,7 +2392,7 @@ void Context::coverStrokePathInstanced(GLsizei numPaths,
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
ANGLE_CONTEXT_TRY(syncState()); ANGLE_CONTEXT_TRY(syncStateForPathOperation());
mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType, mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
transformValues); transformValues);
...@@ -2409,7 +2410,7 @@ void Context::stencilFillPathInstanced(GLsizei numPaths, ...@@ -2409,7 +2410,7 @@ void Context::stencilFillPathInstanced(GLsizei numPaths,
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
ANGLE_CONTEXT_TRY(syncState()); ANGLE_CONTEXT_TRY(syncStateForPathOperation());
mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType, mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
transformValues); transformValues);
...@@ -2426,8 +2427,7 @@ void Context::stencilStrokePathInstanced(GLsizei numPaths, ...@@ -2426,8 +2427,7 @@ void Context::stencilStrokePathInstanced(GLsizei numPaths,
{ {
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType, mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
transformValues); transformValues);
...@@ -2445,8 +2445,7 @@ void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths, ...@@ -2445,8 +2445,7 @@ void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
{ {
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask, mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
transformType, transformValues); transformType, transformValues);
...@@ -2464,8 +2463,7 @@ void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths, ...@@ -2464,8 +2463,7 @@ void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
{ {
const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase); const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering? ANGLE_CONTEXT_TRY(syncStateForPathOperation());
ANGLE_CONTEXT_TRY(syncState());
mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask, mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
transformType, transformValues); transformType, transformValues);
...@@ -3385,7 +3383,7 @@ Error Context::prepareForDraw(PrimitiveMode mode) ...@@ -3385,7 +3383,7 @@ Error Context::prepareForDraw(PrimitiveMode mode)
ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mGLState)); ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mGLState));
} }
ANGLE_TRY(syncDirtyObjects()); ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects));
if (isRobustResourceInitEnabled()) if (isRobustResourceInitEnabled())
{ {
...@@ -3414,13 +3412,6 @@ Error Context::prepareForClearBuffer(GLenum buffer, GLint drawbuffer) ...@@ -3414,13 +3412,6 @@ Error Context::prepareForClearBuffer(GLenum buffer, GLint drawbuffer)
return NoError(); return NoError();
} }
Error Context::syncState()
{
ANGLE_TRY(syncDirtyObjects());
ANGLE_TRY(syncDirtyBits());
return NoError();
}
Error Context::syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask) Error Context::syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask)
{ {
ANGLE_TRY(syncDirtyObjects(objectMask)); ANGLE_TRY(syncDirtyObjects(objectMask));
...@@ -3444,11 +3435,6 @@ Error Context::syncDirtyBits(const State::DirtyBits &bitMask) ...@@ -3444,11 +3435,6 @@ Error Context::syncDirtyBits(const State::DirtyBits &bitMask)
return NoError(); return NoError();
} }
Error Context::syncDirtyObjects()
{
return mGLState.syncDirtyObjects(this);
}
Error Context::syncDirtyObjects(const State::DirtyObjects &objectMask) Error Context::syncDirtyObjects(const State::DirtyObjects &objectMask)
{ {
return mGLState.syncDirtyObjects(this, objectMask); return mGLState.syncDirtyObjects(this, objectMask);
...@@ -4309,6 +4295,16 @@ Error Context::syncStateForBlit() ...@@ -4309,6 +4295,16 @@ Error Context::syncStateForBlit()
return syncState(mBlitDirtyBits, mBlitDirtyObjects); return syncState(mBlitDirtyBits, mBlitDirtyObjects);
} }
Error Context::syncStateForPathOperation()
{
ANGLE_TRY(syncDirtyObjects(mPathOperationDirtyObjects));
// TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
ANGLE_TRY(syncDirtyBits());
return NoError();
}
void Context::activeShaderProgram(GLuint pipeline, GLuint program) void Context::activeShaderProgram(GLuint pipeline, GLuint program)
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
......
...@@ -1498,15 +1498,14 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1498,15 +1498,14 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
Error prepareForDraw(PrimitiveMode mode); Error prepareForDraw(PrimitiveMode mode);
Error prepareForClear(GLbitfield mask); Error prepareForClear(GLbitfield mask);
Error prepareForClearBuffer(GLenum buffer, GLint drawbuffer); Error prepareForClearBuffer(GLenum buffer, GLint drawbuffer);
Error syncState();
Error syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask); Error syncState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
Error syncDirtyBits(); Error syncDirtyBits();
Error syncDirtyBits(const State::DirtyBits &bitMask); Error syncDirtyBits(const State::DirtyBits &bitMask);
Error syncDirtyObjects();
Error syncDirtyObjects(const State::DirtyObjects &objectMask); Error syncDirtyObjects(const State::DirtyObjects &objectMask);
Error syncStateForReadPixels(); Error syncStateForReadPixels();
Error syncStateForTexImage(); Error syncStateForTexImage();
Error syncStateForBlit(); Error syncStateForBlit();
Error syncStateForPathOperation();
VertexArray *checkVertexArrayAllocation(GLuint vertexArrayHandle); VertexArray *checkVertexArrayAllocation(GLuint vertexArrayHandle);
TransformFeedback *checkTransformFeedbackAllocation(GLuint transformFeedback); TransformFeedback *checkTransformFeedbackAllocation(GLuint transformFeedback);
...@@ -1609,6 +1608,8 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1609,6 +1608,8 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
const bool mExtensionsEnabled; const bool mExtensionsEnabled;
MemoryProgramCache *mMemoryProgramCache; MemoryProgramCache *mMemoryProgramCache;
State::DirtyObjects mDrawDirtyObjects;
State::DirtyObjects mPathOperationDirtyObjects;
State::DirtyBits mTexImageDirtyBits; State::DirtyBits mTexImageDirtyBits;
State::DirtyObjects mTexImageDirtyObjects; State::DirtyObjects mTexImageDirtyObjects;
State::DirtyBits mReadPixelsDirtyBits; State::DirtyBits mReadPixelsDirtyBits;
......
...@@ -2629,14 +2629,6 @@ bool State::hasMappedBuffer(BufferBinding target) const ...@@ -2629,14 +2629,6 @@ bool State::hasMappedBuffer(BufferBinding target) const
} }
} }
Error State::syncDirtyObjects(const Context *context)
{
if (!mDirtyObjects.any())
return NoError();
return syncDirtyObjects(context, mDirtyObjects);
}
Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset) Error State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset)
{ {
const DirtyObjects &dirtyObjects = mDirtyObjects & bitset; const DirtyObjects &dirtyObjects = mDirtyObjects & bitset;
...@@ -2882,7 +2874,7 @@ Error State::clearUnclearedActiveTextures(const Context *context) ...@@ -2882,7 +2874,7 @@ Error State::clearUnclearedActiveTextures(const Context *context)
return NoError(); return NoError();
} }
ASSERT(!mDirtyObjects.any()); ASSERT(!mDirtyObjects[DIRTY_OBJECT_PROGRAM_TEXTURES]);
for (auto textureIndex : mActiveTexturesMask) for (auto textureIndex : mActiveTexturesMask)
{ {
......
...@@ -450,7 +450,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -450,7 +450,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
using DirtyObjects = angle::BitSet<DIRTY_OBJECT_MAX>; using DirtyObjects = angle::BitSet<DIRTY_OBJECT_MAX>;
void clearDirtyObjects() { mDirtyObjects.reset(); } void clearDirtyObjects() { mDirtyObjects.reset(); }
void setAllDirtyObjects() { mDirtyObjects.set(); } void setAllDirtyObjects() { mDirtyObjects.set(); }
Error syncDirtyObjects(const Context *context);
Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset); Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
Error syncDirtyObject(const Context *context, GLenum target); Error syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(GLenum target); void setObjectDirty(GLenum target);
......
...@@ -322,6 +322,46 @@ TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer) ...@@ -322,6 +322,46 @@ TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
testZeroHeightRenderbuffer(); testZeroHeightRenderbuffer();
} }
// Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
{
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
GLTexture incompleteTexture;
glBindTexture(GL_TEXTURE_2D, incompleteTexture);
GLFramebuffer incompleteFBO;
glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
glCheckFramebufferStatus(GL_FRAMEBUFFER));
GLTexture completeTexture;
glBindTexture(GL_TEXTURE_2D, completeTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
GLFramebuffer completeFBO;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
completeTexture, 0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
ASSERT_GL_NO_ERROR();
// Simple draw program.
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
// 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.
ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest, ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
......
...@@ -144,14 +144,17 @@ TEST_P(WebGLFramebufferTest, TestFramebufferRequiredCombinations) ...@@ -144,14 +144,17 @@ TEST_P(WebGLFramebufferTest, TestFramebufferRequiredCombinations)
checkBufferBits(GL_DEPTH_ATTACHMENT, GL_NONE); checkBufferBits(GL_DEPTH_ATTACHMENT, GL_NONE);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
// 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL if (getClientMajorVersion() == 2)
// renderbuffer {
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height); // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT =
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, // DEPTH_STENCIL renderbuffer
renderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
EXPECT_GL_NO_ERROR(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
checkFramebufferForAllowedStatuses(ALLOW_COMPLETE); renderbuffer);
checkBufferBits(GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE); EXPECT_GL_NO_ERROR();
checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
checkBufferBits(GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE);
}
} }
void testAttachment(GLint width, void testAttachment(GLint width,
...@@ -370,6 +373,9 @@ void WebGLFramebufferTest::testDepthStencilRenderbuffer(GLint width, ...@@ -370,6 +373,9 @@ void WebGLFramebufferTest::testDepthStencilRenderbuffer(GLint width,
// Test various attachment combinations with WebGL framebuffers. // Test various attachment combinations with WebGL framebuffers.
TEST_P(WebGLFramebufferTest, TestAttachments) TEST_P(WebGLFramebufferTest, TestAttachments)
{ {
// GL_DEPTH_STENCIL renderbuffer format is only valid for WebGL1
ANGLE_SKIP_TEST_IF(getClientMajorVersion() != 2);
for (GLint width = 2; width <= 2; width += 2) for (GLint width = 2; width <= 2; width += 2)
{ {
for (GLint height = 2; height <= 2; height += 2) for (GLint height = 2; height <= 2; height += 2)
...@@ -856,6 +862,9 @@ ANGLE_INSTANTIATE_TEST(WebGLFramebufferTest, ...@@ -856,6 +862,9 @@ ANGLE_INSTANTIATE_TEST(WebGLFramebufferTest,
ES2_D3D11(), ES2_D3D11(),
ES2_D3D11_FL9_3(), ES2_D3D11_FL9_3(),
ES2_OPENGL(), ES2_OPENGL(),
ES2_OPENGLES()); ES2_OPENGLES(),
ES3_D3D11(),
ES3_OPENGL(),
ES3_OPENGLES());
} // namespace } // namespace
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