Commit a53d0e18 by Frank Henigman Committed by Commit Bot

Vulkan: support indices in client memory.

glDrawElements will now work with indices and/or vertex data in client memory, as well as in a buffer object. Enable corresponding tests. BUG=angleproject:1683 Change-Id: Iefb9796a48b21ed6f9a837b08b0ad3218ff6dd6b Reviewed-on: https://chromium-review.googlesource.com/915721 Commit-Queue: Frank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 6dd4a92a
......@@ -11,6 +11,7 @@
#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
......@@ -60,6 +61,9 @@ enum DescriptorPoolIndex : uint8_t
TexturePool = 1,
};
constexpr size_t kStreamingVertexDataSize = 1024 * 1024;
constexpr size_t kStreamingIndexDataSize = 1024 * 8;
} // anonymous namespace
ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
......@@ -68,7 +72,8 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
mCurrentDrawMode(GL_NONE),
mVertexArrayDirty(false),
mTexturesDirty(false),
mStreamingVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1024 * 1024)
mStreamingVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kStreamingVertexDataSize),
mStreamingIndexData(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, kStreamingIndexDataSize)
{
memset(&mClearColorValue, 0, sizeof(mClearColorValue));
memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
......@@ -84,6 +89,7 @@ void ContextVk::onDestroy(const gl::Context *context)
mDescriptorPool.destroy(device);
mStreamingVertexData.destroy(device);
mStreamingIndexData.destroy(device);
mLineLoopHandler.destroy(device);
}
......@@ -159,8 +165,8 @@ gl::Error ContextVk::initPipeline(const gl::Context *context)
gl::Error ContextVk::setupDraw(const gl::Context *context,
GLenum mode,
DrawType drawType,
int firstVertex,
int lastVertex,
size_t firstVertex,
size_t lastVertex,
ResourceVk *elementArrayBufferOverride,
vk::CommandBuffer **commandBuffer)
{
......@@ -299,15 +305,20 @@ gl::Error ContextVk::drawElements(const gl::Context *context,
GLenum type,
const void *indices)
{
const gl::Buffer *elementArrayBuffer =
mState.getState().getVertexArray()->getElementArrayBuffer().get();
ASSERT(elementArrayBuffer);
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
gl::VertexArray *vao = mState.getState().getVertexArray();
const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
vk::CommandBuffer *commandBuffer = nullptr;
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));
......@@ -320,26 +331,50 @@ gl::Error ContextVk::drawElements(const gl::Context *context,
}
else
{
// TODO(fjhenigman): calculate the index range and pass to setupDraw()
ANGLE_TRY(setupDraw(context, mode, DrawType::Elements, 0, 0, nullptr, &commandBuffer));
if (indices)
if (type == GL_UNSIGNED_BYTE)
{
// TODO(jmadill): Buffer offsets and immediate data.
// TODO(fjhenigman): Index format translation.
UNIMPLEMENTED();
return gl::InternalError()
<< "Only zero-offset index buffers are currently implemented.";
return gl::InternalError() << "Unsigned byte translation is not yet implemented.";
}
if (type == GL_UNSIGNED_BYTE)
ContextVk *contextVk = vk::GetImpl(context);
const bool computeIndexRange = vk::GetImpl(vao)->attribsToStream(contextVk).any();
gl::IndexRange range;
VkBuffer buffer = VK_NULL_HANDLE;
VkDeviceSize offset = 0;
if (elementArrayBuffer)
{
// TODO(jmadill): Index translation.
UNIMPLEMENTED();
return gl::InternalError() << "Unsigned byte translation is not yet implemented.";
BufferVk *elementArrayBufferVk = vk::GetImpl(elementArrayBuffer);
buffer = elementArrayBufferVk->getVkBuffer().getHandle();
offset = 0;
if (computeIndexRange)
{
ANGLE_TRY(elementArrayBufferVk->getIndexRange(
context, type, 0, count, false /*primitiveRestartEnabled*/, &range));
}
}
else
{
const GLsizei amount = sizeof(GLushort) * count;
uint8_t *dst = nullptr;
ANGLE_TRY(mStreamingIndexData.allocate(contextVk, amount, &dst, &buffer, &offset));
memcpy(dst, indices, amount);
ANGLE_TRY(mStreamingIndexData.flush(contextVk));
if (computeIndexRange)
{
range =
gl::ComputeIndexRange(type, indices, count, false /*primitiveRestartEnabled*/);
}
}
commandBuffer->bindIndexBuffer(elementArrayBufferVk->getVkBuffer(), 0,
GetVkIndexType(type));
ANGLE_TRY(setupDraw(context, mode, DrawType::Elements, range.start, range.end, nullptr,
&commandBuffer));
commandBuffer->bindIndexBuffer(buffer, offset, GetVkIndexType(type));
commandBuffer->drawIndexed(count, 1, 0, 0, 0);
}
......
......@@ -166,8 +166,8 @@ class ContextVk : public ContextImpl
gl::Error setupDraw(const gl::Context *context,
GLenum mode,
DrawType drawType,
int firstVertex,
int lastVertex,
size_t firstVertex,
size_t lastVertex,
ResourceVk *elementArrayBufferOverride,
vk::CommandBuffer **commandBuffer);
......@@ -192,6 +192,7 @@ class ContextVk : public ContextImpl
VkClearValue mClearDepthStencilValue;
StreamingBuffer mStreamingVertexData;
StreamingBuffer mStreamingIndexData;
vk::LineLoopHandler mLineLoopHandler;
};
......
......@@ -43,6 +43,12 @@ void VertexArrayVk::destroy(const gl::Context *context)
{
}
gl::AttributesMask VertexArrayVk::attribsToStream(ContextVk *context) const
{
const gl::Program *programGL = context->getGLState().getProgram();
return mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
}
gl::Error VertexArrayVk::streamVertexData(ContextVk *context,
StreamingBuffer *stream,
size_t firstVertex,
......@@ -50,13 +56,10 @@ gl::Error VertexArrayVk::streamVertexData(ContextVk *context,
{
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
const gl::Program *programGL = context->getGLState().getProgram();
const gl::AttributesMask attribsToStream =
mClientMemoryAttribs & programGL->getActiveAttribLocationsMask();
// 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 : attribsToStream)
for (auto attribIndex : attribsToStream(context))
{
const gl::VertexAttribute &attrib = attribs[attribIndex];
const gl::VertexBinding &binding = bindings[attrib.bindingIndex];
......@@ -179,7 +182,7 @@ void VertexArrayVk::updateDrawDependencies(vk::CommandGraphNode *readNode,
}
// Handle the bound element array buffer.
if (drawType == DrawType::Elements)
if (drawType == DrawType::Elements && mCurrentElementArrayBufferResource)
{
if (elementArrayBufferOverride != nullptr)
{
......
......@@ -26,6 +26,7 @@ class VertexArrayVk : public VertexArrayImpl
void destroy(const gl::Context *context) override;
gl::AttributesMask attribsToStream(ContextVk *context) const;
gl::Error streamVertexData(ContextVk *context,
StreamingBuffer *stream,
size_t firstVertex,
......
......@@ -601,14 +601,6 @@ void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
}
void CommandBuffer::bindIndexBuffer(const vk::Buffer &buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ASSERT(valid());
vkCmdBindIndexBuffer(mHandle, buffer.getHandle(), offset, indexType);
}
void CommandBuffer::bindIndexBuffer(const VkBuffer &buffer,
VkDeviceSize offset,
VkIndexType indexType)
......
......@@ -381,7 +381,6 @@ class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
uint32_t bindingCount,
const VkBuffer *buffers,
const VkDeviceSize *offsets);
void bindIndexBuffer(const vk::Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
void bindIndexBuffer(const VkBuffer &buffer, VkDeviceSize offset, VkIndexType indexType);
void bindDescriptorSets(VkPipelineBindPoint bindPoint,
const vk::PipelineLayout &layout,
......
......@@ -157,16 +157,6 @@ class Attrib
typedef std::vector<Attrib> TestCase;
bool UsesClientMemory(const TestCase &tc)
{
for (const Attrib &a : tc)
{
if (a.inClientMemory())
return true;
}
return false;
}
void PrepareTestCase(const TestCase &tc)
{
for (const Attrib &a : tc)
......@@ -400,18 +390,6 @@ class AttributeLayoutMemoryIndexed : public AttributeLayoutTest
class AttributeLayoutBufferIndexed : public AttributeLayoutTest
{
bool Skip(const TestCase &tc) override
{
if (IsVulkan() && UsesClientMemory(tc))
{
std::cout
<< "test case skipped on Vulkan: indexed draw with vertex data in client memory"
<< std::endl;
return true;
}
return false;
}
void Draw(int firstVertex, unsigned vertexCount, const GLushort *indices) override
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
......@@ -437,12 +415,6 @@ TEST_P(AttributeLayoutNonIndexed, Test)
TEST_P(AttributeLayoutMemoryIndexed, Test)
{
if (IsVulkan())
{
std::cout << "test skipped on Vulkan: indices in memory not supported" << std::endl;
return;
}
Run(true);
if (IsWindows() && IsAMD() && (IsOpenGL() || GetParam() == ES2_D3D11_FL9_3()))
......@@ -457,7 +429,6 @@ TEST_P(AttributeLayoutMemoryIndexed, Test)
TEST_P(AttributeLayoutBufferIndexed, Test)
{
Run(true);
if (IsWindows() && IsAMD() && (IsOpenGL() || GetParam() == ES2_D3D11_FL9_3()))
......
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