Commit 7fe44a53 by Mohan Maiya Committed by Commit Bot

Vulkan: Don't acquire new BufferHelper for external buffers

EXT_external_buffer spec - This extension allows the data store for an immutable buffer to be sourced from an external EGLClientBuffer, allowing sharing of EGL client buffers across APIs, across processes, and across different processing cores such as the GPU, CPU, and DSP. The intent is for a single backing memory to be reused across various processes and processors. Ensure that a glBuffer backed by external memory does not orphan the memory when glBuffer APIs like glBufferSubData or glMapBufferRangeEXT modify the glBuffer. Bug: angleproject:4380 Bug: angleproject:5073 Tests: ExternalBufferTestES31.*DoesNotCauseOrphaning*Vulkan Change-Id: I4e88f80d93ee1ba1208378121412926351d10af8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2776192 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7e9b497c
...@@ -475,7 +475,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, ...@@ -475,7 +475,8 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
ASSERT(mBuffer && mBuffer->valid()); ASSERT(mBuffer && mBuffer->valid());
if ((access & GL_MAP_INVALIDATE_BUFFER_BIT) != 0 && if ((access & GL_MAP_INVALIDATE_BUFFER_BIT) != 0 &&
mBuffer->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial())) mBuffer->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()) &&
!mBuffer->isExternalBuffer())
{ {
// We try to map buffer, but buffer is busy. Caller has told us it doesn't care about // We try to map buffer, but buffer is busy. Caller has told us it doesn't care about
// previous content. Instead of wait for GPU to finish, we just allocate a new buffer. // previous content. Instead of wait for GPU to finish, we just allocate a new buffer.
...@@ -730,12 +731,14 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, ...@@ -730,12 +731,14 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
updateShadowBuffer(data, size, offset); updateShadowBuffer(data, size, offset);
// if the buffer is currently in use // if the buffer is currently in use
// if sub data size meets threshold, acquire a new BufferHelper from the pool // if it isn't an external buffer and sub data size meets threshold
// else stage an update // acquire a new BufferHelper from the pool
// else stage the update
// else update the buffer directly // else update the buffer directly
if (mBuffer->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial())) if (mBuffer->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()))
{ {
if (SubDataSizeMeetsThreshold(size, static_cast<size_t>(mState.getSize()))) if (!mBuffer->isExternalBuffer() &&
SubDataSizeMeetsThreshold(size, static_cast<size_t>(mState.getSize())))
{ {
ANGLE_TRY(acquireAndUpdate(contextVk, data, size, offset)); ANGLE_TRY(acquireAndUpdate(contextVk, data, size, offset));
} }
......
...@@ -129,7 +129,62 @@ TEST_P(ExternalBufferTestES31, BufferSubData) ...@@ -129,7 +129,62 @@ TEST_P(ExternalBufferTestES31, BufferSubData)
} }
unlockAndroidHardwareBuffer(aHardwareBuffer); unlockAndroidHardwareBuffer(aHardwareBuffer);
// Delete the source AHB when in use
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// Delete the source AHB
destroyAndroidHardwareBuffer(aHardwareBuffer);
}
// Verify that subdata updates to an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31, SubDataDoesNotCauseOrphaning)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
constexpr uint8_t kBufferSize = 16;
std::vector<GLubyte> initData(kBufferSize, 0xA);
// Create the AHB
AHardwareBuffer *aHardwareBuffer;
constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
// Create externalBuffer
GLBuffer externalBuffer;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, externalBuffer);
glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
ASSERT_GL_NO_ERROR();
// Create a copy read buffer
std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
GLBuffer copyReadBuffer;
glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
ASSERT_GL_NO_ERROR();
// Copy from copyReadBuffer to externalBuffer
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
ASSERT_GL_NO_ERROR();
// Update externalBuffer
std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
glFinish();
ASSERT_GL_NO_ERROR();
// Inspect the data written into the AHB, through externalBuffer, using CPU access.
uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
for (uint32_t i = 0; i < kBufferSize; ++i)
{
EXPECT_EQ(data[i], 0xFF);
}
unlockAndroidHardwareBuffer(aHardwareBuffer);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// Delete the source AHB
destroyAndroidHardwareBuffer(aHardwareBuffer); destroyAndroidHardwareBuffer(aHardwareBuffer);
} }
...@@ -184,7 +239,9 @@ TEST_P(ExternalBufferTestES31, DispatchCompute) ...@@ -184,7 +239,9 @@ TEST_P(ExternalBufferTestES31, DispatchCompute)
} }
unlockAndroidHardwareBuffer(aHardwareBuffer); unlockAndroidHardwareBuffer(aHardwareBuffer);
// Delete the source AHB when in use
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// Delete the source AHB
destroyAndroidHardwareBuffer(aHardwareBuffer); destroyAndroidHardwareBuffer(aHardwareBuffer);
} }
...@@ -197,7 +254,7 @@ TEST_P(ExternalBufferTestES31, MapBuffer) ...@@ -197,7 +254,7 @@ TEST_P(ExternalBufferTestES31, MapBuffer)
constexpr uint8_t kBufferSize = 16; constexpr uint8_t kBufferSize = 16;
std::vector<GLubyte> initData(kBufferSize, 0xFF); std::vector<GLubyte> initData(kBufferSize, 0xFF);
// Create the Image // Create the AHB
AHardwareBuffer *aHardwareBuffer; AHardwareBuffer *aHardwareBuffer;
constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT); constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT);
aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data()); aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
...@@ -220,7 +277,71 @@ TEST_P(ExternalBufferTestES31, MapBuffer) ...@@ -220,7 +277,71 @@ TEST_P(ExternalBufferTestES31, MapBuffer)
} }
glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER); glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
// Delete the source AHB when in use
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// Delete the source AHB
destroyAndroidHardwareBuffer(aHardwareBuffer);
}
// Verify that mapping an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31, MapBufferDoesNotCauseOrphaning)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
!IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
constexpr uint8_t kBufferSize = 16;
std::vector<GLubyte> initData(kBufferSize, 0xA);
// Create the AHB
AHardwareBuffer *aHardwareBuffer;
constexpr GLbitfield kFlags =
(GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
GLBuffer buffer;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
ASSERT_GL_NO_ERROR();
// Create a copy read buffer
std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
GLBuffer copyReadBuffer;
glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
ASSERT_GL_NO_ERROR();
// Copy from copyReadBuffer to externalBuffer
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
ASSERT_GL_NO_ERROR();
// Inspect the data written into the buffer using map buffer API.
constexpr GLbitfield kMapFlags = (GL_MAP_WRITE_BIT_EXT | GL_MAP_INVALIDATE_BUFFER_BIT);
uint8_t *mapData = static_cast<uint8_t *>(
glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, kMapFlags));
ASSERT_GL_NO_ERROR();
EXPECT_NE(mapData, nullptr);
glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
// Update externalBuffer
std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
glFinish();
ASSERT_GL_NO_ERROR();
// Inspect the data written into the AHB, through externalBuffer, using CPU access.
uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
for (uint32_t i = 0; i < kBufferSize; ++i)
{
EXPECT_EQ(data[i], 0xFF);
}
unlockAndroidHardwareBuffer(aHardwareBuffer);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// Delete the source AHB
destroyAndroidHardwareBuffer(aHardwareBuffer); destroyAndroidHardwareBuffer(aHardwareBuffer);
} }
......
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