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,
if (!elementArrayBuffer)
{
ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
&mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
renderer, drawCallParams, &mCurrentElementArrayBufferHandle,
&mCurrentElementArrayBufferOffset));
}
else
{
......@@ -505,9 +505,10 @@ gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
}
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();
return gl::InternalError()
<< "Unsigned byte translation is not implemented for indices in a buffer object";
......
......@@ -446,29 +446,43 @@ gl::Error LineLoopHelper::getIndexBufferForElementArrayBuffer(RendererVk *render
return gl::NoError();
}
gl::Error LineLoopHelper::getIndexBufferForClientElementArray(RendererVk *renderer,
const void *indicesInput,
VkIndexType indexType,
int indexCount,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut)
gl::Error LineLoopHelper::getIndexBufferForClientElementArray(
RendererVk *renderer,
const gl::DrawCallParams &drawCallParams,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut)
{
// TODO(lucferron): we'll eventually need to support uint8, emulated on 16 since Vulkan only
// supports 16 / 32.
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
uint8_t *indices = nullptr;
uint32_t offset = 0;
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,
reinterpret_cast<uint8_t **>(&indices), bufferHandleOut,
&offset, nullptr));
*bufferOffsetOut = static_cast<VkDeviceSize>(offset);
memcpy(indices, indicesInput, unitSize * indexCount);
memcpy(indices + unitSize * indexCount, indicesInput, unitSize);
if (drawCallParams.type() == GL_UNSIGNED_BYTE)
{
// 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()));
return gl::NoError();
......
......@@ -147,9 +147,7 @@ class LineLoopHelper final : public vk::CommandGraphResource
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
gl::Error getIndexBufferForClientElementArray(RendererVk *renderer,
const void *indicesInput,
VkIndexType indexType,
int indexCount,
const gl::DrawCallParams &drawCallParams,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
......
......@@ -778,19 +778,21 @@ TEST_P(SimpleOperationTest, DrawWith2DTexture)
EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
}
// Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
template <typename T>
void TestDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,
int windowWidth,
int windowHeight)
{
ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
glUseProgram(program);
// We expect to draw a square with these 4 vertices with a drawArray call.
std::vector<Vector3> vertices;
CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, getWindowWidth(),
getWindowHeight(), &vertices);
CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, windowWidth,
windowHeight, &vertices);
// 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");
ASSERT_NE(-1, positionLocation);
......@@ -803,13 +805,13 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(positionLocation);
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);
ASSERT_GL_NO_ERROR();
int quarterWidth = getWindowWidth() / 4;
int quarterHeight = getWindowHeight() / 4;
int quarterWidth = windowWidth / 4;
int quarterHeight = windowHeight / 4;
// Bottom left
EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
......@@ -824,6 +826,20 @@ TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
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.
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