GL: Unbind buffers after mapping them.

Qualcomm drivers generate errors if a bound array buffer is
mapped during a draw call even if it is not used by the draw.

Bug: chromium:1345777
Change-Id: I0639caf5d74c8cbdc7245324fdcb136bd3d51b86
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3871333
Reviewed-by: Peng Huang <penghuang@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
This commit is contained in:
Geoff Lang 2022-09-02 10:19:46 -04:00 коммит произвёл Angle LUCI CQ
Родитель b9df95ffdf
Коммит f99e255b46
2 изменённых файлов: 56 добавлений и 10 удалений

Просмотреть файл

@ -152,19 +152,26 @@ angle::Result BufferGL::map(const gl::Context *context, GLenum access, void **ma
{
*mapPtr = mShadowCopy.data();
}
else if (functions->mapBuffer)
{
stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
*mapPtr = ANGLE_GL_TRY(
context, functions->mapBuffer(gl::ToGLenum(DestBufferOperationTarget), access));
}
else
{
ASSERT(functions->mapBufferRange && access == GL_WRITE_ONLY_OES);
stateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
*mapPtr =
ANGLE_GL_TRY(context, functions->mapBufferRange(gl::ToGLenum(DestBufferOperationTarget),
0, mBufferSize, GL_MAP_WRITE_BIT));
if (functions->mapBuffer)
{
*mapPtr = ANGLE_GL_TRY(
context, functions->mapBuffer(gl::ToGLenum(DestBufferOperationTarget), access));
}
else
{
ASSERT(functions->mapBufferRange && access == GL_WRITE_ONLY_OES);
*mapPtr = ANGLE_GL_TRY(
context, functions->mapBufferRange(gl::ToGLenum(DestBufferOperationTarget), 0,
mBufferSize, GL_MAP_WRITE_BIT));
}
// Unbind the mapped buffer from the array buffer binding. Some drivers generate errors if
// any mapped buffer is bound to array buffer bindings.
// crbug.com/1345777
stateManager->bindBuffer(DestBufferOperationTarget, 0);
}
mIsMapped = true;
@ -197,6 +204,11 @@ angle::Result BufferGL::mapRange(const gl::Context *context,
*mapPtr =
ANGLE_GL_TRY(context, functions->mapBufferRange(gl::ToGLenum(DestBufferOperationTarget),
offset, length, access));
// Unbind the mapped buffer from the array buffer binding. Some drivers generate errors if
// any mapped buffer is bound to array buffer bindings.
// crbug.com/1345777
stateManager->bindBuffer(DestBufferOperationTarget, 0);
}
mIsMapped = true;

Просмотреть файл

@ -979,6 +979,40 @@ TEST_P(BufferDataTest, BufferSizeValidation32Bit)
EXPECT_GL_ERROR(GL_INVALID_VALUE);
}
// Some drivers generate errors when array buffer bindings are left mapped during draw calls.
// crbug.com/1345777
TEST_P(BufferDataTestES3, GLDriverErrorWhenMappingArrayBuffersDuringDraw)
{
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
ASSERT_NE(program, 0u);
glUseProgram(program);
auto quadVertices = GetQuadVertices();
GLBuffer vb;
glBindBuffer(GL_ARRAY_BUFFER, vb.get());
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size(), quadVertices.data(),
GL_STATIC_DRAW);
GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
ASSERT_NE(-1, positionLocation);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
GLBuffer pb;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pb);
glBufferData(GL_PIXEL_UNPACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 1024, GL_MAP_WRITE_BIT);
EXPECT_GL_NO_ERROR();
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_NO_ERROR();
}
// Tests a null crash bug caused by copying from null back-end buffer pointer
// when calling bufferData again after drawing without calling bufferData in D3D11.
TEST_P(BufferDataTestES3, DrawWithNotCallingBufferData)