Commit 9420fa06 by Tim Van Patten Committed by Commit Bot

Vulkan: Implement copyBufferSubData

Implement BufferVk::copySubData(). Bug: angleproject:3194 Test: dEQP-GLES3.functional.buffer.copy.* Test: dEQP-GLES3.functional.negative_api.buffer.copy_buffer_sub_data Test: angle_end2end_tests BufferDataTestES3 Change-Id: I220cd490eb1eb799604e217b3e377af3fd431d97 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1648669 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d5cef305
...@@ -150,8 +150,26 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -150,8 +150,26 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
GLintptr destOffset, GLintptr destOffset,
GLsizeiptr size) GLsizeiptr size)
{ {
ANGLE_VK_UNREACHABLE(vk::GetImpl(context)); ASSERT(mBuffer.valid());
return angle::Result::Stop;
ContextVk *contextVk = vk::GetImpl(context);
auto *sourceBuffer = GetAs<BufferVk>(source);
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
// Enqueue a copy command on the GPU.
VkBufferCopy copyRegion = {static_cast<VkDeviceSize>(sourceOffset),
static_cast<VkDeviceSize>(destOffset),
static_cast<VkDeviceSize>(size)};
sourceBuffer->mBuffer.onRead(&mBuffer, VK_ACCESS_TRANSFER_READ_BIT);
mBuffer.onWrite(contextVk, VK_ACCESS_TRANSFER_WRITE_BIT);
commandBuffer->copyBuffer(sourceBuffer->getBuffer().getBuffer(), mBuffer.getBuffer(), 1,
&copyRegion);
return angle::Result::Continue;
} }
angle::Result BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr) angle::Result BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr)
...@@ -172,7 +190,7 @@ angle::Result BufferVk::mapRange(const gl::Context *context, ...@@ -172,7 +190,7 @@ angle::Result BufferVk::mapRange(const gl::Context *context,
angle::Result BufferVk::mapImpl(ContextVk *contextVk, void **mapPtr) angle::Result BufferVk::mapImpl(ContextVk *contextVk, void **mapPtr)
{ {
return mapRangeImpl(contextVk, 0, mState.getSize(), 0, mapPtr); return mapRangeImpl(contextVk, 0, static_cast<VkDeviceSize>(mState.getSize()), 0, mapPtr);
} }
angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
......
...@@ -275,7 +275,7 @@ void CommandGraphResource::addReadDependency(CommandGraphResource *readingResour ...@@ -275,7 +275,7 @@ void CommandGraphResource::addReadDependency(CommandGraphResource *readingResour
CommandGraphNode *readingNode = readingResource->mCurrentWritingNode; CommandGraphNode *readingNode = readingResource->mCurrentWritingNode;
ASSERT(readingNode); ASSERT(readingNode);
if (mCurrentWritingNode) if (mCurrentWritingNode && (mCurrentWritingNode != readingNode))
{ {
// Ensure 'readingNode' happens after the current writing node. // Ensure 'readingNode' happens after the current writing node.
CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, readingNode); CommandGraphNode::SetHappensBeforeDependency(mCurrentWritingNode, readingNode);
......
...@@ -587,9 +587,6 @@ ...@@ -587,9 +587,6 @@
2905 VULKAN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_component_type = SKIP 2905 VULKAN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_component_type = SKIP
2905 VULKAN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_x_size_texture = SKIP 2905 VULKAN : dEQP-GLES3.functional.state_query.fbo.framebuffer_attachment_x_size_texture = SKIP
// Buffer copy:
3194 VULKAN : dEQP-GLES3.functional.buffer.copy.* = SKIP
// Shader support: // Shader support:
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.link_program = FAIL 3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.link_program = FAIL
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.use_program = FAIL 3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.use_program = FAIL
...@@ -686,9 +683,6 @@ ...@@ -686,9 +683,6 @@
2672 VULKAN : dEQP-GLES3.functional.primitive_restart.begin_restart_end_restart_duplicate_restarts.line_loop.unsigned_short.draw_elements_instanced = SKIP 2672 VULKAN : dEQP-GLES3.functional.primitive_restart.begin_restart_end_restart_duplicate_restarts.line_loop.unsigned_short.draw_elements_instanced = SKIP
2672 VULKAN : dEQP-GLES3.functional.primitive_restart.begin_restart_end_restart_duplicate_restarts.line_loop.unsigned_int.draw_elements_instanced = SKIP 2672 VULKAN : dEQP-GLES3.functional.primitive_restart.begin_restart_end_restart_duplicate_restarts.line_loop.unsigned_int.draw_elements_instanced = SKIP
// - BufferVk::copySubData:
2950 VULKAN : dEQP-GLES3.functional.negative_api.buffer.copy_buffer_sub_data = SKIP
// - ES3 Query Types: // - ES3 Query Types:
2950 VULKAN : dEQP-GLES3.functional.negative_api.fragment.begin_query = SKIP 2950 VULKAN : dEQP-GLES3.functional.negative_api.fragment.begin_query = SKIP
...@@ -736,6 +730,8 @@ ...@@ -736,6 +730,8 @@
3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.unsigned_byte.components* = FAIL 3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.unsigned_byte.components* = FAIL
3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.short.components* = FAIL 3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.short.components* = FAIL
3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.unsigned_short.components* = FAIL 3193 ANDROID VULKAN : dEQP-GLES3.functional.vertex_arrays.single_attribute.output_types.unsigned_short.components* = FAIL
3544 ANDROID VULKAN : dEQP-GLES3.functional.buffer.copy.basic.* = SKIP
3544 ANDROID VULKAN : dEQP-GLES3.functional.buffer.copy.subrange.* = SKIP
// Fixed in later driver versions. // Fixed in later driver versions.
2727 VULKAN ANDROID : dEQP-GLES3.functional.shaders.builtin_variable.pointcoord = FAIL 2727 VULKAN ANDROID : dEQP-GLES3.functional.shaders.builtin_variable.pointcoord = FAIL
...@@ -350,7 +350,7 @@ TEST_P(BufferDataTestES3, BufferResizing) ...@@ -350,7 +350,7 @@ TEST_P(BufferDataTestES3, BufferResizing)
// Resize the buffer // Resize the buffer
// To trigger the bug, the buffer need to be big enough because some hardware copy buffers // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
// by chunks of pages instead of the minimum number of bytes neeeded. // by chunks of pages instead of the minimum number of bytes needed.
const size_t numBytes = 4096 * 4; const size_t numBytes = 4096 * 4;
glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
...@@ -402,6 +402,68 @@ TEST_P(BufferDataTestES3, BufferResizing) ...@@ -402,6 +402,68 @@ TEST_P(BufferDataTestES3, BufferResizing)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Verify the functionality of glMapBufferRange()'s GL_MAP_UNSYNCHRONIZED_BIT
// NOTE: On Vulkan, if we ever use memory that's not `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`, then
// this could incorrectly pass.
TEST_P(BufferDataTestES3, MapBufferRangeUnsynchronizedBit)
{
// We can currently only control the behavior of the Vulkan backend's synchronizing operation's
ANGLE_SKIP_TEST_IF(!IsVulkan());
const size_t numElements = 10;
std::vector<uint8_t> srcData(numElements);
std::vector<uint8_t> dstData(numElements);
for (uint8_t i = 0; i < srcData.size(); i++)
{
srcData[i] = i;
}
for (uint8_t i = 0; i < dstData.size(); i++)
{
dstData[i] = static_cast<uint8_t>(i + dstData.size());
}
GLBuffer srcBuffer;
GLBuffer dstBuffer;
glBindBuffer(GL_COPY_READ_BUFFER, srcBuffer);
ASSERT_GL_NO_ERROR();
glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
ASSERT_GL_NO_ERROR();
glBufferData(GL_COPY_READ_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
glBufferData(GL_COPY_WRITE_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
ASSERT_GL_NO_ERROR();
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numElements);
// With GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be stale and match dstData
// NOTE: We are specifying GL_MAP_WRITE_BIT so we can use GL_MAP_UNSYNCHRONIZED_BIT. This is
// venturing into undefined behavior, since we are actually planning on reading from this
// pointer.
auto *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
EXPECT_GL_NO_ERROR();
for (size_t i = 0; i < numElements; ++i)
{
EXPECT_EQ(dstData[i], data[i]);
}
glUnmapBuffer(GL_COPY_WRITE_BUFFER);
EXPECT_GL_NO_ERROR();
// Without GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be copied and match srcData
data = reinterpret_cast<uint8_t *>(
glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_READ_BIT));
EXPECT_GL_NO_ERROR();
for (size_t i = 0; i < numElements; ++i)
{
EXPECT_EQ(srcData[i], data[i]);
}
glUnmapBuffer(GL_COPY_WRITE_BUFFER);
EXPECT_GL_NO_ERROR();
}
// Verify OES_mapbuffer is present if EXT_map_buffer_range is. // Verify OES_mapbuffer is present if EXT_map_buffer_range is.
TEST_P(BufferDataTest, ExtensionDependency) TEST_P(BufferDataTest, ExtensionDependency)
{ {
...@@ -475,8 +537,12 @@ ANGLE_INSTANTIATE_TEST(BufferDataTest, ...@@ -475,8 +537,12 @@ ANGLE_INSTANTIATE_TEST(BufferDataTest,
ES2_OPENGL(), ES2_OPENGL(),
ES2_OPENGLES(), ES2_OPENGLES(),
ES2_VULKAN()); ES2_VULKAN());
ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(BufferDataTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(IndexedBufferCopyTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(IndexedBufferCopyTest,
ES3_D3D11(),
ES3_OPENGL(),
ES3_OPENGLES(),
ES3_VULKAN());
#ifdef _WIN64 #ifdef _WIN64
......
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