Bug fix in unpack buffer validation
For an implementation that supports GL_EXT_buffer_storage extension
it is valid to read or write from a buffer that is partially or fully
mapped if it was allocated by a call to glBufferStorageEXT with the
GL_MAP_PERSISTENT_BIT_EXT included in <flags>
Bug: angleproject:5056
Bug: angleproject:6689
Test: BufferStorageTestES3.TexImage2DPixelUnpackBufferMappedPersistently
Change-Id: Ia4b6967aab02bbfb101d5253b9c83d314bc92f5f
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3278482
Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Charlie Lao <cclao@google.com>
diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h
index 9809a3b..da3c8a3 100644
--- a/src/libANGLE/Buffer.h
+++ b/src/libANGLE/Buffer.h
@@ -140,6 +140,10 @@
GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
GLenum getAccess() const { return mState.mAccess; }
GLboolean isMapped() const { return mState.mMapped; }
+ bool isPersistentlyMapped() const
+ {
+ return (mState.mStorageExtUsageFlags & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+ }
void *getMapPointer() const { return mState.mMapPointer; }
GLint64 getMapOffset() const { return mState.mMapOffset; }
GLint64 getMapLength() const { return mState.mMapLength; }
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 87b9f94..dfa0dfa 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -803,8 +803,8 @@
}
}
- // ...the buffer object's data store is currently mapped.
- if (pixelUnpackBuffer->isMapped())
+ // ...the buffer object's data store is currently mapped but not persistently.
+ if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
return false;
diff --git a/src/tests/gl_tests/BufferDataTest.cpp b/src/tests/gl_tests/BufferDataTest.cpp
index 74c39e4..325ba67 100644
--- a/src/tests/gl_tests/BufferDataTest.cpp
+++ b/src/tests/gl_tests/BufferDataTest.cpp
@@ -1225,6 +1225,41 @@
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
+// Test that we are able to perform glTex*D calls while a pixel unpack buffer is bound
+// and persistently mapped.
+TEST_P(BufferStorageTestES3, TexImage2DPixelUnpackBufferMappedPersistently)
+{
+ ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
+ !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
+
+ std::vector<uint8_t> data(64);
+ FillVectorWithRandomUBytes(&data);
+
+ GLBuffer buffer;
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.get());
+ glBufferStorageEXT(GL_PIXEL_UNPACK_BUFFER, data.size(), data.data(),
+ GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
+
+ // Map the buffer.
+ void *mapPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, data.size(),
+ GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
+ ASSERT_NE(nullptr, mapPtr);
+ ASSERT_GL_NO_ERROR();
+
+ // Create a 2D texture and fill it using the persistenly mapped unpack buffer
+ GLTexture tex;
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ constexpr GLsizei kTextureWidth = 4;
+ constexpr GLsizei kTextureHeight = 4;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTextureWidth, kTextureHeight, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, 0);
+ ASSERT_GL_NO_ERROR();
+
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ ASSERT_GL_NO_ERROR();
+}
+
// Verify persistently mapped buffers can use glBufferSubData
TEST_P(BufferStorageTestES3, StorageBufferSubDataMapped)
{