Commit 879f90d2 by Luc Ferron Committed by Commit Bot

Vulkan: Avoid recopying the data every time we draw line loops

Use the Observer pattern to get notified when the BufferVk we've copied our data from is changing. We will only recopy the data if anything has changed, but otherwise we'll keep drawing with the same index buffer we've created previously. Bug: angleproject:2335 Change-Id: Ib65677b4d5ec90c46a5e3b975fffd1fddeed59e7 Reviewed-on: https://chromium-review.googlesource.com/948622 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 7b21381e
......@@ -115,4 +115,9 @@ void ObserverBinding::onSubjectReset()
{
mSubject = nullptr;
}
const Subject *ObserverBinding::getSubject() const
{
return mSubject;
}
} // namespace angle
......@@ -77,6 +77,8 @@ class ObserverBinding final
void onStateChange(const gl::Context *context, SubjectMessage message) const;
void onSubjectReset();
const Subject *getSubject() const;
private:
Subject *mSubject;
ObserverInterface *mObserver;
......
......@@ -84,6 +84,7 @@ gl::Error BufferVk::setData(const gl::Context *context,
ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, 0));
}
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError();
}
......@@ -99,6 +100,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context);
ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, offset));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError();
}
......@@ -122,6 +124,7 @@ gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr
ANGLE_TRY(
mBufferMemory.map(device, 0, mState.getSize(), 0, reinterpret_cast<uint8_t **>(mapPtr)));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError();
}
......@@ -138,6 +141,7 @@ gl::Error BufferVk::mapRange(const gl::Context *context,
ANGLE_TRY(mBufferMemory.map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError();
}
......@@ -150,6 +154,7 @@ gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result)
mBufferMemory.unmap(device);
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError();
}
......
......@@ -10,6 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
#define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
#include "libANGLE/Observer.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
......@@ -17,7 +18,7 @@ namespace rx
{
class RendererVk;
class BufferVk : public BufferImpl, public ResourceVk
class BufferVk : public BufferImpl, public ResourceVk, public angle::Subject
{
public:
BufferVk(const gl::BufferState &state);
......
......@@ -1330,7 +1330,8 @@ void GarbageObject::destroy(VkDevice device)
}
LineLoopHandler::LineLoopHandler()
: mStreamingLineLoopIndicesData(
: mObserverBinding(this, 0u),
mStreamingLineLoopIndicesData(
new StreamingBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
kLineLoopStreamingBufferMinSize)),
mLineLoopIndexBuffer(VK_NULL_HANDLE),
......@@ -1385,16 +1386,17 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co
{
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32);
if (mLineLoopIndexBuffer != VK_NULL_HANDLE)
if (bufferVk == mObserverBinding.getSubject() && mLineLoopIndexBuffer != VK_NULL_HANDLE)
{
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);
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),
......@@ -1416,12 +1418,12 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co
copies.data());
ANGLE_TRY(mStreamingLineLoopIndicesData->flush(contextVk));
return gl::NoError();
}
void LineLoopHandler::destroy(VkDevice device)
{
mObserverBinding.reset();
mStreamingLineLoopIndicesData->destroy(device);
}
......@@ -1438,6 +1440,17 @@ ResourceVk *LineLoopHandler::getLineLoopBufferResource()
{
return mStreamingLineLoopIndicesData.get();
}
void LineLoopHandler::onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message)
{
// Indicate we want to recopy on next draw since something changed in the buffer.
if (message == angle::SubjectMessage::STATE_CHANGE)
{
mLineLoopIndexBuffer = VK_NULL_HANDLE;
}
}
} // namespace vk
namespace gl_vk
......
......@@ -17,6 +17,7 @@
#include "common/Optional.h"
#include "common/debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/Observer.h"
#include "libANGLE/renderer/renderer_utils.h"
#define ANGLE_GL_OBJECTS_X(PROC) \
......@@ -680,7 +681,7 @@ Error AllocateImageMemory(RendererVk *renderer,
// 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.
class LineLoopHandler final : angle::NonCopyable
class LineLoopHandler final : angle::NonCopyable, angle::ObserverInterface
{
public:
LineLoopHandler();
......@@ -699,7 +700,13 @@ class LineLoopHandler final : angle::NonCopyable
ResourceVk *getLineLoopBufferResource();
// Observer interface implementation.
void onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
private:
angle::ObserverBinding mObserverBinding;
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