Commit e14951e6 by Jamie Madill Committed by Commit Bot

Implement robust buffer initialization.

This uses the most simple implementation: on BufferData calls without explicit data arguments, it will initialize the buffer data store to zero. This could be improved by deferring the init until needed, and skipping it if the buffer store is cleared through other API calls, but it is not a regression from current Chromium implementation. BUG=angleproject:1635 Change-Id: I2fb1594851c5050dc2578736c3f74761555da267 Reviewed-on: https://chromium-review.googlesource.com/450921Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 0bb791ed
......@@ -67,7 +67,19 @@ Error Buffer::bufferData(const Context *context,
GLsizeiptr size,
GLenum usage)
{
ANGLE_TRY(mImpl->setData(rx::SafeGetImpl(context), target, data, size, usage));
const void *dataForImpl = data;
// If we are using robust resource init, make sure the buffer starts cleared.
// TODO(jmadill): Investigate lazier clearing.
if (context && context->getGLState().isRobustResourceInitEnabled() && data == nullptr)
{
angle::MemoryBuffer *scratchBuffer = nullptr;
ANGLE_TRY(context->getScratchBuffer(static_cast<size_t>(size), &scratchBuffer));
std::fill(scratchBuffer->data(), scratchBuffer->data() + size, static_cast<uint8_t>(0));
dataForImpl = scratchBuffer->data();
}
ANGLE_TRY(mImpl->setData(rx::SafeGetImpl(context), target, dataForImpl, size, usage));
mIndexRangeCache.clear();
mState.mUsage = usage;
......
......@@ -272,7 +272,8 @@ Context::Context(rx::EGLImplFactory *implFactory,
mRobustAccess(GetRobustAccess(attribs)),
mCurrentSurface(nullptr),
mSurfacelessFramebuffer(nullptr),
mWebGLContext(GetWebGLContext(attribs))
mWebGLContext(GetWebGLContext(attribs)),
mScratchBuffer(1000u)
{
if (mRobustAccess)
{
......@@ -3941,4 +3942,13 @@ void Context::setFramebufferParameteri(GLenum target, GLenum pname, GLint param)
SetFramebufferParameteri(framebuffer, pname, param);
}
Error Context::getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const
{
if (!mScratchBuffer.get(requestedSize, scratchBufferOut))
{
return gl::OutOfMemory() << "Failed to allocate internal buffer.";
}
return gl::NoError();
}
} // namespace gl
......@@ -14,13 +14,14 @@
#include <string>
#include "angle_gl.h"
#include "common/MemoryBuffer.h"
#include "common/angleutils.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Constants.h"
#include "libANGLE/ContextState.h"
#include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/Workarounds.h"
#include "libANGLE/angletypes.h"
......@@ -661,6 +662,8 @@ class Context final : public ValidationContext
void getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
void setFramebufferParameteri(GLenum target, GLenum pname, GLint param);
Error getScratchBuffer(size_t requestedSize, angle::MemoryBuffer **scratchBufferOut) const;
private:
void syncRendererState();
void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
......@@ -753,6 +756,9 @@ class Context final : public ValidationContext
State::DirtyObjects mBlitDirtyObjects;
Workarounds mWorkarounds;
// Not really a property of context state. The size and contexts change per-api-call.
mutable angle::ScratchBuffer mScratchBuffer;
};
} // namespace gl
......
......@@ -321,6 +321,7 @@ class State : angle::NonCopyable
void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
bool hasMappedBuffer(GLenum target) const;
bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
enum DirtyBitType
{
......
......@@ -28,17 +28,38 @@ class RobustResourceInitTest : public ANGLETest
setDeferContextInit(true);
setRobustResourceInit(true);
}
bool hasEGLExtension()
{
EGLDisplay display = getEGLWindow()->getDisplay();
ASSERT(display != EGL_NO_DISPLAY);
return (eglDisplayExtensionEnabled(
display, "EGL_ANGLE_create_context_robust_resource_initialization"));
}
bool setup()
{
if (!hasEGLExtension())
{
return false;
}
if (!getEGLWindow()->initializeContext())
{
EXPECT_TRUE(false);
return false;
}
return true;
}
};
// Context creation should fail if EGL_ANGLE_create_context_robust_resource_initialization
// is not available, and succeed otherwise.
TEST_P(RobustResourceInitTest, ExtensionInit)
{
EGLDisplay display = getEGLWindow()->getDisplay();
ASSERT_TRUE(display != EGL_NO_DISPLAY);
if (eglDisplayExtensionEnabled(display,
"EGL_ANGLE_create_context_robust_resource_initialization"))
if (hasEGLExtension())
{
// Context creation shold succeed with robust resource init enabled.
EXPECT_TRUE(getEGLWindow()->initializeContext());
......@@ -89,8 +110,7 @@ TEST_P(RobustResourceInitTest, QueriesOnNonRobustContext)
EGLDisplay display = getEGLWindow()->getDisplay();
ASSERT_TRUE(display != EGL_NO_DISPLAY);
if (!eglDisplayExtensionEnabled(display,
"EGL_ANGLE_create_context_robust_resource_initialization"))
if (!hasEGLExtension())
{
return;
}
......@@ -110,6 +130,54 @@ TEST_P(RobustResourceInitTest, QueriesOnNonRobustContext)
EXPECT_GL_NO_ERROR();
}
// Tests that buffers start zero-filled if the data pointer is null.
TEST_P(RobustResourceInitTest, BufferData)
{
if (!setup())
{
return;
}
GLBuffer buffer;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, getWindowWidth() * getWindowHeight() * sizeof(GLfloat), nullptr,
GL_STATIC_DRAW);
const std::string &vertexShader =
"attribute vec2 position;\n"
"attribute float testValue;\n"
"varying vec4 colorOut;\n"
"void main() {\n"
" gl_Position = vec4(position, 0, 1);\n"
" colorOut = testValue == 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
"}";
const std::string &fragmentShader =
"varying mediump vec4 colorOut;\n"
"void main() {\n"
" gl_FragColor = colorOut;\n"
"}";
ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
GLint testValueLoc = glGetAttribLocation(program.get(), "testValue");
ASSERT_NE(-1, testValueLoc);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(testValueLoc, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
glEnableVertexAttribArray(testValueLoc);
glBindBuffer(GL_ARRAY_BUFFER, 0);
drawQuad(program.get(), "position", 0.5f);
ASSERT_GL_NO_ERROR();
std::vector<GLColor> expected(getWindowWidth() * getWindowHeight(), GLColor::green);
std::vector<GLColor> actual(getWindowWidth() * getWindowHeight());
glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
actual.data());
EXPECT_EQ(expected, actual);
}
ANGLE_INSTANTIATE_TEST(RobustResourceInitTest,
ES2_D3D9(),
ES2_D3D11(),
......
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