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() ...@@ -115,4 +115,9 @@ void ObserverBinding::onSubjectReset()
{ {
mSubject = nullptr; mSubject = nullptr;
} }
const Subject *ObserverBinding::getSubject() const
{
return mSubject;
}
} // namespace angle } // namespace angle
...@@ -77,6 +77,8 @@ class ObserverBinding final ...@@ -77,6 +77,8 @@ class ObserverBinding final
void onStateChange(const gl::Context *context, SubjectMessage message) const; void onStateChange(const gl::Context *context, SubjectMessage message) const;
void onSubjectReset(); void onSubjectReset();
const Subject *getSubject() const;
private: private:
Subject *mSubject; Subject *mSubject;
ObserverInterface *mObserver; ObserverInterface *mObserver;
......
...@@ -84,6 +84,7 @@ gl::Error BufferVk::setData(const gl::Context *context, ...@@ -84,6 +84,7 @@ gl::Error BufferVk::setData(const gl::Context *context,
ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, 0)); ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, 0));
} }
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError(); return gl::NoError();
} }
...@@ -99,6 +100,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context, ...@@ -99,6 +100,7 @@ gl::Error BufferVk::setSubData(const gl::Context *context,
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, offset)); ANGLE_TRY(setDataImpl(contextVk, static_cast<const uint8_t *>(data), size, offset));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError(); return gl::NoError();
} }
...@@ -122,6 +124,7 @@ gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr ...@@ -122,6 +124,7 @@ gl::Error BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr
ANGLE_TRY( ANGLE_TRY(
mBufferMemory.map(device, 0, mState.getSize(), 0, reinterpret_cast<uint8_t **>(mapPtr))); mBufferMemory.map(device, 0, mState.getSize(), 0, reinterpret_cast<uint8_t **>(mapPtr)));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError(); return gl::NoError();
} }
...@@ -138,6 +141,7 @@ gl::Error BufferVk::mapRange(const gl::Context *context, ...@@ -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))); ANGLE_TRY(mBufferMemory.map(device, offset, length, 0, reinterpret_cast<uint8_t **>(mapPtr)));
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError(); return gl::NoError();
} }
...@@ -150,6 +154,7 @@ gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result) ...@@ -150,6 +154,7 @@ gl::Error BufferVk::unmap(const gl::Context *context, GLboolean *result)
mBufferMemory.unmap(device); mBufferMemory.unmap(device);
onStateChange(context, angle::SubjectMessage::STATE_CHANGE);
return gl::NoError(); return gl::NoError();
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_ #ifndef LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
#define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_ #define LIBANGLE_RENDERER_VULKAN_BUFFERVK_H_
#include "libANGLE/Observer.h"
#include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/vulkan/vk_utils.h" #include "libANGLE/renderer/vulkan/vk_utils.h"
...@@ -17,7 +18,7 @@ namespace rx ...@@ -17,7 +18,7 @@ namespace rx
{ {
class RendererVk; class RendererVk;
class BufferVk : public BufferImpl, public ResourceVk class BufferVk : public BufferImpl, public ResourceVk, public angle::Subject
{ {
public: public:
BufferVk(const gl::BufferState &state); BufferVk(const gl::BufferState &state);
......
...@@ -1330,7 +1330,8 @@ void GarbageObject::destroy(VkDevice device) ...@@ -1330,7 +1330,8 @@ void GarbageObject::destroy(VkDevice device)
} }
LineLoopHandler::LineLoopHandler() LineLoopHandler::LineLoopHandler()
: mStreamingLineLoopIndicesData( : mObserverBinding(this, 0u),
mStreamingLineLoopIndicesData(
new StreamingBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, new StreamingBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
kLineLoopStreamingBufferMinSize)), kLineLoopStreamingBufferMinSize)),
mLineLoopIndexBuffer(VK_NULL_HANDLE), mLineLoopIndexBuffer(VK_NULL_HANDLE),
...@@ -1385,16 +1386,17 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co ...@@ -1385,16 +1386,17 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co
{ {
ASSERT(indexType == VK_INDEX_TYPE_UINT16 || indexType == VK_INDEX_TYPE_UINT32); 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(); 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; 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)); auto unitSize = (indexType == VK_INDEX_TYPE_UINT16 ? sizeof(uint16_t) : sizeof(uint32_t));
ANGLE_TRY(mStreamingLineLoopIndicesData->allocate( ANGLE_TRY(mStreamingLineLoopIndicesData->allocate(
contextVk, unitSize * (count + 1), reinterpret_cast<uint8_t **>(&indices), contextVk, unitSize * (count + 1), reinterpret_cast<uint8_t **>(&indices),
...@@ -1416,12 +1418,12 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co ...@@ -1416,12 +1418,12 @@ gl::Error LineLoopHandler::createIndexBufferFromElementArrayBuffer(ContextVk *co
copies.data()); copies.data());
ANGLE_TRY(mStreamingLineLoopIndicesData->flush(contextVk)); ANGLE_TRY(mStreamingLineLoopIndicesData->flush(contextVk));
return gl::NoError(); return gl::NoError();
} }
void LineLoopHandler::destroy(VkDevice device) void LineLoopHandler::destroy(VkDevice device)
{ {
mObserverBinding.reset();
mStreamingLineLoopIndicesData->destroy(device); mStreamingLineLoopIndicesData->destroy(device);
} }
...@@ -1438,6 +1440,17 @@ ResourceVk *LineLoopHandler::getLineLoopBufferResource() ...@@ -1438,6 +1440,17 @@ ResourceVk *LineLoopHandler::getLineLoopBufferResource()
{ {
return mStreamingLineLoopIndicesData.get(); 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 vk
namespace gl_vk namespace gl_vk
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "common/Optional.h" #include "common/Optional.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/Observer.h"
#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/renderer_utils.h"
#define ANGLE_GL_OBJECTS_X(PROC) \ #define ANGLE_GL_OBJECTS_X(PROC) \
...@@ -680,7 +681,7 @@ Error AllocateImageMemory(RendererVk *renderer, ...@@ -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, // 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 // v2, v3], we will create an indexed buffer with these indexes: [0, 1, 2, 3, 0] to emulate the
// loop. // loop.
class LineLoopHandler final : angle::NonCopyable class LineLoopHandler final : angle::NonCopyable, angle::ObserverInterface
{ {
public: public:
LineLoopHandler(); LineLoopHandler();
...@@ -699,7 +700,13 @@ class LineLoopHandler final : angle::NonCopyable ...@@ -699,7 +700,13 @@ class LineLoopHandler final : angle::NonCopyable
ResourceVk *getLineLoopBufferResource(); ResourceVk *getLineLoopBufferResource();
// Observer interface implementation.
void onSubjectStateChange(const gl::Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
private: private:
angle::ObserverBinding mObserverBinding;
std::unique_ptr<StreamingBuffer> mStreamingLineLoopIndicesData; std::unique_ptr<StreamingBuffer> mStreamingLineLoopIndicesData;
VkBuffer mLineLoopIndexBuffer; VkBuffer mLineLoopIndexBuffer;
VkDeviceSize mLineLoopIndexBufferOffset; 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