Commit 3e313805 by Luc Ferron Committed by Commit Bot

Vulkan: Line loop edge case with ubyte indices

Bug: angleproject:2637 Change-Id: I2cec129ed1aa0e55e0dbf1d353caa65a51c528a3 Reviewed-on: https://chromium-review.googlesource.com/1096017 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 9c0e3063
...@@ -417,8 +417,8 @@ gl::Error VertexArrayVk::drawElements(const gl::Context *context, ...@@ -417,8 +417,8 @@ gl::Error VertexArrayVk::drawElements(const gl::Context *context,
if (!elementArrayBuffer) if (!elementArrayBuffer)
{ {
ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray( ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(), renderer, drawCallParams, &mCurrentElementArrayBufferHandle,
&mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset)); &mCurrentElementArrayBufferOffset));
} }
else else
{ {
...@@ -505,9 +505,10 @@ gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context, ...@@ -505,9 +505,10 @@ gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
} }
else if (mIndexBufferDirty || newCommandBuffer) else if (mIndexBufferDirty || newCommandBuffer)
{ {
if (drawCallParams.type() == GL_UNSIGNED_BYTE) if (drawCallParams.type() == GL_UNSIGNED_BYTE &&
drawCallParams.mode() != gl::PrimitiveMode::LineLoop)
{ {
// TODO(fjhenigman): Index format translation. // TODO(fjhenigman): Index format translation for non line-loop calls.
UNIMPLEMENTED(); UNIMPLEMENTED();
return gl::InternalError() return gl::InternalError()
<< "Unsigned byte translation is not implemented for indices in a buffer object"; << "Unsigned byte translation is not implemented for indices in a buffer object";
......
...@@ -446,29 +446,43 @@ gl::Error LineLoopHelper::getIndexBufferForElementArrayBuffer(RendererVk *render ...@@ -446,29 +446,43 @@ gl::Error LineLoopHelper::getIndexBufferForElementArrayBuffer(RendererVk *render
return gl::NoError(); return gl::NoError();
} }
gl::Error LineLoopHelper::getIndexBufferForClientElementArray(RendererVk *renderer, gl::Error LineLoopHelper::getIndexBufferForClientElementArray(
const void *indicesInput, RendererVk *renderer,
VkIndexType indexType, const gl::DrawCallParams &drawCallParams,
int indexCount, VkBuffer *bufferHandleOut,
VkBuffer *bufferHandleOut, VkDeviceSize *bufferOffsetOut)
VkDeviceSize *bufferOffsetOut)
{ {
// TODO(lucferron): we'll eventually need to support uint8, emulated on 16 since Vulkan only VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
// supports 16 / 32.
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
uint8_t *indices = nullptr; uint8_t *indices = nullptr;
uint32_t offset = 0; uint32_t offset = 0;
auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t)); auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
size_t allocateBytes = unitSize * (indexCount + 1); size_t allocateBytes = unitSize * (drawCallParams.indexCount() + 1);
ANGLE_TRY(mDynamicIndexBuffer.allocate(renderer, allocateBytes, ANGLE_TRY(mDynamicIndexBuffer.allocate(renderer, allocateBytes,
reinterpret_cast<uint8_t **>(&indices), bufferHandleOut, reinterpret_cast<uint8_t **>(&indices), bufferHandleOut,
&offset, nullptr)); &offset, nullptr));
*bufferOffsetOut = static_cast<VkDeviceSize>(offset); *bufferOffsetOut = static_cast<VkDeviceSize>(offset);
memcpy(indices, indicesInput, unitSize * indexCount); if (drawCallParams.type() == GL_UNSIGNED_BYTE)
memcpy(indices + unitSize * indexCount, indicesInput, unitSize); {
// Vulkan doesn't support uint8 index types, so we need to emulate it.
ASSERT(indexType == VK_INDEX_TYPE_UINT16);
uint16_t *indicesDst = reinterpret_cast<uint16_t *>(indices);
const uint8_t *srcPtr = reinterpret_cast<const uint8_t *>(drawCallParams.indices());
for (int i = 0; i < drawCallParams.indexCount(); i++)
{
indicesDst[i] = srcPtr[i];
}
indicesDst[drawCallParams.indexCount()] = srcPtr[0];
}
else
{
memcpy(indices, drawCallParams.indices(), unitSize * drawCallParams.indexCount());
memcpy(indices + unitSize * drawCallParams.indexCount(), drawCallParams.indices(),
unitSize);
}
ANGLE_TRY(mDynamicIndexBuffer.flush(renderer->getDevice())); ANGLE_TRY(mDynamicIndexBuffer.flush(renderer->getDevice()));
return gl::NoError(); return gl::NoError();
......
...@@ -147,9 +147,7 @@ class LineLoopHelper final : public vk::CommandGraphResource ...@@ -147,9 +147,7 @@ class LineLoopHelper final : public vk::CommandGraphResource
VkBuffer *bufferHandleOut, VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut); VkDeviceSize *bufferOffsetOut);
gl::Error getIndexBufferForClientElementArray(RendererVk *renderer, gl::Error getIndexBufferForClientElementArray(RendererVk *renderer,
const void *indicesInput, const gl::DrawCallParams &drawCallParams,
VkIndexType indexType,
int indexCount,
VkBuffer *bufferHandleOut, VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut); VkDeviceSize *bufferOffsetOut);
......
...@@ -778,19 +778,21 @@ TEST_P(SimpleOperationTest, DrawWith2DTexture) ...@@ -778,19 +778,21 @@ TEST_P(SimpleOperationTest, DrawWith2DTexture)
EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow); EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
} }
// Draw a line loop using a drawElement call and client side memory. template <typename T>
TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory) void TestDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,
int windowWidth,
int windowHeight)
{ {
ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader); ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
glUseProgram(program); glUseProgram(program);
// We expect to draw a square with these 4 vertices with a drawArray call. // We expect to draw a square with these 4 vertices with a drawArray call.
std::vector<Vector3> vertices; std::vector<Vector3> vertices;
CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, getWindowWidth(), CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, windowWidth,
getWindowHeight(), &vertices); windowHeight, &vertices);
// If we use these indices to draw however, we should be drawing an hourglass. // If we use these indices to draw however, we should be drawing an hourglass.
std::vector<GLushort> indices{3, 2, 1, 0}; std::vector<T> indices{3, 2, 1, 0};
GLint positionLocation = glGetAttribLocation(program, "position"); GLint positionLocation = glGetAttribLocation(program, "position");
ASSERT_NE(-1, positionLocation); ASSERT_NE(-1, positionLocation);
...@@ -803,13 +805,13 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory) ...@@ -803,13 +805,13 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation); glEnableVertexAttribArray(positionLocation);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, indices.data()); glDrawElements(GL_LINE_LOOP, 4, indexType, indices.data());
glDisableVertexAttribArray(positionLocation); glDisableVertexAttribArray(positionLocation);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
int quarterWidth = getWindowWidth() / 4; int quarterWidth = windowWidth / 4;
int quarterHeight = getWindowHeight() / 4; int quarterHeight = windowHeight / 4;
// Bottom left // Bottom left
EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green); EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
...@@ -824,6 +826,20 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory) ...@@ -824,6 +826,20 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green); EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
} }
// Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUShortClientSideMemory)
{
TestDrawElementsLineLoopUsingClientSideMemory<GLushort>(GL_UNSIGNED_SHORT, getWindowWidth(),
getWindowHeight());
}
// Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUByteClientSideMemory)
{
TestDrawElementsLineLoopUsingClientSideMemory<GLubyte>(GL_UNSIGNED_BYTE, getWindowWidth(),
getWindowHeight());
}
// Creates a program with a cube texture and renders with it. // Creates a program with a cube texture and renders with it.
TEST_P(SimpleOperationTest, DrawWithCubeTexture) TEST_P(SimpleOperationTest, DrawWithCubeTexture)
{ {
......
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