Commit bd159f06 by Jamie Madill Committed by Commit Bot

Vulkan: Use minimal dirty bits in VertexArrayVk.

This should slightly reduce draw call overhead. BUG=angleproject:1898 Change-Id: I0e515bf2868f237f1d6948c12942f8cb6637c0c0 Reviewed-on: https://chromium-review.googlesource.com/707690Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 492f58ec
...@@ -341,6 +341,7 @@ ProgramState::ProgramState() ...@@ -341,6 +341,7 @@ ProgramState::ProgramState()
mAttachedVertexShader(nullptr), mAttachedVertexShader(nullptr),
mAttachedComputeShader(nullptr), mAttachedComputeShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS), mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mMaxActiveAttribLocation(0),
mSamplerUniformRange(0, 0), mSamplerUniformRange(0, 0),
mImageUniformRange(0, 0), mImageUniformRange(0, 0),
mAtomicCounterUniformRange(0, 0), mAtomicCounterUniformRange(0, 0),
...@@ -847,6 +848,7 @@ void Program::unlink() ...@@ -847,6 +848,7 @@ void Program::unlink()
{ {
mState.mAttributes.clear(); mState.mAttributes.clear();
mState.mActiveAttribLocationsMask.reset(); mState.mActiveAttribLocationsMask.reset();
mState.mMaxActiveAttribLocation = 0;
mState.mLinkedTransformFeedbackVaryings.clear(); mState.mLinkedTransformFeedbackVaryings.clear();
mState.mUniforms.clear(); mState.mUniforms.clear();
mState.mUniformLocations.clear(); mState.mUniformLocations.clear();
...@@ -2134,11 +2136,14 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog) ...@@ -2134,11 +2136,14 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
for (const sh::Attribute &attribute : mState.mAttributes) for (const sh::Attribute &attribute : mState.mAttributes)
{ {
ASSERT(attribute.location != -1); ASSERT(attribute.location != -1);
int regs = VariableRegisterCount(attribute.type); unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
for (int r = 0; r < regs; r++) for (unsigned int r = 0; r < regs; r++)
{ {
mState.mActiveAttribLocationsMask.set(attribute.location + r); unsigned int location = static_cast<unsigned int>(attribute.location) + r;
mState.mActiveAttribLocationsMask.set(location);
mState.mMaxActiveAttribLocation =
std::max(mState.mMaxActiveAttribLocation, location + 1);
} }
} }
......
...@@ -272,6 +272,7 @@ class ProgramState final : angle::NonCopyable ...@@ -272,6 +272,7 @@ class ProgramState final : angle::NonCopyable
{ {
return mActiveAttribLocationsMask; return mActiveAttribLocationsMask;
} }
unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; } DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; } const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
const std::map<int, VariableLocation> &getOutputLocations() const { return mOutputLocations; } const std::map<int, VariableLocation> &getOutputLocations() const { return mOutputLocations; }
...@@ -330,6 +331,7 @@ class ProgramState final : angle::NonCopyable ...@@ -330,6 +331,7 @@ class ProgramState final : angle::NonCopyable
std::vector<sh::Attribute> mAttributes; std::vector<sh::Attribute> mAttributes;
angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
unsigned int mMaxActiveAttribLocation;
// Uniforms are sorted in order: // Uniforms are sorted in order:
// 1. Non-opaque uniforms // 1. Non-opaque uniforms
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "common/bitset_utils.h" #include "common/bitset_utils.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/Program.h" #include "libANGLE/Program.h"
#include "libANGLE/renderer/vulkan/BufferVk.h" #include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/CompilerVk.h" #include "libANGLE/renderer/vulkan/CompilerVk.h"
...@@ -77,8 +78,9 @@ gl::Error ContextVk::flush() ...@@ -77,8 +78,9 @@ gl::Error ContextVk::flush()
gl::Error ContextVk::finish() gl::Error ContextVk::finish()
{ {
UNIMPLEMENTED(); // TODO(jmadill): Implement finish.
return gl::InternalError(); // UNIMPLEMENTED();
return gl::NoError();
} }
gl::Error ContextVk::initPipeline(const gl::Context *context) gl::Error ContextVk::initPipeline(const gl::Context *context)
...@@ -302,46 +304,29 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, GLenum mode) ...@@ -302,46 +304,29 @@ gl::Error ContextVk::setupDraw(const gl::Context *context, GLenum mode)
const auto &state = mState.getState(); const auto &state = mState.getState();
const auto &programGL = state.getProgram(); const auto &programGL = state.getProgram();
const auto &vao = state.getVertexArray(); const auto &vao = state.getVertexArray();
const auto &attribs = vao->getVertexAttributes(); VertexArrayVk *vkVAO = GetImplAs<VertexArrayVk>(vao);
const auto &bindings = vao->getVertexBindings();
const auto *drawFBO = state.getDrawFramebuffer(); const auto *drawFBO = state.getDrawFramebuffer();
FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO); FramebufferVk *vkFBO = GetImplAs<FramebufferVk>(drawFBO);
Serial queueSerial = mRenderer->getCurrentQueueSerial(); Serial queueSerial = mRenderer->getCurrentQueueSerial();
uint32_t maxAttrib = programGL->getState().getMaxActiveAttribLocation();
// Process vertex attributes // Process vertex attributes. Assume zero offsets for now.
// TODO(jmadill): Caching with dirty bits. // TODO(jmadill): Offset handling.
std::vector<VkBuffer> vertexHandles; const std::vector<VkBuffer> &vertexHandles = vkVAO->getCurrentVertexBufferHandlesCache();
std::vector<VkDeviceSize> vertexOffsets; angle::MemoryBuffer *zeroBuf = nullptr;
ANGLE_TRY(context->getZeroFilledBuffer(maxAttrib * sizeof(VkDeviceSize), &zeroBuf));
for (auto attribIndex : programGL->getActiveAttribLocationsMask())
{
const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled)
{
// TODO(jmadill): Offset handling.
gl::Buffer *bufferGL = binding.getBuffer().get();
ASSERT(bufferGL);
BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
vertexHandles.push_back(bufferVk->getVkBuffer().getHandle());
vertexOffsets.push_back(0);
bufferVk->setQueueSerial(queueSerial);
}
else
{
UNIMPLEMENTED();
}
}
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer)); ANGLE_TRY(mRenderer->getStartedCommandBuffer(&commandBuffer));
ANGLE_TRY(vkFBO->ensureInRenderPass(context, device, commandBuffer, queueSerial, state)); ANGLE_TRY(vkFBO->ensureInRenderPass(context, device, commandBuffer, queueSerial, state));
commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline); commandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, mCurrentPipeline);
commandBuffer->bindVertexBuffers(0, maxAttrib, vertexHandles.data(),
reinterpret_cast<const VkDeviceSize *>(zeroBuf->data()));
// TODO(jmadill): the queue serial should be bound to the pipeline. // TODO(jmadill): the queue serial should be bound to the pipeline.
setQueueSerial(queueSerial); setQueueSerial(queueSerial);
commandBuffer->bindVertexBuffers(0, vertexHandles, vertexOffsets); vkVAO->updateCurrentBufferSerials(programGL->getActiveAttribLocationsMask(), queueSerial);
return gl::NoError(); return gl::NoError();
} }
......
...@@ -12,12 +12,16 @@ ...@@ -12,12 +12,16 @@
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
namespace rx namespace rx
{ {
VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state) : VertexArrayImpl(state) VertexArrayVk::VertexArrayVk(const gl::VertexArrayState &state)
: VertexArrayImpl(state),
mCurrentVertexBufferHandlesCache(state.getMaxAttribs(), VK_NULL_HANDLE),
mCurrentVkBuffersCache(state.getMaxAttribs(), nullptr)
{ {
} }
...@@ -30,9 +34,60 @@ void VertexArrayVk::syncState(const gl::Context *context, ...@@ -30,9 +34,60 @@ void VertexArrayVk::syncState(const gl::Context *context,
{ {
ASSERT(dirtyBits.any()); ASSERT(dirtyBits.any());
// Invalidate current pipeline.
// TODO(jmadill): Use pipeline cache. // TODO(jmadill): Use pipeline cache.
auto contextVk = GetImplAs<ContextVk>(context); auto contextVk = GetImplAs<ContextVk>(context);
contextVk->invalidateCurrentPipeline(); contextVk->invalidateCurrentPipeline();
// Rebuild current attribute buffers cache. This will fail horribly if the buffer changes.
// TODO(jmadill): Handle buffer storage changes.
const auto &attribs = mState.getVertexAttributes();
const auto &bindings = mState.getVertexBindings();
for (auto dirtyBit : dirtyBits)
{
if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
continue;
size_t attribIndex = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
const auto &attrib = attribs[attribIndex];
const auto &binding = bindings[attrib.bindingIndex];
if (attrib.enabled)
{
gl::Buffer *bufferGL = binding.getBuffer().get();
if (bufferGL)
{
BufferVk *bufferVk = GetImplAs<BufferVk>(bufferGL);
mCurrentVkBuffersCache[attribIndex] = bufferVk;
mCurrentVertexBufferHandlesCache[attribIndex] = bufferVk->getVkBuffer().getHandle();
}
else
{
mCurrentVkBuffersCache[attribIndex] = nullptr;
mCurrentVertexBufferHandlesCache[attribIndex] = VK_NULL_HANDLE;
}
}
else
{
UNIMPLEMENTED();
}
}
}
const std::vector<VkBuffer> &VertexArrayVk::getCurrentVertexBufferHandlesCache() const
{
return mCurrentVertexBufferHandlesCache;
}
void VertexArrayVk::updateCurrentBufferSerials(const gl::AttributesMask &activeAttribsMask,
Serial serial)
{
for (auto attribIndex : activeAttribsMask)
{
mCurrentVkBuffersCache[attribIndex]->setQueueSerial(serial);
}
} }
} // namespace rx } // namespace rx
...@@ -11,9 +11,11 @@ ...@@ -11,9 +11,11 @@
#define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_ #define LIBANGLE_RENDERER_VULKAN_VERTEXARRAYVK_H_
#include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/vulkan/renderervk_utils.h"
namespace rx namespace rx
{ {
class BufferVk;
class VertexArrayVk : public VertexArrayImpl class VertexArrayVk : public VertexArrayImpl
{ {
...@@ -23,6 +25,14 @@ class VertexArrayVk : public VertexArrayImpl ...@@ -23,6 +25,14 @@ class VertexArrayVk : public VertexArrayImpl
void syncState(const gl::Context *context, void syncState(const gl::Context *context,
const gl::VertexArray::DirtyBits &dirtyBits) override; const gl::VertexArray::DirtyBits &dirtyBits) override;
const std::vector<VkBuffer> &getCurrentVertexBufferHandlesCache() const;
void updateCurrentBufferSerials(const gl::AttributesMask &activeAttribsMask, Serial serial);
private:
std::vector<VkBuffer> mCurrentVertexBufferHandlesCache;
std::vector<BufferVk *> mCurrentVkBuffersCache;
}; };
} // namespace rx } // namespace rx
......
...@@ -446,12 +446,12 @@ void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint, ...@@ -446,12 +446,12 @@ void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
} }
void CommandBuffer::bindVertexBuffers(uint32_t firstBinding, void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
const std::vector<VkBuffer> &buffers, uint32_t bindingCount,
const std::vector<VkDeviceSize> &offsets) const VkBuffer *buffers,
const VkDeviceSize *offsets)
{ {
ASSERT(valid() && buffers.size() == offsets.size()); ASSERT(valid());
vkCmdBindVertexBuffers(mHandle, firstBinding, static_cast<uint32_t>(buffers.size()), vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
buffers.data(), offsets.data());
} }
void CommandBuffer::bindIndexBuffer(const vk::Buffer &buffer, void CommandBuffer::bindIndexBuffer(const vk::Buffer &buffer,
......
...@@ -239,8 +239,9 @@ class CommandBuffer final : public WrappedObject<CommandBuffer, VkCommandBuffer> ...@@ -239,8 +239,9 @@ class CommandBuffer final : public WrappedObject<CommandBuffer, VkCommandBuffer>
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const vk::Pipeline &pipeline); void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const vk::Pipeline &pipeline);
void bindVertexBuffers(uint32_t firstBinding, void bindVertexBuffers(uint32_t firstBinding,
const std::vector<VkBuffer> &buffers, uint32_t bindingCount,
const std::vector<VkDeviceSize> &offsets); const VkBuffer *buffers,
const VkDeviceSize *offsets);
void bindIndexBuffer(const vk::Buffer &buffer, VkDeviceSize offset, VkIndexType indexType); void bindIndexBuffer(const vk::Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
private: private:
......
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