Commit 78e39b3f by Luc Ferron Committed by Commit Bot

Vulkan: Line loops for indexed draw calls

Bug: angleproject:2335 Change-Id: Iabd6ae8181c6d3fb487f953a6fbf699db568a1c9 Reviewed-on: https://chromium-review.googlesource.com/941261 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent b27b03a2
......@@ -56,7 +56,7 @@ gl::Error BufferVk::setData(const gl::Context *context,
const VkImageUsageFlags usageFlags =
(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
// TODO(jmadill): Proper usage bit implementation. Likely will involve multiple backing
// buffers like in D3D11.
......
......@@ -161,6 +161,7 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
DrawType drawType,
int firstVertex,
int lastVertex,
ResourceVk *elementArrayBufferOverride,
vk::CommandBuffer **commandBuffer)
{
if (mode != mCurrentDrawMode)
......@@ -199,11 +200,12 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
}
// Ensure any writes to the VAO buffers are flushed before we read from them.
if (mVertexArrayDirty)
if (mVertexArrayDirty || elementArrayBufferOverride != nullptr)
{
mVertexArrayDirty = false;
vkVAO->updateDrawDependencies(renderNode, programGL->getActiveAttribLocationsMask(),
queueSerial, drawType);
elementArrayBufferOverride, queueSerial, drawType);
}
// Ensure any writes to the textures are flushed before we read from them.
......@@ -264,11 +266,14 @@ gl::Error ContextVk::setupDraw(const gl::Context *context,
gl::Error ContextVk::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
{
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(setupDraw(context, mode, DrawType::Arrays, first, first + count - 1, &commandBuffer));
ANGLE_TRY(setupDraw(context, mode, DrawType::Arrays, first, first + count - 1, nullptr,
&commandBuffer));
if (mode == GL_LINE_LOOP)
{
ANGLE_TRY(mLineLoopHandler.draw(this, first, count, commandBuffer));
ANGLE_TRY(mLineLoopHandler.createIndexBuffer(this, first, count));
mLineLoopHandler.bindIndexBuffer(VK_INDEX_TYPE_UINT32, &commandBuffer);
ANGLE_TRY(mLineLoopHandler.draw(count, commandBuffer));
}
else
{
......@@ -294,32 +299,49 @@ gl::Error ContextVk::drawElements(const gl::Context *context,
GLenum type,
const void *indices)
{
vk::CommandBuffer *commandBuffer;
// TODO(fjhenigman): calculate the index range and pass to setupDraw()
ANGLE_TRY(setupDraw(context, mode, DrawType::Elements, 0, 0, &commandBuffer));
const gl::Buffer *elementArrayBuffer =
mState.getState().getVertexArray()->getElementArrayBuffer().get();
ASSERT(elementArrayBuffer);
if (indices)
{
// TODO(jmadill): Buffer offsets and immediate data.
UNIMPLEMENTED();
return gl::InternalError() << "Only zero-offset index buffers are currently implemented.";
}
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
vk::CommandBuffer *commandBuffer = nullptr;
if (type == GL_UNSIGNED_BYTE)
if (mode == GL_LINE_LOOP)
{
// TODO(jmadill): Index translation.
UNIMPLEMENTED();
return gl::InternalError() << "Unsigned byte translation is not yet implemented.";
ANGLE_TRY(mLineLoopHandler.createIndexBufferFromElementArrayBuffer(
this, elementArrayBufferVk, GetVkIndexType(type), count));
// TODO(fjhenigman): calculate the index range and pass to setupDraw()
ANGLE_TRY(setupDraw(context, mode, DrawType::Elements, 0, 0,
mLineLoopHandler.getLineLoopBufferResource(), &commandBuffer));
mLineLoopHandler.bindIndexBuffer(GetVkIndexType(type), &commandBuffer);
commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0);
}
else
{
// TODO(fjhenigman): calculate the index range and pass to setupDraw()
ANGLE_TRY(setupDraw(context, mode, DrawType::Elements, 0, 0, nullptr, &commandBuffer));
const gl::Buffer *elementArrayBuffer =
mState.getState().getVertexArray()->getElementArrayBuffer().get();
ASSERT(elementArrayBuffer);
if (indices)
{
// TODO(jmadill): Buffer offsets and immediate data.
UNIMPLEMENTED();
return gl::InternalError()
<< "Only zero-offset index buffers are currently implemented.";
}
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
if (type == GL_UNSIGNED_BYTE)
{
// TODO(jmadill): Index translation.
UNIMPLEMENTED();
return gl::InternalError() << "Unsigned byte translation is not yet implemented.";
}
commandBuffer->bindIndexBuffer(elementArrayBufferVk->getVkBuffer(), 0, GetVkIndexType(type));
commandBuffer->drawIndexed(count, 1, 0, 0, 0);
commandBuffer->bindIndexBuffer(elementArrayBufferVk->getVkBuffer(), 0,
GetVkIndexType(type));
commandBuffer->drawIndexed(count, 1, 0, 0, 0);
}
return gl::NoError();
}
......
......@@ -168,6 +168,7 @@ class ContextVk : public ContextImpl
DrawType drawType,
int firstVertex,
int lastVertex,
ResourceVk *elementArrayBufferOverride,
vk::CommandBuffer **commandBuffer);
RendererVk *mRenderer;
......
......@@ -68,6 +68,7 @@ gl::Error StreamingBuffer::allocate(ContextVk *context,
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
ANGLE_TRY(mBuffer.init(device, createInfo));
ANGLE_TRY(vk::AllocateBufferMemory(renderer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mBuffer,
&mMemory, &mSize));
ANGLE_TRY(mMemory.map(device, 0, mSize, 0, &mMappedMemory));
......
......@@ -165,6 +165,7 @@ const gl::AttribArray<VkDeviceSize> &VertexArrayVk::getCurrentArrayBufferOffsets
void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
const gl::AttributesMask &activeAttribsMask,
ResourceVk *elementArrayBufferOverride,
Serial serial,
DrawType drawType)
{
......@@ -178,8 +179,15 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
// Handle the bound element array buffer.
if (drawType == DrawType::Elements)
{
ASSERT(mCurrentElementArrayBufferResource);
mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
if (elementArrayBufferOverride != nullptr)
{
elementArrayBufferOverride->onReadResource(readNode, serial);
}
else
{
ASSERT(mCurrentElementArrayBufferResource);
mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
}
}
}
......
......@@ -38,6 +38,7 @@ class VertexArrayVk : public VertexArrayImpl
void updateDrawDependencies(vk::CommandGraphNode *readNode,
const gl::AttributesMask &activeAttribsMask,
ResourceVk *elementArrayBufferOverride,
Serial serial,
DrawType drawType);
......
......@@ -10,9 +10,9 @@
#include "libANGLE/renderer/vulkan/vk_utils.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
......@@ -459,6 +459,15 @@ void CommandBuffer::copyBuffer(const vk::Buffer &srcBuffer,
vkCmdCopyBuffer(mHandle, srcBuffer.getHandle(), destBuffer.getHandle(), regionCount, regions);
}
void CommandBuffer::copyBuffer(const VkBuffer &srcBuffer,
const VkBuffer &destBuffer,
uint32_t regionCount,
const VkBufferCopy *regions)
{
ASSERT(valid());
vkCmdCopyBuffer(mHandle, srcBuffer, destBuffer, regionCount, regions);
}
void CommandBuffer::clearSingleColorImage(const vk::Image &image, const VkClearColorValue &color)
{
ASSERT(valid());
......@@ -1322,7 +1331,8 @@ void GarbageObject::destroy(VkDevice device)
LineLoopHandler::LineLoopHandler()
: mStreamingLineLoopIndicesData(
new StreamingBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kLineLoopStreamingBufferMinSize)),
new StreamingBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
kLineLoopStreamingBufferMinSize)),
mLineLoopIndexBuffer(VK_NULL_HANDLE),
mLineLoopIndexBufferOffset(VK_NULL_HANDLE)
{
......@@ -1330,10 +1340,12 @@ LineLoopHandler::LineLoopHandler()
LineLoopHandler::~LineLoopHandler() = default;
gl::Error LineLoopHandler::bindLineLoopIndexBuffer(ContextVk *contextVk,
int firstVertex,
int count,
vk::CommandBuffer **commandBuffer)
void LineLoopHandler::bindIndexBuffer(VkIndexType indexType, vk::CommandBuffer **commandBuffer)
{
(*commandBuffer)->bindIndexBuffer(mLineLoopIndexBuffer, mLineLoopIndexBufferOffset, indexType);
}
gl::Error LineLoopHandler::createIndexBuffer(ContextVk *contextVk, int firstVertex, int count)
{
int lastVertex = firstVertex + count;
if (mLineLoopIndexBuffer == VK_NULL_HANDLE || !mLineLoopBufferFirstIndex.valid() ||
......@@ -1363,8 +1375,48 @@ gl::Error LineLoopHandler::bindLineLoopIndexBuffer(ContextVk *contextVk,
mLineLoopBufferLastIndex = lastVertex;
}
(*commandBuffer)
->bindIndexBuffer(mLineLoopIndexBuffer, mLineLoopIndexBufferOffset, VK_INDEX_TYPE_UINT32);
return gl::NoError();
}
gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *contextVk,
BufferVk *bufferVk,
VkIndexType indexType,
int count)
{
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
if (mLineLoopIndexBuffer != VK_NULL_HANDLE)
{
return gl::NoError();
}
uint32_t *indices = nullptr;
// TODO: Use the signal_utils to know when the user's bufferVk has changed and if it did we copy
// again. Otherwise if we already created that fake index buffer we keep it and avoid recopying
// every time.
auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
ANGLE_TRY(mStreamingLineLoopIndicesData->allocate(
contextVk, unitSize * (count + 1), reinterpret_cast<uint8_t **>(&indices),
&mLineLoopIndexBuffer, &mLineLoopIndexBufferOffset));
VkBufferCopy copy1 = {0, mLineLoopIndexBufferOffset,
static_cast<VkDeviceSize>(count) * unitSize};
VkBufferCopy copy2 = {
0, mLineLoopIndexBufferOffset + static_cast<VkDeviceSize>(count) * unitSize, unitSize};
std::array<VkBufferCopy, 2> copies = {{copy1, copy2}};
vk::CommandBuffer *commandBuffer;
mStreamingLineLoopIndicesData->beginWriteResource(contextVk->getRenderer(), &commandBuffer);
Serial currentSerial = contextVk->getRenderer()->getCurrentQueueSerial();
bufferVk->onReadResource(mStreamingLineLoopIndicesData->getCurrentWritingNode(currentSerial),
currentSerial);
commandBuffer->copyBuffer(bufferVk->getVkBuffer().getHandle(), mLineLoopIndexBuffer, 2,
copies.data());
ANGLE_TRY(mStreamingLineLoopIndicesData->flush(contextVk));
return gl::NoError();
}
......@@ -1373,13 +1425,8 @@ void LineLoopHandler::destroy(VkDevice device)
mStreamingLineLoopIndicesData->destroy(device);
}
gl::Error LineLoopHandler::draw(ContextVk *contextVk,
int firstVertex,
int count,
CommandBuffer *commandBuffer)
gl::Error LineLoopHandler::draw(int count, CommandBuffer *commandBuffer)
{
ANGLE_TRY(bindLineLoopIndexBuffer(contextVk, firstVertex, count, &commandBuffer));
// Our first index is always 0 because that's how we set it up in the
// bindLineLoopIndexBuffer.
commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0);
......@@ -1387,6 +1434,10 @@ gl::Error LineLoopHandler::draw(ContextVk *contextVk,
return gl::NoError();
}
ResourceVk *LineLoopHandler::getLineLoopBufferResource()
{
return mStreamingLineLoopIndicesData.get();
}
} // namespace vk
namespace gl_vk
......
......@@ -346,6 +346,11 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
uint32_t regionCount,
const VkBufferCopy *regions);
void copyBuffer(const VkBuffer &srcBuffer,
const VkBuffer &destBuffer,
uint32_t regionCount,
const VkBufferCopy *regions);
void copySingleImage(const vk::Image &srcImage,
const vk::Image &destImage,
const gl::Box &copyRegion,
......@@ -681,15 +686,20 @@ class LineLoopHandler final : angle::NonCopyable
LineLoopHandler();
~LineLoopHandler();
void bindIndexBuffer(VkIndexType indexType, vk::CommandBuffer **commandBuffer);
gl::Error createIndexBuffer(ContextVk *contextVk, int firstVertex, int count);
gl::Error createIndexBufferFromElementArrayBuffer(ContextVk *contextVk,
BufferVk *bufferVk,
VkIndexType indexType,
int count);
void destroy(VkDevice device);
gl::Error draw(ContextVk *contextVk, int firstVertex, int count, CommandBuffer *commandBuffer);
gl::Error draw(int count, CommandBuffer *commandBuffer);
ResourceVk *getLineLoopBufferResource();
private:
gl::Error bindLineLoopIndexBuffer(ContextVk *contextVk,
int firstVertex,
int count,
vk::CommandBuffer **commandBuffer);
std::unique_ptr<StreamingBuffer> mStreamingLineLoopIndicesData;
VkBuffer mLineLoopIndexBuffer;
VkDeviceSize mLineLoopIndexBufferOffset;
......
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