Commit a064c27c by Jamie Madill Committed by Commit Bot

Vulkan: Refactor VertexArrayVk::streamVertexData.

Merges duplicated code in convertVertexBuffer with streamVertexData. Refactoring change only. Bug: angleproject:2786 Change-Id: I32baaad42d74918cfb17f04970d3c7e9b88362e7 Reviewed-on: https://chromium-review.googlesource.com/1188950Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 70a4ef10
...@@ -30,6 +30,27 @@ bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize) ...@@ -30,6 +30,27 @@ bool BindingIsAligned(const gl::VertexBinding &binding, unsigned componentSize)
{ {
return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0); return (binding.getOffset() % componentSize == 0) && (binding.getStride() % componentSize == 0);
} }
angle::Result StreamVertexData(ContextVk *contextVk,
vk::DynamicBuffer *dynamicBuffer,
const uint8_t *sourceData,
size_t bytesToAllocate,
size_t destOffset,
size_t vertexCount,
size_t stride,
VertexCopyFunction vertexLoadFunction,
VkBuffer *bufferHandleOut,
VkDeviceSize *bufferOffsetOut)
{
uint8_t *dst = nullptr;
ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, bufferHandleOut,
bufferOffsetOut, nullptr));
dst += destOffset;
vertexLoadFunction(sourceData, stride, vertexCount, dst);
ANGLE_TRY(dynamicBuffer->flush(contextVk));
return angle::Result::Continue();
}
} // anonymous namespace } // anonymous namespace
#define INIT \ #define INIT \
...@@ -94,52 +115,13 @@ void VertexArrayVk::destroy(const gl::Context *context) ...@@ -94,52 +115,13 @@ void VertexArrayVk::destroy(const gl::Context *context)
mLineLoopHelper.destroy(device); mLineLoopHelper.destroy(device);
} }
angle::Result VertexArrayVk::streamVertexData(ContextVk *contextVk,
const gl::AttributesMask &attribsToStream,
const gl::DrawCallParams &drawCallParams)
{
ASSERT(!attribsToStream.none());
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
// 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 (size_t attribIndex : attribsToStream)
{
const gl::VertexAttribute &attrib = attribs[attribIndex];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
// Only vertexCount() vertices will be used by the upcoming draw so that is
// all we copy, but we allocate space firstVertex() + vertexCount() so indexing
// will work. If we don't start at zero all the indices will be off.
// TODO(fjhenigman): See if we can account for indices being off by adjusting
// the offset, thus avoiding wasted memory.
const size_t bytesAllocated =
(drawCallParams.firstVertex() + drawCallParams.vertexCount()) *
mCurrentArrayBufferStrides[attribIndex];
const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer) +
drawCallParams.firstVertex() * binding.getStride();
uint8_t *dst = nullptr;
ANGLE_TRY(mDynamicVertexData.allocate(contextVk, bytesAllocated, &dst,
&mCurrentArrayBufferHandles[attribIndex],
&mCurrentArrayBufferOffsets[attribIndex], nullptr));
dst += drawCallParams.firstVertex() * mCurrentArrayBufferStrides[attribIndex];
mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction(
src, binding.getStride(), drawCallParams.vertexCount(), dst);
}
ANGLE_TRY(mDynamicVertexData.flush(contextVk));
mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
return angle::Result::Continue();
}
angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk, angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
const gl::DrawCallParams &drawCallParams) const gl::DrawCallParams &drawCallParams)
{ {
ASSERT(!mState.getElementArrayBuffer().get()); ASSERT(!mState.getElementArrayBuffer().get());
mDynamicIndexData.releaseRetainedBuffers(contextVk->getRenderer());
const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount(); const GLsizei amount = sizeof(GLushort) * drawCallParams.indexCount();
GLubyte *dst = nullptr; GLubyte *dst = nullptr;
...@@ -161,7 +143,6 @@ angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk, ...@@ -161,7 +143,6 @@ angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
memcpy(dst, drawCallParams.indices(), amount); memcpy(dst, drawCallParams.indices(), amount);
} }
ANGLE_TRY(mDynamicIndexData.flush(contextVk)); ANGLE_TRY(mDynamicIndexData.flush(contextVk));
mDynamicIndexData.releaseRetainedBuffers(contextVk->getRenderer());
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -169,17 +150,19 @@ angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk, ...@@ -169,17 +150,19 @@ angle::Result VertexArrayVk::streamIndexData(ContextVk *contextVk,
// and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong // and/or align it as we copy it to a DynamicBuffer. The assumption could be wrong
// but the alternative of copying it piecemeal on each draw would have a lot more // but the alternative of copying it piecemeal on each draw would have a lot more
// overhead. // overhead.
angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *context, angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *contextVk,
BufferVk *srcBuffer, BufferVk *srcBuffer,
const gl::VertexBinding &binding, const gl::VertexBinding &binding,
size_t attribIndex) size_t attribIndex)
{ {
// Preparation for mapping source buffer. // Preparation for mapping source buffer.
ANGLE_TRY(context->getRenderer()->finish(context)); ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes; unsigned srcFormatSize = mCurrentArrayBufferFormats[attribIndex]->angleFormat().pixelBytes;
unsigned dstFormatSize = mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes; unsigned dstFormatSize = mCurrentArrayBufferStrides[attribIndex];
mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(contextVk->getRenderer());
// Bytes usable for vertex data. // Bytes usable for vertex data.
GLint64 bytes = srcBuffer->getSize() - binding.getOffset(); GLint64 bytes = srcBuffer->getSize() - binding.getOffset();
...@@ -195,20 +178,17 @@ angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *context, ...@@ -195,20 +178,17 @@ angle::Result VertexArrayVk::convertVertexBuffer(ContextVk *context,
numVertices += static_cast<size_t>(bytes) / binding.getStride(); numVertices += static_cast<size_t>(bytes) / binding.getStride();
void *src = nullptr; void *src = nullptr;
uint8_t *dst = nullptr; ANGLE_TRY(srcBuffer->mapImpl(contextVk, &src));
const uint8_t *srcBytes = reinterpret_cast<const uint8_t *>(src);
ANGLE_TRY(mCurrentArrayBufferConversion[attribIndex].allocate( srcBytes += binding.getOffset();
context, numVertices * dstFormatSize, &dst, &mCurrentArrayBufferHandles[attribIndex], ANGLE_TRY(StreamVertexData(contextVk, &mCurrentArrayBufferConversion[attribIndex], srcBytes,
&mCurrentArrayBufferOffsets[attribIndex], nullptr)); numVertices * dstFormatSize, 0, numVertices, binding.getStride(),
ANGLE_TRY(srcBuffer->mapImpl(context, &src)); mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction( &mCurrentArrayBufferHandles[attribIndex],
static_cast<const uint8_t *>(src) + binding.getOffset(), binding.getStride(), numVertices, &mCurrentArrayBufferOffsets[attribIndex]));
dst); ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
ANGLE_TRY(srcBuffer->unmapImpl(context));
ANGLE_TRY(mCurrentArrayBufferConversion[attribIndex].flush(context));
mCurrentArrayBufferConversionCanRelease[attribIndex] = true; mCurrentArrayBufferConversionCanRelease[attribIndex] = true;
mCurrentArrayBufferStrides[attribIndex] = dstFormatSize;
return angle::Result::Continue(); return angle::Result::Continue();
} }
...@@ -335,9 +315,11 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk, ...@@ -335,9 +315,11 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion || if (mCurrentArrayBufferFormats[attribIndex]->vertexLoadRequiresConversion ||
!BindingIsAligned(binding, componentSize)) !BindingIsAligned(binding, componentSize))
{ {
mCurrentArrayBufferStrides[attribIndex] =
mCurrentArrayBufferFormats[attribIndex]->bufferFormat().pixelBytes;
ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex)); ANGLE_TRY(convertVertexBuffer(contextVk, bufferVk, binding, attribIndex));
mCurrentArrayBufferConversion[attribIndex].releaseRetainedBuffers(renderer);
mCurrentArrayBufferResources[attribIndex] = nullptr; mCurrentArrayBufferResources[attribIndex] = nullptr;
releaseConversion = false; releaseConversion = false;
} }
...@@ -565,7 +547,42 @@ gl::Error VertexArrayVk::onDraw(const gl::Context *context, ...@@ -565,7 +547,42 @@ gl::Error VertexArrayVk::onDraw(const gl::Context *context,
if (clientAttribs.any()) if (clientAttribs.any())
{ {
ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context)); ANGLE_TRY(drawCallParams.ensureIndexRangeResolved(context));
ANGLE_TRY(streamVertexData(contextVk, clientAttribs, drawCallParams));
mDynamicVertexData.releaseRetainedBuffers(contextVk->getRenderer());
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
// 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 (size_t attribIndex : clientAttribs)
{
const gl::VertexAttribute &attrib = attribs[attribIndex];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
ASSERT(attrib.enabled && binding.getBuffer().get() == nullptr);
const size_t bytesToAllocate =
(drawCallParams.firstVertex() + drawCallParams.vertexCount()) *
mCurrentArrayBufferStrides[attribIndex];
const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer) +
drawCallParams.firstVertex() * binding.getStride();
size_t destOffset =
drawCallParams.firstVertex() * mCurrentArrayBufferStrides[attribIndex];
// Only vertexCount() vertices will be used by the upcoming draw so that is all we copy,
// but we allocate space firstVertex() + vertexCount() so indexing will work. If we
// don't start at zero all the indices will be off.
// TODO(fjhenigman): See if we can account for indices being off by adjusting the
// offset, thus avoiding wasted memory.
ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate,
destOffset, drawCallParams.vertexCount(),
binding.getStride(),
mCurrentArrayBufferFormats[attribIndex]->vertexLoadFunction,
&mCurrentArrayBufferHandles[attribIndex],
&mCurrentArrayBufferOffsets[attribIndex]));
}
commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(), commandBuffer->bindVertexBuffers(0, maxAttrib, mCurrentArrayBufferHandles.data(),
mCurrentArrayBufferOffsets.data()); mCurrentArrayBufferOffsets.data());
} }
......
...@@ -82,10 +82,6 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -82,10 +82,6 @@ class VertexArrayVk : public VertexArrayImpl
void updateElementArrayBufferReadDependency(vk::CommandGraphResource *drawFramebuffer, void updateElementArrayBufferReadDependency(vk::CommandGraphResource *drawFramebuffer,
Serial serial); Serial serial);
angle::Result streamVertexData(ContextVk *contextVk,
const gl::AttributesMask &attribsToStream,
const gl::DrawCallParams &drawCallParams);
angle::Result streamIndexData(ContextVk *contextVk, const gl::DrawCallParams &drawCallParams); angle::Result streamIndexData(ContextVk *contextVk, const gl::DrawCallParams &drawCallParams);
angle::Result convertVertexBuffer(ContextVk *contextVk, angle::Result convertVertexBuffer(ContextVk *contextVk,
BufferVk *srcBuffer, BufferVk *srcBuffer,
......
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