From 5fedd0174bdf4955f3908ab3489fadfc16c317ea Mon Sep 17 00:00:00 2001 From: Jamie Madill Date: Thu, 8 May 2014 10:19:36 -0400 Subject: [PATCH] Implement copies from pack buffers to native buffers. Full support for using pack buffers as vertex buffers or other binding points requires us to copy through the staging buffer. BUG=angle:511 Change-Id: Ife0f5390a1a83dfbe0fa0b19db72f3a8b82b6b83 Reviewed-on: https://chromium-review.googlesource.com/198435 Reviewed-by: Shannon Woods Tested-by: Jamie Madill --- .../renderer/d3d11/BufferStorage11.cpp | 24 +++++++++ tests/angle_tests/ReadPixelsTest.cpp | 53 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp index f57cf4a00..4aa0b6298 100644 --- a/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp +++ b/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp @@ -82,6 +82,7 @@ class BufferStorage11::TypedBufferStorage11 DataRevision getDataRevision() const { return mRevision; } BufferUsage getUsage() const { return mUsage; } size_t getSize() const { return mBufferSize; } + bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); } void setDataRevision(DataRevision rev) { mRevision = rev; } @@ -274,6 +275,17 @@ void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t TypedBufferStorage11 *source = sourceStorage11->getLatestStorage(); if (source && dest) { + // If copying to/from a pixel pack buffer, we must have a staging or + // pack buffer partner, because other native buffers can't be mapped + if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable()) + { + source = sourceStorage11->getStagingBuffer(); + } + else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable()) + { + dest = getStagingBuffer(); + } + dest->copyFromStorage(source, sourceOffset, size, destOffset); dest->setDataRevision(dest->getDataRevision() + 1); } @@ -433,6 +445,18 @@ BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage u TypedBufferStorage11 *latestBuffer = getLatestStorage(); if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) { + // if copying from a pack buffer to a non-staging native buffer, we must first + // copy through the staging buffer, because other native buffers can't be mapped + if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) + { + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); + directBuffer->setDataRevision(latestBuffer->getDataRevision()); + + latestBuffer = stagingBuffer; + } + // if copyFromStorage returns true, the D3D buffer has been recreated // and we should update our serial if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) diff --git a/tests/angle_tests/ReadPixelsTest.cpp b/tests/angle_tests/ReadPixelsTest.cpp index de3883884..70efe99af 100644 --- a/tests/angle_tests/ReadPixelsTest.cpp +++ b/tests/angle_tests/ReadPixelsTest.cpp @@ -240,3 +240,56 @@ TEST_F(ReadPixelsTest, pbo_and_sub_data_offset) glUnmapBuffer(GL_ARRAY_BUFFER); EXPECT_GL_NO_ERROR(); } + +TEST_F(ReadPixelsTest, draw_with_pbo) +{ + unsigned char data[4] = { 1, 2, 3, 4 }; + + glBindTexture(GL_TEXTURE_2D, mTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); + EXPECT_GL_NO_ERROR(); + + // glReadBuffer(GL_COLOR_ATTACHMENT0); // FIXME: currently UNIMPLEMENTED + glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO); + EXPECT_GL_NO_ERROR(); + + glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + EXPECT_GL_NO_ERROR(); + + float positionData[] = { 0.5f, 0.5f }; + + glUseProgram(mProgram); + glViewport(0, 0, 1, 1); + glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData); + EXPECT_GL_NO_ERROR(); + + GLint positionLocation = glGetAttribLocation(mProgram, "aPosition"); + EXPECT_NE(-1, positionLocation); + + GLint testLocation = glGetAttribLocation(mProgram, "aTest"); + EXPECT_NE(-1, testLocation); + + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(positionLocation); + EXPECT_GL_NO_ERROR(); + + glBindBuffer(GL_ARRAY_BUFFER, mPBO); + glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0); + glEnableVertexAttribArray(testLocation); + EXPECT_GL_NO_ERROR(); + + glDrawArrays(GL_POINTS, 0, 1); + EXPECT_GL_NO_ERROR(); + + memset(data, 0, 4); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data); + EXPECT_GL_NO_ERROR(); + + EXPECT_EQ(1, data[0]); + EXPECT_EQ(2, data[1]); + EXPECT_EQ(3, data[2]); + EXPECT_EQ(4, data[3]); +}