Commit a912046d by Luc Ferron Committed by Commit Bot

Vulkan: DrawElements with line loops client side memory support

- Also enables 6 new tests in LineLoopTests.cpp in angle_end2end Bug: angleproject:2458 Change-Id: I4aec12b0ac780e81e6811f1199a5acaf17d9b982 Reviewed-on: https://chromium-review.googlesource.com/1010411Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Luc Ferron <lucferron@chromium.org>
parent 983c429f
......@@ -405,22 +405,24 @@ gl::Error VertexArrayVk::drawElements(const gl::Context *context,
}
// Handle GL_LINE_LOOP drawElements.
gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
if (!elementArrayBuffer)
{
UNIMPLEMENTED();
return gl::InternalError() << "Line loop indices in client memory not supported";
}
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
if (mDirtyLineLoopTranslation)
{
ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
&mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
gl::Buffer *elementArrayBuffer = mState.getElementArrayBuffer().get();
VkIndexType indexType = gl_vk::GetIndexType(drawCallParams.type());
if (!elementArrayBuffer)
{
ANGLE_TRY(mLineLoopHelper.getIndexBufferForClientElementArray(
renderer, drawCallParams.indices(), indexType, drawCallParams.indexCount(),
&mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
}
else
{
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
ANGLE_TRY(mLineLoopHelper.getIndexBufferForElementArrayBuffer(
renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
&mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
}
}
ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
......@@ -485,7 +487,7 @@ gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
{
ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
if (!mState.getElementArrayBuffer().get())
if (!mState.getElementArrayBuffer().get() && drawCallParams.mode() != GL_LINE_LOOP)
{
ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
ANGLE_TRY(streamIndexData(renderer, drawCallParams));
......
......@@ -377,6 +377,34 @@ 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)
{
// 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);
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);
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);
ANGLE_TRY(mDynamicIndexBuffer.flush(renderer->getDevice()));
return gl::NoError();
}
void LineLoopHelper::destroy(VkDevice device)
{
mDynamicIndexBuffer.destroy(device);
......
......@@ -128,6 +128,13 @@ class LineLoopHelper final : public vk::CommandGraphResource
int indexCount,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
gl::Error getIndexBufferForClientElementArray(RendererVk *renderer,
const void *indicesInput,
VkIndexType indexType,
int indexCount,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut);
void destroy(VkDevice device);
static void Draw(int count, CommandBuffer *commandBuffer);
......
......@@ -112,6 +112,9 @@ class LineLoopTest : public ANGLETest
TEST_P(LineLoopTest, LineLoopUByteIndices)
{
// TODO(fjhenigman): UByte not yet supported in VertexArrayVk
ANGLE_SKIP_TEST_IF(IsVulkan());
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
// On Win7, the D3D SDK Layers emits a false warning for these tests.
// This doesn't occur on Windows 10 (Version 1511) though.
......@@ -146,6 +149,9 @@ TEST_P(LineLoopTest, LineLoopUIntIndices)
TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
{
// TODO(fjhenigman): UByte not yet supported in VertexArrayVk
ANGLE_SKIP_TEST_IF(IsVulkan());
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
ignoreD3D11SDKLayersWarnings();
......@@ -163,6 +169,11 @@ TEST_P(LineLoopTest, LineLoopUByteIndexBuffer)
TEST_P(LineLoopTest, LineLoopUShortIndexBuffer)
{
// TODO(lucferron): Looks like we have a bug supporting ushort as index buffers
// on line loops drawing.
// http://anglebug.com/2473
ANGLE_SKIP_TEST_IF(IsVulkan());
// Disable D3D11 SDK Layers warnings checks, see ANGLE issue 667 for details
ignoreD3D11SDKLayersWarnings();
......@@ -202,4 +213,9 @@ TEST_P(LineLoopTest, LineLoopUIntIndexBuffer)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(LineLoopTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
ANGLE_INSTANTIATE_TEST(LineLoopTest,
ES2_D3D9(),
ES2_D3D11(),
ES2_OPENGL(),
ES2_OPENGLES(),
ES2_VULKAN());
......@@ -747,6 +747,52 @@ TEST_P(SimpleOperationTest, DrawWithTexture)
EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
}
// Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingClientSideMemory)
{
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);
// If we use these indices to draw however, we should be drawing an hourglass.
std::vector<GLushort> indices{3, 2, 1, 0};
GLint positionLocation = glGetAttribLocation(program, "position");
ASSERT_NE(-1, positionLocation);
GLBuffer vertexBuffer;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
GL_STATIC_DRAW);
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());
glDisableVertexAttribArray(positionLocation);
ASSERT_GL_NO_ERROR();
int quarterWidth = getWindowWidth() / 4;
int quarterHeight = getWindowHeight() / 4;
// Bottom left
EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
// Top left
EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::green);
// Top right
EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::green);
// Verify line is closed between the 2 last vertices
EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
}
// Tests rendering to a user framebuffer.
TEST_P(SimpleOperationTest, RenderToTexture)
{
......
......@@ -1008,15 +1008,9 @@ TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
glUseProgram(program);
// We expect to draw a square with these 4 vertices with a drawArray call.
auto pixelPoints =
std::vector<Vector2>{{8.5f, 8.5f}, {8.5f, 24.5f}, {24.5f, 8.5f}, {24.5f, 24.5f}};
auto vertices = std::vector<Vector3>();
for (Vector2 pixelPoint : pixelPoints)
{
vertices.emplace_back(Vector3(pixelPoint[0] * 2 / getWindowWidth() - 1,
pixelPoint[1] * 2 / getWindowHeight() - 1, 0.0f));
}
std::vector<Vector3> vertices;
CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 8}, {24, 24}}, getWindowWidth(),
getWindowHeight(), &vertices);
// If we use these indices to draw however, we should be drawing an hourglass.
auto indices = std::vector<GLushort>{0, 2, 1, 3};
......@@ -1051,15 +1045,9 @@ TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
glUseProgram(program);
// We expect to draw a square with these 4 vertices with a drawArray call.
auto pixelPoints =
std::vector<Vector2>{{8.5f, 8.5f}, {8.5f, 24.5f}, {24.5f, 8.5f}, {24.5f, 24.5f}};
auto vertices = std::vector<Vector3>();
for (Vector2 pixelPoint : pixelPoints)
{
vertices.emplace_back(Vector3(pixelPoint[0] * 2 / getWindowWidth() - 1,
pixelPoint[1] * 2 / getWindowHeight() - 1, 0.0f));
}
std::vector<Vector3> vertices;
CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 8}, {24, 24}}, getWindowWidth(),
getWindowHeight(), &vertices);
// If we use these indices to draw however, we should be drawing an hourglass.
auto indices = std::vector<GLushort>{0, 2, 1, 3};
......
......@@ -139,6 +139,19 @@ testing::AssertionResult GLColor::ExpectNear(const GLColor &expected, const GLCo
return result;
}
void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
int windowWidth,
int windowHeight,
std::vector<Vector3> *outVertices)
{
for (Vector2 pixelPoint : pixelPoints)
{
outVertices->emplace_back(Vector3((pixelPoint[0] + 0.5f) * 2.0f / windowWidth - 1.0f,
(pixelPoint[1] + 0.5f) * 2.0f / windowHeight - 1.0f,
0.0f));
}
}
angle::Vector4 GLColor::toNormalizedVector() const
{
return angle::Vector4(ColorNorm(R), ColorNorm(G), ColorNorm(B), ColorNorm(A));
......
......@@ -111,6 +111,14 @@ static constexpr GLColor32F kFloatBlue = {0.0f, 0.0f, 1.0f, 1.0f};
struct WorkaroundsD3D;
// The input here for pixelPoints are the expected integer window coordinates, we add .5 to every
// one of them and re-scale the numbers to be between [-1,1]. Using this technique, we can make
// sure the rasterization stage will end up drawing pixels at the expected locations.
void CreatePixelCenterWindowCoords(const std::vector<Vector2> &pixelPoints,
int windowWidth,
int windowHeight,
std::vector<Vector3> *outVertices);
// Useful to cast any type to GLubyte.
template <typename TR, typename TG, typename TB, typename TA>
GLColor MakeGLColor(TR r, TG g, TB b, TA a)
......
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