Vulkan: Move Streaming data to VertexArrayVk.
Instead of the ContextVk owning the translations for the various
attributes, make the VertexArrayVk own them. This way they can
handle the dirty bit state notifications directly instead of
needing their own Observers.
Bug: angleproject:2389
Change-Id: I5e571ba6c563e820a4c0d5f92db35031e6f2428a
Reviewed-on: https://chromium-review.googlesource.com/989258
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 1ac5e3c..bacc486 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -38,44 +38,16 @@
namespace rx
{
-
-namespace
-{
-
-VkIndexType GetVkIndexType(GLenum glIndexType)
-{
- switch (glIndexType)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT:
- return VK_INDEX_TYPE_UINT16;
- case GL_UNSIGNED_INT:
- return VK_INDEX_TYPE_UINT32;
- default:
- UNREACHABLE();
- return VK_INDEX_TYPE_MAX_ENUM;
- }
-}
-
-constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
-constexpr size_t kDynamicIndexDataSize = 1024 * 8;
-
-} // anonymous namespace
-
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state),
mRenderer(renderer),
mCurrentDrawMode(GL_NONE),
mDynamicDescriptorPool(),
- mVertexArrayDirty(false),
mTexturesDirty(false),
- mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
- mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize)
+ mVertexArrayBindingHasChanged(false)
{
memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
- mDynamicVertexData.init(1);
- mDynamicIndexData.init(1);
}
ContextVk::~ContextVk()
@@ -84,12 +56,7 @@
void ContextVk::onDestroy(const gl::Context *context)
{
- VkDevice device = mRenderer->getDevice();
-
mDynamicDescriptorPool.destroy(mRenderer);
- mDynamicVertexData.destroy(device);
- mDynamicIndexData.destroy(device);
- mLineLoopHandler.destroy(device);
}
gl::Error ContextVk::initialize()
@@ -149,8 +116,8 @@
gl::Error ContextVk::setupDraw(const gl::Context *context,
const gl::DrawCallParams &drawCallParams,
- ResourceVk *elementArrayBufferOverride,
- vk::CommandBuffer **commandBufferOut)
+ vk::CommandGraphNode **drawNodeOut,
+ bool *newCommandBufferOut)
{
if (drawCallParams.mode() != mCurrentDrawMode)
{
@@ -166,12 +133,9 @@
const auto &state = mState.getState();
const gl::Program *programGL = state.getProgram();
ProgramVk *programVk = vk::GetImpl(programGL);
- const gl::VertexArray *vao = state.getVertexArray();
- VertexArrayVk *vkVAO = vk::GetImpl(vao);
const auto *drawFBO = state.getDrawFramebuffer();
FramebufferVk *vkFBO = vk::GetImpl(drawFBO);
Serial queueSerial = mRenderer->getCurrentQueueSerial();
- uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
vk::CommandGraphNode *graphNode = nullptr;
ANGLE_TRY(vkFBO->getCommandGraphNodeForDraw(context, &graphNode));
@@ -180,23 +144,15 @@
if (!graphNode->getInsideRenderPassCommands()->valid())
{
- mVertexArrayDirty = true;
mTexturesDirty = true;
+ *newCommandBufferOut = true;
ANGLE_TRY(graphNode->beginInsideRenderPassRecording(mRenderer, &commandBuffer));
}
else
{
- commandBuffer = graphNode->getInsideRenderPassCommands();
- }
-
- // Ensure any writes to the VAO buffers are flushed before we read from them.
- if (mVertexArrayDirty || elementArrayBufferOverride != nullptr)
- {
-
- mVertexArrayDirty = false;
- vkVAO->updateDrawDependencies(graphNode, programGL->getActiveAttribLocationsMask(),
- elementArrayBufferOverride, queueSerial,
- drawCallParams.isDrawElements());
+ *newCommandBufferOut = mVertexArrayBindingHasChanged;
+ mVertexArrayBindingHasChanged = false;
+ commandBuffer = graphNode->getInsideRenderPassCommands();
}
// Ensure any writes to the textures are flushed before we read from them.
@@ -224,9 +180,6 @@
}
commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline->get());
- ANGLE_TRY(vkVAO->streamVertexData(context, &mDynamicVertexData, drawCallParams));
- commandBuffer->bindVertexBuffers(0, maxAttrib, vkVAO->getCurrentArrayBufferHandles().data(),
- vkVAO->getCurrentArrayBufferOffsets().data());
// Update the queue serial for the pipeline object.
ASSERT(mCurrentPipeline && mCurrentPipeline->valid());
@@ -251,7 +204,7 @@
programVk->getDynamicOffsets());
}
- *commandBufferOut = commandBuffer;
+ *drawNodeOut = graphNode;
return gl::NoError();
}
@@ -259,19 +212,13 @@
{
const gl::DrawCallParams &drawCallParams = context->getParams<gl::DrawCallParams>();
- vk::CommandBuffer *commandBuffer = nullptr;
- ANGLE_TRY(setupDraw(context, drawCallParams, nullptr, &commandBuffer));
+ vk::CommandGraphNode *drawNode = nullptr;
+ bool newCommands = false;
+ ANGLE_TRY(setupDraw(context, drawCallParams, &drawNode, &newCommands));
- if (mode == GL_LINE_LOOP)
- {
- ANGLE_TRY(mLineLoopHandler.createIndexBuffer(this, first, count));
- mLineLoopHandler.bindIndexBuffer(VK_INDEX_TYPE_UINT32, &commandBuffer);
- ANGLE_TRY(mLineLoopHandler.draw(count, commandBuffer));
- }
- else
- {
- commandBuffer->draw(count, 1, first, 0);
- }
+ const gl::VertexArray *vertexArray = context->getGLState().getVertexArray();
+ VertexArrayVk *vertexArrayVk = vk::GetImpl(vertexArray);
+ ANGLE_TRY(vertexArrayVk->drawArrays(context, mRenderer, drawCallParams, drawNode, newCommands));
return gl::NoError();
}
@@ -294,80 +241,14 @@
{
const gl::DrawCallParams &drawCallParams = context->getParams<gl::DrawCallParams>();
- gl::VertexArray *vao = mState.getState().getVertexArray();
- const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- vk::CommandBuffer *commandBuffer = nullptr;
+ vk::CommandGraphNode *drawNode = nullptr;
+ bool newCommands = false;
+ ANGLE_TRY(setupDraw(context, drawCallParams, &drawNode, &newCommands));
- if (mode == GL_LINE_LOOP)
- {
- if (!elementArrayBuffer)
- {
- UNIMPLEMENTED();
- return gl::InternalError() << "Line loop indices in client memory not supported";
- }
-
- BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
-
- ANGLE_TRY(mLineLoopHandler.createIndexBufferFromElementArrayBuffer(
- this, elementArrayBufferVk, GetVkIndexType(type), count));
-
- // TODO(fjhenigman): calculate the index range and pass to setupDraw()
- ANGLE_TRY(setupDraw(context, drawCallParams, mLineLoopHandler.getLineLoopBufferResource(),
- &commandBuffer));
-
- mLineLoopHandler.bindIndexBuffer(GetVkIndexType(type), &commandBuffer);
- commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0);
- }
- else
- {
- ContextVk *contextVk = vk::GetImpl(context);
- gl::IndexRange range;
- VkBuffer buffer = VK_NULL_HANDLE;
- uint32_t offset = 0;
-
- if (elementArrayBuffer)
- {
- if (type == GL_UNSIGNED_BYTE)
- {
- // TODO(fjhenigman): Index format translation.
- UNIMPLEMENTED();
- return gl::InternalError() << "Unsigned byte translation is not implemented for "
- << "indices in a buffer object";
- }
-
- BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
- buffer = elementArrayBufferVk->getVkBuffer().getHandle();
- offset = 0;
- }
- else
- {
- const GLsizei amount = sizeof(GLushort) * count;
- GLubyte *dst = nullptr;
-
- ANGLE_TRY(
- mDynamicIndexData.allocate(contextVk, amount, &dst, &buffer, &offset, nullptr));
- if (type == GL_UNSIGNED_BYTE)
- {
- // Unsigned bytes don't have direct support in Vulkan so we have to expand the
- // memory to a GLushort.
- const GLubyte *in = static_cast<const GLubyte *>(indices);
- GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
- for (GLsizei index = 0; index < count; index++)
- {
- expandedDst[index] = static_cast<GLushort>(in[index]);
- }
- }
- else
- {
- memcpy(dst, indices, amount);
- }
- ANGLE_TRY(mDynamicIndexData.flush(contextVk));
- }
-
- ANGLE_TRY(setupDraw(context, drawCallParams, nullptr, &commandBuffer));
- commandBuffer->bindIndexBuffer(buffer, offset, GetVkIndexType(type));
- commandBuffer->drawIndexed(count, 1, 0, 0, 0);
- }
+ gl::VertexArray *vao = mState.getState().getVertexArray();
+ VertexArrayVk *vertexArrayVk = vk::GetImpl(vao);
+ ANGLE_TRY(
+ vertexArrayVk->drawElements(context, mRenderer, drawCallParams, drawNode, newCommands));
return gl::NoError();
}
@@ -636,7 +517,8 @@
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
break;
case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
- mVertexArrayDirty = true;
+ invalidateCurrentPipeline();
+ mVertexArrayBindingHasChanged = true;
break;
case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
WARN() << "DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING unimplemented";
@@ -823,13 +705,6 @@
mCurrentPipeline = nullptr;
}
-void ContextVk::onVertexArrayChange()
-{
- // TODO(jmadill): Does not handle dependent state changes.
- mVertexArrayDirty = true;
- invalidateCurrentPipeline();
-}
-
gl::Error ContextVk::dispatchCompute(const gl::Context *context,
GLuint numGroupsX,
GLuint numGroupsY,
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h
index 779d500..a9aeeab 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -155,7 +155,6 @@
RendererVk *getRenderer() { return mRenderer; }
void invalidateCurrentPipeline();
- void onVertexArrayChange();
DynamicDescriptorPool *getDynamicDescriptorPool();
@@ -167,8 +166,8 @@
gl::Error initPipeline(const gl::Context *context);
gl::Error setupDraw(const gl::Context *context,
const gl::DrawCallParams &drawCallParams,
- ResourceVk *elementArrayBufferOverride,
- vk::CommandBuffer **commandBufferOut);
+ vk::CommandGraphNode **drawNodeOut,
+ bool *newCommandBufferOut);
RendererVk *mRenderer;
vk::PipelineAndSerial *mCurrentPipeline;
@@ -183,17 +182,12 @@
DynamicDescriptorPool mDynamicDescriptorPool;
// Triggers adding dependencies to the command graph.
- bool mVertexArrayDirty;
bool mTexturesDirty;
+ bool mVertexArrayBindingHasChanged;
// Cached clear value for color and depth/stencil.
VkClearValue mClearColorValue;
VkClearValue mClearDepthStencilValue;
-
- DynamicBuffer mDynamicVertexData;
- DynamicBuffer mDynamicIndexData;
-
- vk::LineLoopHandler mLineLoopHandler;
};
} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/DynamicBuffer.cpp b/src/libANGLE/renderer/vulkan/DynamicBuffer.cpp
index 9528cf3..04768fc 100644
--- a/src/libANGLE/renderer/vulkan/DynamicBuffer.cpp
+++ b/src/libANGLE/renderer/vulkan/DynamicBuffer.cpp
@@ -44,7 +44,7 @@
return mAlignment > 0;
}
-vk::Error DynamicBuffer::allocate(ContextVk *context,
+vk::Error DynamicBuffer::allocate(RendererVk *renderer,
size_t sizeInBytes,
uint8_t **ptrOut,
VkBuffer *handleOut,
@@ -52,11 +52,7 @@
bool *outNewBufferAllocated)
{
ASSERT(valid());
- RendererVk *renderer = context->getRenderer();
-
- // TODO(fjhenigman): Update this when we have buffers that need to
- // persist longer than one frame.
- updateQueueSerial(renderer->getCurrentQueueSerial());
+ VkDevice device = renderer->getDevice();
size_t sizeToAllocate = roundUp(sizeInBytes, mAlignment);
@@ -65,16 +61,15 @@
if (!checkedNextWriteOffset.IsValid() || checkedNextWriteOffset.ValueOrDie() > mSize)
{
- VkDevice device = context->getDevice();
-
if (mMappedMemory)
{
- ANGLE_TRY(flush(context));
+ ANGLE_TRY(flush(device));
mMemory.unmap(device);
mMappedMemory = nullptr;
}
- renderer->releaseResource(*this, &mBuffer);
- renderer->releaseResource(*this, &mMemory);
+ Serial currentSerial = renderer->getCurrentQueueSerial();
+ renderer->releaseObject(currentSerial, &mBuffer);
+ renderer->releaseObject(currentSerial, &mMemory);
VkBufferCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@@ -121,7 +116,7 @@
return vk::NoError();
}
-vk::Error DynamicBuffer::flush(ContextVk *context)
+vk::Error DynamicBuffer::flush(VkDevice device)
{
if (mNextWriteOffset > mLastFlushOffset)
{
@@ -131,7 +126,7 @@
range.memory = mMemory.getHandle();
range.offset = mLastFlushOffset;
range.size = mNextWriteOffset - mLastFlushOffset;
- ANGLE_VK_TRY(vkFlushMappedMemoryRanges(context->getDevice(), 1, &range));
+ ANGLE_VK_TRY(vkFlushMappedMemoryRanges(device, 1, &range));
mLastFlushOffset = mNextWriteOffset;
}
diff --git a/src/libANGLE/renderer/vulkan/DynamicBuffer.h b/src/libANGLE/renderer/vulkan/DynamicBuffer.h
index b6dc7fa..48dce8e 100644
--- a/src/libANGLE/renderer/vulkan/DynamicBuffer.h
+++ b/src/libANGLE/renderer/vulkan/DynamicBuffer.h
@@ -20,16 +20,17 @@
{
public:
DynamicBuffer(VkBufferUsageFlags usage, size_t minSize);
+ ~DynamicBuffer();
+
void init(size_t alignment);
bool valid();
- ~DynamicBuffer();
- vk::Error allocate(ContextVk *context,
+ vk::Error allocate(RendererVk *renderer,
size_t sizeInBytes,
uint8_t **ptrOut,
VkBuffer *handleOut,
uint32_t *offsetOut,
bool *outNewBufferAllocated);
- vk::Error flush(ContextVk *context);
+ vk::Error flush(VkDevice device);
void destroy(VkDevice device);
VkBuffer getCurrentBufferHandle() const;
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index e2e958b..a3a7c36 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -113,8 +113,8 @@
}
}
-vk::Error SyncDefaultUniformBlock(ContextVk *contextVk,
- DynamicBuffer &dynamicBuffer,
+vk::Error SyncDefaultUniformBlock(RendererVk *renderer,
+ DynamicBuffer *dynamicBuffer,
const angle::MemoryBuffer &bufferData,
uint32_t *outOffset,
bool *outBufferModified)
@@ -123,11 +123,11 @@
uint8_t *data = nullptr;
VkBuffer *outBuffer = nullptr;
uint32_t offset;
- ANGLE_TRY(dynamicBuffer.allocate(contextVk, bufferData.size(), &data, outBuffer, &offset,
- outBufferModified));
+ ANGLE_TRY(dynamicBuffer->allocate(renderer, bufferData.size(), &data, outBuffer, &offset,
+ outBufferModified));
*outOffset = offset;
memcpy(data, bufferData.data(), bufferData.size());
- ANGLE_TRY(dynamicBuffer.flush(contextVk));
+ ANGLE_TRY(dynamicBuffer->flush(renderer->getDevice()));
return vk::NoError();
}
@@ -754,7 +754,7 @@
if (uniformBlock.uniformsDirty)
{
bool bufferModified = false;
- ANGLE_TRY(SyncDefaultUniformBlock(contextVk, uniformBlock.storage,
+ ANGLE_TRY(SyncDefaultUniformBlock(contextVk->getRenderer(), &uniformBlock.storage,
uniformBlock.uniformData,
&mUniformBlocksOffsets[index], &bufferModified));
uniformBlock.uniformsDirty = false;
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index df7bf21..3114538 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -15,17 +15,29 @@
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
namespace rx
{
+namespace
+{
+constexpr size_t kDynamicVertexDataSize = 1024 * 1024;
+constexpr size_t kDynamicIndexDataSize = 1024 * 8;
+} // anonymous namespace
VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
: VertexArrayImpl(state),
mCurrentArrayBufferHandles{},
mCurrentArrayBufferOffsets{},
mCurrentArrayBufferResources{},
- mCurrentElementArrayBufferResource(nullptr)
+ mCurrentElementArrayBufferHandle(VK_NULL_HANDLE),
+ mCurrentElementArrayBufferOffset(0),
+ mCurrentElementArrayBufferResource(nullptr),
+ mDynamicVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kDynamicVertexDataSize),
+ mDynamicIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kDynamicIndexDataSize),
+ mVertexBuffersDirty(false),
+ mIndexBufferDirty(false)
{
mCurrentArrayBufferHandles.fill(VK_NULL_HANDLE);
mCurrentArrayBufferOffsets.fill(0);
@@ -33,6 +45,9 @@
mPackedInputBindings.fill({0, 0});
mPackedInputAttributes.fill({0, 0, 0});
+
+ mDynamicVertexData.init(1);
+ mDynamicIndexData.init(1);
}
VertexArrayVk::~VertexArrayVk()
@@ -41,29 +56,27 @@
void VertexArrayVk::destroy(const gl::Context *context)
{
+ VkDevice device = vk::GetImpl(context)->getRenderer()->getDevice();
+
+ mDynamicVertexData.destroy(device);
+ mDynamicIndexData.destroy(device);
+ mLineLoopHandler.destroy(device);
}
-gl::AttributesMask VertexArrayVk::getAttribsToStream(const gl::Context *context) const
-{
- const gl::Program *programGL = context->getGLState().getProgram();
- return mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
-}
-
-gl::Error VertexArrayVk::streamVertexData(const gl::Context *context,
- DynamicBuffer *dynamicBuffer,
+gl::Error VertexArrayVk::streamVertexData(RendererVk *renderer,
+ const gl::AttributesMask &attribsToStream,
const gl::DrawCallParams &drawCallParams)
{
- ContextVk *contextVk = vk::GetImpl(context);
+ ASSERT(!attribsToStream.none());
+
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
- ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
-
const size_t lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
// TODO(fjhenigman): When we have a bunch of interleaved attributes, they end up
// un-interleaved, wasting space and copying time. Consider improving on that.
- for (auto attribIndex : getAttribsToStream(context))
+ for (auto attribIndex : attribsToStream)
{
const gl::VertexAttribute &attrib = attribs[attribIndex];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
@@ -86,14 +99,48 @@
lastVertex * binding.getStride() + gl::ComputeVertexAttributeTypeSize(attrib);
uint8_t *dst = nullptr;
uint32_t offset = 0;
- ANGLE_TRY(dynamicBuffer->allocate(
- contextVk, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
+ ANGLE_TRY(mDynamicVertexData.allocate(
+ renderer, lastByte, &dst, &mCurrentArrayBufferHandles[attribIndex], &offset, nullptr));
mCurrentArrayBufferOffsets[attribIndex] = static_cast<VkDeviceSize>(offset);
memcpy(dst + firstByte, static_cast<const uint8_t *>(attrib.pointer) + firstByte,
lastByte - firstByte);
}
- ANGLE_TRY(dynamicBuffer->flush(contextVk));
+ ANGLE_TRY(mDynamicVertexData.flush(renderer->getDevice()));
+ return gl::NoError();
+}
+
+gl::Error VertexArrayVk::streamIndexData(RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams)
+{
+ ASSERT(!mState.getElementArrayBuffer().get());
+
+ uint32_t offset = 0;
+
+ const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
+ GLubyte *dst = nullptr;
+
+ ANGLE_TRY(mDynamicIndexData.allocate(renderer, amount, &dst, &mCurrentElementArrayBufferHandle,
+ &offset, nullptr));
+ if (drawCallParams.type() == GL_UNSIGNED_BYTE)
+ {
+ // Unsigned bytes don't have direct support in Vulkan so we have to expand the
+ // memory to a GLushort.
+ const GLubyte *in = static_cast<const GLubyte *>(drawCallParams.indices());
+ GLushort *expandedDst = reinterpret_cast<GLushort *>(dst);
+ for (GLsizei index = 0; index < drawCallParams.indexCount(); index++)
+ {
+ expandedDst[index] = static_cast<GLushort>(in[index]);
+ }
+ }
+ else
+ {
+ memcpy(dst, drawCallParams.indices(), amount);
+ }
+ ANGLE_TRY(mDynamicIndexData.flush(renderer->getDevice()));
+
+ mCurrentElementArrayBufferOffset = offset;
+
return gl::NoError();
}
@@ -104,9 +151,10 @@
{
ASSERT(dirtyBits.any());
+ bool invalidatePipeline = false;
+
// Invalidate current pipeline.
ContextVk *contextVk = vk::GetImpl(context);
- contextVk->onVertexArrayChange();
// Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
// TODO(jmadill): Handle buffer storage changes.
@@ -122,16 +170,24 @@
gl::Buffer *bufferGL = mState.getElementArrayBuffer().get();
if (bufferGL)
{
- mCurrentElementArrayBufferResource = vk::GetImpl(bufferGL);
+ BufferVk *bufferVk = vk::GetImpl(bufferGL);
+ mCurrentElementArrayBufferResource = bufferVk;
+ mCurrentElementArrayBufferHandle = bufferVk->getVkBuffer().getHandle();
+ mCurrentElementArrayBufferOffset = 0;
}
else
{
mCurrentElementArrayBufferResource = nullptr;
+ mCurrentElementArrayBufferHandle = VK_NULL_HANDLE;
+ mCurrentElementArrayBufferOffset = 0;
}
+ mIndexBufferDirty = true;
break;
}
case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
+ mLineLoopBufferFirstIndex.reset();
+ mLineLoopBufferLastIndex.reset();
break;
default:
@@ -170,11 +226,19 @@
mClientMemoryAttribs.reset(attribIndex);
UNIMPLEMENTED();
}
+
+ invalidatePipeline = true;
break;
}
}
}
+ if (invalidatePipeline)
+ {
+ mVertexBuffersDirty = true;
+ contextVk->invalidateCurrentPipeline();
+ }
+
return gl::NoError();
}
@@ -188,30 +252,25 @@
return mCurrentArrayBufferOffsets;
}
-void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
- const gl::AttributesMask &activeAttribsMask,
- ResourceVk *elementArrayBufferOverride,
- Serial serial,
- bool isDrawElements)
+void VertexArrayVk::updateArrayBufferReadDependencies(vk::CommandGraphNode *drawNode,
+ const gl::AttributesMask &activeAttribsMask,
+ Serial serial)
{
// Handle the bound array buffers.
- for (auto attribIndex : activeAttribsMask)
+ for (size_t attribIndex : activeAttribsMask)
{
if (mCurrentArrayBufferResources[attribIndex])
- mCurrentArrayBufferResources[attribIndex]->onReadResource(readNode, serial);
+ mCurrentArrayBufferResources[attribIndex]->onReadResource(drawNode, serial);
}
+}
+void VertexArrayVk::updateElementArrayBufferReadDependency(vk::CommandGraphNode *drawNode,
+ Serial serial)
+{
// Handle the bound element array buffer.
- if (isDrawElements)
+ if (mCurrentElementArrayBufferResource)
{
- if (elementArrayBufferOverride != nullptr)
- {
- elementArrayBufferOverride->onReadResource(readNode, serial);
- }
- else if (mCurrentElementArrayBufferResource != nullptr)
- {
- mCurrentElementArrayBufferResource->onReadResource(readNode, serial);
- }
+ mCurrentElementArrayBufferResource->onReadResource(drawNode, serial);
}
}
@@ -271,4 +330,155 @@
attribDesc.offset = static_cast<uint32_t>(ComputeVertexAttributeOffset(attrib, binding));
}
+gl::Error VertexArrayVk::drawArrays(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer)
+{
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ ASSERT(commandBuffer->valid());
+
+ ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
+
+ if (drawCallParams.mode() != GL_LINE_LOOP)
+ {
+ commandBuffer->draw(drawCallParams.vertexCount(), 1, drawCallParams.firstVertex(), 0);
+ return gl::NoError();
+ }
+
+ // Handle GL_LINE_LOOP drawArrays.
+ int lastVertex = drawCallParams.firstVertex() + drawCallParams.vertexCount();
+ if (!mLineLoopBufferFirstIndex.valid() || !mLineLoopBufferLastIndex.valid() ||
+ mLineLoopBufferFirstIndex != drawCallParams.firstVertex() ||
+ mLineLoopBufferLastIndex != lastVertex)
+ {
+ ANGLE_TRY(mLineLoopHandler.createIndexBuffer(renderer, drawCallParams,
+ &mCurrentElementArrayBufferHandle,
+ &mCurrentElementArrayBufferOffset));
+
+ mLineLoopBufferFirstIndex = drawCallParams.firstVertex();
+ mLineLoopBufferLastIndex = lastVertex;
+ }
+
+ commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
+ mCurrentElementArrayBufferOffset, VK_INDEX_TYPE_UINT32);
+
+ vk::LineLoopHandler::Draw(drawCallParams.vertexCount(), commandBuffer);
+
+ return gl::NoError();
+}
+
+gl::Error VertexArrayVk::drawElements(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer)
+{
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ ASSERT(commandBuffer->valid());
+
+ if (drawCallParams.mode() != GL_LINE_LOOP)
+ {
+ ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
+ commandBuffer->drawIndexed(drawCallParams.indexCount(), 1, 0, 0, 0);
+ return gl::NoError();
+ }
+
+ // 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());
+
+ ANGLE_TRY(mLineLoopHandler.createIndexBufferFromElementArrayBuffer(
+ renderer, elementArrayBufferVk, indexType, drawCallParams.indexCount(),
+ &mCurrentElementArrayBufferHandle, &mCurrentElementArrayBufferOffset));
+
+ ANGLE_TRY(onIndexedDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
+ vk::LineLoopHandler::Draw(drawCallParams.indexCount(), commandBuffer);
+
+ return gl::NoError();
+}
+
+gl::Error VertexArrayVk::onDraw(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer)
+{
+ const gl::State &state = context->getGLState();
+ const gl::Program *programGL = state.getProgram();
+ const gl::AttributesMask &activeAttribs = programGL->getActiveAttribLocationsMask();
+ uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
+
+ if (mClientMemoryAttribs.any())
+ {
+ const gl::AttributesMask &attribsToStream = (mClientMemoryAttribs & activeAttribs);
+ if (attribsToStream.any())
+ {
+ ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
+ ANGLE_TRY(streamVertexData(renderer, attribsToStream, drawCallParams));
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
+ mCurrentArrayBufferOffsets.data());
+ }
+ }
+ else if (mVertexBuffersDirty || newCommandBuffer)
+ {
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
+ mCurrentArrayBufferOffsets.data());
+ updateArrayBufferReadDependencies(drawNode, activeAttribs,
+ renderer->getCurrentQueueSerial());
+ mVertexBuffersDirty = false;
+ }
+
+ return gl::NoError();
+}
+
+gl::Error VertexArrayVk::onIndexedDraw(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer)
+{
+ ANGLE_TRY(onDraw(context, renderer, drawCallParams, drawNode, newCommandBuffer));
+
+ if (!mState.getElementArrayBuffer().get())
+ {
+ ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
+ ANGLE_TRY(streamIndexData(renderer, drawCallParams));
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
+ mCurrentElementArrayBufferOffset,
+ gl_vk::GetIndexType(drawCallParams.type()));
+ }
+ else if (mIndexBufferDirty || newCommandBuffer)
+ {
+ if (drawCallParams.type() == GL_UNSIGNED_BYTE)
+ {
+ // TODO(fjhenigman): Index format translation.
+ UNIMPLEMENTED();
+ return gl::InternalError()
+ << "Unsigned byte translation is not implemented for indices in a buffer object";
+ }
+
+ vk::CommandBuffer *commandBuffer = drawNode->getInsideRenderPassCommands();
+ commandBuffer->bindIndexBuffer(mCurrentElementArrayBufferHandle,
+ mCurrentElementArrayBufferOffset,
+ gl_vk::GetIndexType(drawCallParams.type()));
+ updateElementArrayBufferReadDependency(drawNode, renderer->getCurrentQueueSerial());
+ mIndexBufferDirty = false;
+ }
+
+ return gl::NoError();
+}
+
} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
index 90a1b54..917f3aa 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/vulkan/DynamicBuffer.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
namespace gl
@@ -31,10 +32,6 @@
void destroy(const gl::Context *context) override;
- gl::Error streamVertexData(const gl::Context *context,
- DynamicBuffer *dynamicBuffer,
- const gl::DrawCallParams &drawCallParams);
-
gl::Error syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits,
const gl::VertexArray::DirtyAttribBitsArray &attribBits,
@@ -43,14 +40,20 @@
const gl::AttribArray<VkBuffer> &getCurrentArrayBufferHandles() const;
const gl::AttribArray<VkDeviceSize> &getCurrentArrayBufferOffsets() const;
- void updateDrawDependencies(vk::CommandGraphNode *readNode,
- const gl::AttributesMask &activeAttribsMask,
- ResourceVk *elementArrayBufferOverride,
- Serial serial,
- bool isDrawElements);
-
void getPackedInputDescriptions(vk::PipelineDesc *pipelineDesc);
+ // Draw call handling.
+ gl::Error drawArrays(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer);
+ gl::Error drawElements(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer);
+
private:
// This will update any dirty packed input descriptions, regardless if they're used by the
// active program. This could lead to slight inefficiencies when the app would repeatedly
@@ -62,11 +65,34 @@
const gl::VertexBinding &binding,
const gl::VertexAttribute &attrib);
- gl::AttributesMask getAttribsToStream(const gl::Context *context) const;
+ void updateArrayBufferReadDependencies(vk::CommandGraphNode *drawNode,
+ const gl::AttributesMask &activeAttribsMask,
+ Serial serial);
+
+ void updateElementArrayBufferReadDependency(vk::CommandGraphNode *drawNode, Serial serial);
+
+ gl::Error streamVertexData(RendererVk *renderer,
+ const gl::AttributesMask &attribsToStream,
+ const gl::DrawCallParams &drawCallParams);
+
+ gl::Error streamIndexData(RendererVk *renderer, const gl::DrawCallParams &drawCallParams);
+
+ gl::Error onDraw(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer);
+ gl::Error onIndexedDraw(const gl::Context *context,
+ RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ vk::CommandGraphNode *drawNode,
+ bool newCommandBuffer);
gl::AttribArray<VkBuffer> mCurrentArrayBufferHandles;
gl::AttribArray<VkDeviceSize> mCurrentArrayBufferOffsets;
gl::AttribArray<ResourceVk *> mCurrentArrayBufferResources;
+ VkBuffer mCurrentElementArrayBufferHandle;
+ VkDeviceSize mCurrentElementArrayBufferOffset;
ResourceVk *mCurrentElementArrayBufferResource;
// Keep a cache of binding and attribute descriptions for easy pipeline updates.
@@ -78,6 +104,17 @@
// Which attributes need to be copied from client memory.
// TODO(jmadill): Move this to VertexArrayState. http://anglebug.com/2389
gl::AttributesMask mClientMemoryAttribs;
+
+ DynamicBuffer mDynamicVertexData;
+ DynamicBuffer mDynamicIndexData;
+
+ vk::LineLoopHandler mLineLoopHandler;
+ Optional<int> mLineLoopBufferFirstIndex;
+ Optional<int> mLineLoopBufferLastIndex;
+
+ // Cache variable for determining whether or not to store new dependencies in the node.
+ bool mVertexBuffersDirty;
+ bool mIndexBufferDirty;
};
} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp
index 02a4468..32d5271 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -1179,93 +1179,84 @@
: mObserverBinding(this, 0u),
mDynamicLineLoopIndicesData(
new DynamicBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
- kLineLoopDynamicBufferMinSize)),
- mLineLoopIndexBuffer(VK_NULL_HANDLE),
- mLineLoopIndexBufferOffset(VK_NULL_HANDLE)
+ kLineLoopDynamicBufferMinSize))
{
mDynamicLineLoopIndicesData->init(1);
}
LineLoopHandler::~LineLoopHandler() = default;
-void LineLoopHandler::bindIndexBuffer(VkIndexType indexType, vk::CommandBuffer **commandBuffer)
+gl::Error LineLoopHandler::createIndexBuffer(RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ VkBuffer *bufferHandleOut,
+ VkDeviceSize *offsetOut)
{
- (*commandBuffer)->bindIndexBuffer(mLineLoopIndexBuffer, mLineLoopIndexBufferOffset, indexType);
-}
+ uint32_t *indices = nullptr;
+ size_t allocateBytes = sizeof(uint32_t) * (drawCallParams.vertexCount() + 1);
+ uint32_t offset = 0;
+ ANGLE_TRY(mDynamicLineLoopIndicesData->allocate(renderer, allocateBytes,
+ reinterpret_cast<uint8_t **>(&indices),
+ bufferHandleOut, &offset, nullptr));
+ *offsetOut = static_cast<VkDeviceSize>(offset);
-gl::Error LineLoopHandler::createIndexBuffer(ContextVk *contextVk, int firstVertex, int count)
-{
- int lastVertex = firstVertex + count;
- if (mLineLoopIndexBuffer == VK_NULL_HANDLE || !mLineLoopBufferFirstIndex.valid() ||
- !mLineLoopBufferLastIndex.valid() || mLineLoopBufferFirstIndex != firstVertex ||
- mLineLoopBufferLastIndex != lastVertex)
+ uint32_t unsignedFirstVertex = static_cast<uint32_t>(drawCallParams.firstVertex());
+ uint32_t vertexCount = (drawCallParams.vertexCount() + unsignedFirstVertex);
+ for (uint32_t vertexIndex = unsignedFirstVertex; vertexIndex < vertexCount; vertexIndex++)
{
- uint32_t *indices = nullptr;
- size_t allocateBytes = sizeof(uint32_t) * (count + 1);
- ANGLE_TRY(mDynamicLineLoopIndicesData->allocate(
- contextVk, allocateBytes, reinterpret_cast<uint8_t **>(&indices), &mLineLoopIndexBuffer,
- &mLineLoopIndexBufferOffset, nullptr));
-
- auto unsignedFirstVertex = static_cast<uint32_t>(firstVertex);
- for (auto vertexIndex = unsignedFirstVertex; vertexIndex < (count + unsignedFirstVertex);
- vertexIndex++)
- {
- *indices++ = vertexIndex;
- }
- *indices = unsignedFirstVertex;
-
- // Since we are not using the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT flag when creating the
- // device memory in the DynamicBuffer, we always need to make sure we flush it after
- // writing.
- ANGLE_TRY(mDynamicLineLoopIndicesData->flush(contextVk));
-
- mLineLoopBufferFirstIndex = firstVertex;
- mLineLoopBufferLastIndex = lastVertex;
+ *indices++ = vertexIndex;
}
+ *indices = unsignedFirstVertex;
+
+ // Since we are not using the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT flag when creating the
+ // device memory in the StreamingBuffer, we always need to make sure we flush it after
+ // writing.
+ ANGLE_TRY(mDynamicLineLoopIndicesData->flush(renderer->getDevice()));
return gl::NoError();
}
-gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *contextVk,
- BufferVk *bufferVk,
+gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(RendererVk *renderer,
+ BufferVk *elementArrayBufferVk,
VkIndexType indexType,
- int count)
+ int indexCount,
+ VkBuffer *bufferHandleOut,
+ VkDeviceSize *bufferOffsetOut)
{
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
- if (bufferVk == mObserverBinding.getSubject() && mLineLoopIndexBuffer != VK_NULL_HANDLE)
+ if (elementArrayBufferVk == mObserverBinding.getSubject())
{
return gl::NoError();
}
// We want to know if the bufferVk changes at any point in time, because if it does we need to
// recopy our data on the next call.
- mObserverBinding.bind(bufferVk);
+ mObserverBinding.bind(elementArrayBufferVk);
uint32_t *indices = nullptr;
+ uint32_t offset = 0;
auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
- size_t allocateBytes = unitSize * (count + 1);
- ANGLE_TRY(mDynamicLineLoopIndicesData->allocate(
- contextVk, allocateBytes, reinterpret_cast<uint8_t **>(&indices), &mLineLoopIndexBuffer,
- &mLineLoopIndexBufferOffset, nullptr));
+ size_t allocateBytes = unitSize * (indexCount + 1);
+ ANGLE_TRY(mDynamicLineLoopIndicesData->allocate(renderer, allocateBytes,
+ reinterpret_cast<uint8_t **>(&indices),
+ bufferHandleOut, &offset, nullptr));
+ *bufferOffsetOut = static_cast<VkDeviceSize>(offset);
- VkBufferCopy copy1 = {0, mLineLoopIndexBufferOffset,
- static_cast<VkDeviceSize>(count) * unitSize};
- VkBufferCopy copy2 = {
- 0, mLineLoopIndexBufferOffset + static_cast<VkDeviceSize>(count) * unitSize, unitSize};
+ VkBufferCopy copy1 = {0, offset, static_cast<VkDeviceSize>(indexCount) * unitSize};
+ VkBufferCopy copy2 = {0, offset + static_cast<VkDeviceSize>(indexCount) * unitSize, unitSize};
std::array<VkBufferCopy, 2> copies = {{copy1, copy2}};
vk::CommandBuffer *commandBuffer;
- mDynamicLineLoopIndicesData->beginWriteResource(contextVk->getRenderer(), &commandBuffer);
+ mDynamicLineLoopIndicesData->beginWriteResource(renderer, &commandBuffer);
- Serial currentSerial = contextVk->getRenderer()->getCurrentQueueSerial();
- bufferVk->onReadResource(mDynamicLineLoopIndicesData->getCurrentWritingNode(currentSerial),
- currentSerial);
- commandBuffer->copyBuffer(bufferVk->getVkBuffer().getHandle(), mLineLoopIndexBuffer, 2,
+ Serial currentSerial = renderer->getCurrentQueueSerial();
+ elementArrayBufferVk->onReadResource(
+ mDynamicLineLoopIndicesData->getCurrentWritingNode(currentSerial), currentSerial);
+ commandBuffer->copyBuffer(elementArrayBufferVk->getVkBuffer().getHandle(), *bufferHandleOut, 2,
copies.data());
- ANGLE_TRY(mDynamicLineLoopIndicesData->flush(contextVk));
+ ANGLE_TRY(mDynamicLineLoopIndicesData->flush(renderer->getDevice()));
return gl::NoError();
}
@@ -1275,13 +1266,11 @@
mDynamicLineLoopIndicesData->destroy(device);
}
-gl::Error LineLoopHandler::draw(int count, CommandBuffer *commandBuffer)
+// static
+void LineLoopHandler::Draw(int count, CommandBuffer *commandBuffer)
{
- // Our first index is always 0 because that's how we set it up in the
- // bindLineLoopIndexBuffer.
+ // Our first index is always 0 because that's how we set it up in createIndexBuffer*.
commandBuffer->drawIndexed(count + 1, 1, 0, 0, 0);
-
- return gl::NoError();
}
ResourceVk *LineLoopHandler::getLineLoopBufferResource()
@@ -1296,7 +1285,7 @@
// Indicate we want to recopy on next draw since something changed in the buffer.
if (message == angle::SubjectMessage::CONTENTS_CHANGED)
{
- mLineLoopIndexBuffer = VK_NULL_HANDLE;
+ mObserverBinding.reset();
}
}
@@ -1768,6 +1757,21 @@
return VK_COMPONENT_SWIZZLE_IDENTITY;
}
}
+
+VkIndexType GetIndexType(GLenum elementType)
+{
+ switch (elementType)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ return VK_INDEX_TYPE_UINT16;
+ case GL_UNSIGNED_INT:
+ return VK_INDEX_TYPE_UINT32;
+ default:
+ UNREACHABLE();
+ return VK_INDEX_TYPE_MAX_ENUM;
+ }
+}
} // namespace gl_vk
ResourceVk::ResourceVk() : mCurrentWritingNode(nullptr)
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index bd9629a..f0587f4 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -38,6 +38,7 @@
namespace gl
{
struct Box;
+class DrawCallParams;
struct Extents;
struct RasterizerState;
struct Rectangle;
@@ -641,27 +642,32 @@
DeviceMemory *deviceMemoryOut,
size_t *requiredSizeOut);
-// This class responsibility is to bind an indexed buffer needed to support line loops in Vulkan.
-// In the setup phase of drawing, the bindLineLoopIndexBuffer method should be called with the
-// first/last vertex and the current commandBuffer. If the user wants to draw a loop between [v1,
-// v2, v3], we will create an indexed buffer with these indexes: [0, 1, 2, 3, 0] to emulate the
-// loop.
+// This class' responsibility is to create index buffers needed to support line loops in Vulkan.
+// In the setup phase of drawing, the createIndexBuffer method should be called with the
+// current draw call parameters. If an element array buffer is bound for an indexed draw, use
+// createIndexBufferFromElementArrayBuffer.
+//
+// If the user wants to draw a loop between [v1, v2, v3], we will create an indexed buffer with
+// these indexes: [0, 1, 2, 3, 0] to emulate the loop.
class LineLoopHandler final : angle::NonCopyable, angle::ObserverInterface
{
public:
LineLoopHandler();
~LineLoopHandler();
- void bindIndexBuffer(VkIndexType indexType, CommandBuffer **commandBuffer);
-
- gl::Error createIndexBuffer(ContextVk *contextVk, int firstVertex, int count);
- gl::Error createIndexBufferFromElementArrayBuffer(ContextVk *contextVk,
- BufferVk *bufferVk,
+ gl::Error createIndexBuffer(RendererVk *renderer,
+ const gl::DrawCallParams &drawCallParams,
+ VkBuffer *bufferHandleOut,
+ VkDeviceSize *offsetOut);
+ gl::Error createIndexBufferFromElementArrayBuffer(RendererVk *renderer,
+ BufferVk *elementArrayBufferVk,
VkIndexType indexType,
- int count);
+ int indexCount,
+ VkBuffer *bufferHandleOut,
+ VkDeviceSize *bufferOffsetOut);
void destroy(VkDevice device);
- gl::Error draw(int count, CommandBuffer *commandBuffer);
+ static void Draw(int count, CommandBuffer *commandBuffer);
ResourceVk *getLineLoopBufferResource();
@@ -673,10 +679,6 @@
private:
angle::ObserverBinding mObserverBinding;
std::unique_ptr<DynamicBuffer> mDynamicLineLoopIndicesData;
- VkBuffer mLineLoopIndexBuffer;
- uint32_t mLineLoopIndexBufferOffset;
- Optional<int> mLineLoopBufferFirstIndex;
- Optional<int> mLineLoopBufferLastIndex;
};
class ImageHelper final : angle::NonCopyable
@@ -771,6 +773,7 @@
VkFrontFace GetFrontFace(GLenum frontFace);
VkSampleCountFlagBits GetSamples(GLint sampleCount);
VkComponentSwizzle GetSwizzle(const GLenum swizzle);
+VkIndexType GetIndexType(GLenum elementType);
} // namespace gl_vk
// This is a helper class for back-end objects used in Vk command buffers. It records a serial