Commit fa03eb9d by Brandon Schade Committed by Commit Bot

Vulkan: Use DynamicBuffer for BufferVk

When there is glBufferData API call, if the current VkBuffer is in use, we copy to a staging buffer to be gpu copied later. Instead of doing this second copy, write directly to a new buffer that will be used for subsequent gpu operations. BufferVk now has a DynamicBuffer to handle the logic of acquiring a new/free buffer to be used. Bug: angleproject:4380 Change-Id: I207f334013ae944090eb48c26c692a09e8815f74 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2040513Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
parent 92b3a720
...@@ -141,7 +141,7 @@ BufferVk::VertexConversionBuffer::VertexConversionBuffer(VertexConversionBuffer ...@@ -141,7 +141,7 @@ BufferVk::VertexConversionBuffer::VertexConversionBuffer(VertexConversionBuffer
BufferVk::VertexConversionBuffer::~VertexConversionBuffer() = default; BufferVk::VertexConversionBuffer::~VertexConversionBuffer() = default;
// BufferVk implementation. // BufferVk implementation.
BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state) {} BufferVk::BufferVk(const gl::BufferState &state) : BufferImpl(state), mBuffer(nullptr) {}
BufferVk::~BufferVk() {} BufferVk::~BufferVk() {}
...@@ -155,9 +155,10 @@ void BufferVk::destroy(const gl::Context *context) ...@@ -155,9 +155,10 @@ void BufferVk::destroy(const gl::Context *context)
void BufferVk::release(ContextVk *contextVk) void BufferVk::release(ContextVk *contextVk)
{ {
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
mBuffer.release(renderer);
mStagingBuffer.release(renderer); mStagingBuffer.release(renderer);
mShadowBuffer.release(); mShadowBuffer.release();
mBufferPool.release(renderer);
mBuffer = nullptr;
for (ConversionBuffer &buffer : mVertexConversionBuffers) for (ConversionBuffer &buffer : mVertexConversionBuffers)
{ {
...@@ -212,7 +213,9 @@ angle::Result BufferVk::setData(const gl::Context *context, ...@@ -212,7 +213,9 @@ angle::Result BufferVk::setData(const gl::Context *context,
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
if (size > static_cast<size_t>(mState.getSize())) // BufferData call is re-specifying the entire buffer
// Release and init a new mBuffer with this new size
if (size > 0 && size != static_cast<size_t>(mState.getSize()))
{ {
// Release and re-create the memory and buffer. // Release and re-create the memory and buffer.
release(contextVk); release(contextVk);
...@@ -230,19 +233,17 @@ angle::Result BufferVk::setData(const gl::Context *context, ...@@ -230,19 +233,17 @@ angle::Result BufferVk::setData(const gl::Context *context,
usageFlags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; usageFlags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
} }
VkBufferCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.flags = 0;
createInfo.size = roundUpPow2(size, kBufferSizeGranularity);
createInfo.usage = usageFlags;
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr;
// Assume host visible/coherent memory available. // Assume host visible/coherent memory available.
VkMemoryPropertyFlags memoryPropertyFlags = GetPreferredMemoryType(target, usage); VkMemoryPropertyFlags memoryPropertyFlags = GetPreferredMemoryType(target, usage);
ANGLE_TRY(mBuffer.init(contextVk, createInfo, memoryPropertyFlags)); // mBuffer will be allocated through a DynamicBuffer
constexpr size_t kBufferHelperAlignment = 1;
constexpr size_t kBufferHelperPoolInitialSize = 0;
mBufferPool.initWithFlags(contextVk->getRenderer(), usageFlags, kBufferHelperAlignment,
kBufferHelperPoolInitialSize, memoryPropertyFlags);
ANGLE_TRY(acquireBufferHelper(contextVk, size, &mBuffer));
// Initialize the staging buffer // Initialize the staging buffer
initializeStagingBuffer(contextVk, target, size); initializeStagingBuffer(contextVk, target, size);
...@@ -265,7 +266,7 @@ angle::Result BufferVk::setSubData(const gl::Context *context, ...@@ -265,7 +266,7 @@ angle::Result BufferVk::setSubData(const gl::Context *context,
size_t size, size_t size,
size_t offset) size_t offset)
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
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));
...@@ -279,7 +280,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -279,7 +280,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
GLintptr destOffset, GLintptr destOffset,
GLsizeiptr size) GLsizeiptr size)
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
auto *sourceBuffer = GetAs<BufferVk>(source); auto *sourceBuffer = GetAs<BufferVk>(source);
...@@ -305,7 +306,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -305,7 +306,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &sourceBuffer->getBuffer())); ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &sourceBuffer->getBuffer()));
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, &mBuffer)); ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, mBuffer));
ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer)); ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
// Enqueue a copy command on the GPU. // Enqueue a copy command on the GPU.
...@@ -313,7 +314,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -313,7 +314,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
static_cast<VkDeviceSize>(destOffset), static_cast<VkDeviceSize>(destOffset),
static_cast<VkDeviceSize>(size)}; static_cast<VkDeviceSize>(size)};
commandBuffer->copyBuffer(sourceBuffer->getBuffer().getBuffer(), mBuffer.getBuffer(), 1, commandBuffer->copyBuffer(sourceBuffer->getBuffer().getBuffer(), mBuffer->getBuffer(), 1,
&copyRegion); &copyRegion);
// The new destination buffer data may require a conversion for the next draw, so mark it dirty. // The new destination buffer data may require a conversion for the next draw, so mark it dirty.
...@@ -324,7 +325,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context, ...@@ -324,7 +325,7 @@ angle::Result BufferVk::copySubData(const gl::Context *context,
angle::Result BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr) angle::Result BufferVk::map(const gl::Context *context, GLenum access, void **mapPtr)
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
return mapImpl(vk::GetImpl(context), mapPtr); return mapImpl(vk::GetImpl(context), mapPtr);
} }
...@@ -351,14 +352,14 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk, ...@@ -351,14 +352,14 @@ angle::Result BufferVk::mapRangeImpl(ContextVk *contextVk,
{ {
if (!mShadowBuffer.valid()) if (!mShadowBuffer.valid())
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
if ((access & GL_MAP_UNSYNCHRONIZED_BIT) == 0) if ((access & GL_MAP_UNSYNCHRONIZED_BIT) == 0)
{ {
ANGLE_TRY(mBuffer.waitForIdle(contextVk)); ANGLE_TRY(mBuffer->waitForIdle(contextVk));
} }
ANGLE_TRY(mBuffer.mapWithOffset(contextVk, reinterpret_cast<uint8_t **>(mapPtr), ANGLE_TRY(mBuffer->mapWithOffset(contextVk, reinterpret_cast<uint8_t **>(mapPtr),
static_cast<size_t>(offset))); static_cast<size_t>(offset)));
} }
else else
...@@ -388,12 +389,12 @@ angle::Result BufferVk::unmap(const gl::Context *context, GLboolean *result) ...@@ -388,12 +389,12 @@ angle::Result BufferVk::unmap(const gl::Context *context, GLboolean *result)
angle::Result BufferVk::unmapImpl(ContextVk *contextVk) angle::Result BufferVk::unmapImpl(ContextVk *contextVk)
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
if (!mShadowBuffer.valid()) if (!mShadowBuffer.valid())
{ {
mBuffer.unmap(contextVk->getRenderer()); mBuffer->unmap(contextVk->getRenderer());
mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT); mBuffer->onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
} }
else else
{ {
...@@ -404,7 +405,7 @@ angle::Result BufferVk::unmapImpl(ContextVk *contextVk) ...@@ -404,7 +405,7 @@ angle::Result BufferVk::unmapImpl(ContextVk *contextVk)
// If it was a write operation we need to update the GPU buffer. // If it was a write operation we need to update the GPU buffer.
if (writeOperation) if (writeOperation)
{ {
// We do not yet know if thie data will ever be used. Perform a staged // We do not yet know if this data will ever be used. Perform a staged
// update which will get flushed if and when necessary. // update which will get flushed if and when necessary.
const uint8_t *data = getShadowBuffer(offset); const uint8_t *data = getShadowBuffer(offset);
ANGLE_TRY(stagedUpdate(contextVk, data, size, offset)); ANGLE_TRY(stagedUpdate(contextVk, data, size, offset));
...@@ -444,11 +445,11 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context, ...@@ -444,11 +445,11 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context,
if (!mShadowBuffer.valid()) if (!mShadowBuffer.valid())
{ {
// Needed before reading buffer or we could get stale data. // Needed before reading buffer or we could get stale data.
ANGLE_TRY(mBuffer.finishRunningCommands(contextVk)); ANGLE_TRY(mBuffer->finishRunningCommands(contextVk));
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
ANGLE_TRY(mBuffer.mapWithOffset(contextVk, &mapPointer, offset)); ANGLE_TRY(mBuffer->mapWithOffset(contextVk, &mapPointer, offset));
} }
else else
{ {
...@@ -457,7 +458,7 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context, ...@@ -457,7 +458,7 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context,
*outRange = gl::ComputeIndexRange(type, mapPointer, count, primitiveRestartEnabled); *outRange = gl::ComputeIndexRange(type, mapPointer, count, primitiveRestartEnabled);
mBuffer.unmap(renderer); mBuffer->unmap(renderer);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -468,13 +469,13 @@ angle::Result BufferVk::directUpdate(ContextVk *contextVk, ...@@ -468,13 +469,13 @@ angle::Result BufferVk::directUpdate(ContextVk *contextVk,
{ {
uint8_t *mapPointer = nullptr; uint8_t *mapPointer = nullptr;
ANGLE_TRY(mBuffer.mapWithOffset(contextVk, &mapPointer, offset)); ANGLE_TRY(mBuffer->mapWithOffset(contextVk, &mapPointer, offset));
ASSERT(mapPointer); ASSERT(mapPointer);
memcpy(mapPointer, data, size); memcpy(mapPointer, data, size);
mBuffer.unmap(contextVk->getRenderer()); mBuffer->unmap(contextVk->getRenderer());
mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT); mBuffer->onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -502,7 +503,7 @@ angle::Result BufferVk::stagedUpdate(ContextVk *contextVk, ...@@ -502,7 +503,7 @@ angle::Result BufferVk::stagedUpdate(ContextVk *contextVk,
// Enqueue a copy command on the GPU. // Enqueue a copy command on the GPU.
VkBufferCopy copyRegion = {stagingBufferOffset, offset, size}; VkBufferCopy copyRegion = {stagingBufferOffset, offset, size};
ANGLE_TRY(mBuffer.copyFromBuffer(contextVk, mStagingBuffer.getCurrentBuffer(), ANGLE_TRY(mBuffer->copyFromBuffer(contextVk, mStagingBuffer.getCurrentBuffer(),
VK_ACCESS_HOST_WRITE_BIT, copyRegion)); VK_ACCESS_HOST_WRITE_BIT, copyRegion));
mStagingBuffer.getCurrentBuffer()->retain(&contextVk->getResourceUseList()); mStagingBuffer.getCurrentBuffer()->retain(&contextVk->getResourceUseList());
...@@ -517,11 +518,22 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk, ...@@ -517,11 +518,22 @@ angle::Result BufferVk::setDataImpl(ContextVk *contextVk,
// Update shadow buffer // Update shadow buffer
updateShadowBuffer(data, size, offset); updateShadowBuffer(data, size, offset);
// If the buffer is currently in use, stage the update. Otherwise update the buffer directly. // if the buffer is currently in use
if (mBuffer.isCurrentlyInUse(contextVk->getLastCompletedQueueSerial())) // if size matches mBuffer's size, acquire a new BufferHelper from the pool
// else stage an update
// else update the buffer directly
if (mBuffer->isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()))
{
if (size == static_cast<size_t>(mState.getSize()))
{
ANGLE_TRY(acquireBufferHelper(contextVk, size, &mBuffer));
ANGLE_TRY(directUpdate(contextVk, data, size, offset));
}
else
{ {
ANGLE_TRY(stagedUpdate(contextVk, data, size, offset)); ANGLE_TRY(stagedUpdate(contextVk, data, size, offset));
} }
}
else else
{ {
ANGLE_TRY(directUpdate(contextVk, data, size, offset)); ANGLE_TRY(directUpdate(contextVk, data, size, offset));
...@@ -540,10 +552,10 @@ angle::Result BufferVk::copyToBufferImpl(ContextVk *contextVk, ...@@ -540,10 +552,10 @@ angle::Result BufferVk::copyToBufferImpl(ContextVk *contextVk,
{ {
vk::CommandBuffer *commandBuffer; vk::CommandBuffer *commandBuffer;
ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer)); ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer));
ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, &mBuffer)); ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, mBuffer));
ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer)); ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
commandBuffer->copyBuffer(mBuffer.getBuffer(), destBuffer->getBuffer(), copyCount, copies); commandBuffer->copyBuffer(mBuffer->getBuffer(), destBuffer->getBuffer(), copyCount, copies);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -579,4 +591,28 @@ void BufferVk::onDataChanged() ...@@ -579,4 +591,28 @@ void BufferVk::onDataChanged()
markConversionBuffersDirty(); markConversionBuffersDirty();
} }
angle::Result BufferVk::acquireBufferHelper(ContextVk *contextVk,
size_t sizeInBytes,
vk::BufferHelper **bufferHelperOut)
{
bool needToReleasePreviousBuffers = false;
size_t size = roundUpPow2(sizeInBytes, kBufferSizeGranularity);
ANGLE_TRY(mBufferPool.allocate(contextVk, size, nullptr, nullptr, nullptr,
&needToReleasePreviousBuffers));
if (needToReleasePreviousBuffers)
{
// Release previous buffers
mBufferPool.releaseInFlightBuffers(contextVk);
}
ASSERT(bufferHelperOut);
*bufferHelperOut = mBufferPool.getCurrentBuffer();
ASSERT(*bufferHelperOut);
return angle::Result::Continue;
}
} // namespace rx } // namespace rx
...@@ -84,14 +84,14 @@ class BufferVk : public BufferImpl ...@@ -84,14 +84,14 @@ class BufferVk : public BufferImpl
const vk::BufferHelper &getBuffer() const const vk::BufferHelper &getBuffer() const
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
return mBuffer; return *mBuffer;
} }
vk::BufferHelper &getBuffer() vk::BufferHelper &getBuffer()
{ {
ASSERT(mBuffer.valid()); ASSERT(mBuffer && mBuffer->valid());
return mBuffer; return *mBuffer;
} }
angle::Result mapImpl(ContextVk *contextVk, void **mapPtr); angle::Result mapImpl(ContextVk *contextVk, void **mapPtr);
...@@ -146,6 +146,10 @@ class BufferVk : public BufferImpl ...@@ -146,6 +146,10 @@ class BufferVk : public BufferImpl
void release(ContextVk *context); void release(ContextVk *context);
void markConversionBuffersDirty(); void markConversionBuffersDirty();
angle::Result acquireBufferHelper(ContextVk *contextVk,
size_t sizeInBytes,
vk::BufferHelper **bufferHelperOut);
struct VertexConversionBuffer : public ConversionBuffer struct VertexConversionBuffer : public ConversionBuffer
{ {
VertexConversionBuffer(RendererVk *renderer, VertexConversionBuffer(RendererVk *renderer,
...@@ -163,7 +167,10 @@ class BufferVk : public BufferImpl ...@@ -163,7 +167,10 @@ class BufferVk : public BufferImpl
size_t offset; size_t offset;
}; };
vk::BufferHelper mBuffer; vk::BufferHelper *mBuffer;
// Pool of BufferHelpers for mBuffer to acquire from
vk::DynamicBuffer mBufferPool;
// All staging buffer support is provided by a DynamicBuffer. // All staging buffer support is provided by a DynamicBuffer.
vk::DynamicBuffer mStagingBuffer; vk::DynamicBuffer mStagingBuffer;
......
...@@ -462,7 +462,8 @@ DynamicBuffer::DynamicBuffer() ...@@ -462,7 +462,8 @@ DynamicBuffer::DynamicBuffer()
mNextAllocationOffset(0), mNextAllocationOffset(0),
mLastFlushOrInvalidateOffset(0), mLastFlushOrInvalidateOffset(0),
mSize(0), mSize(0),
mAlignment(0) mAlignment(0),
mMemoryPropertyFlags(0)
{} {}
DynamicBuffer::DynamicBuffer(DynamicBuffer &&other) DynamicBuffer::DynamicBuffer(DynamicBuffer &&other)
...@@ -474,6 +475,7 @@ DynamicBuffer::DynamicBuffer(DynamicBuffer &&other) ...@@ -474,6 +475,7 @@ DynamicBuffer::DynamicBuffer(DynamicBuffer &&other)
mLastFlushOrInvalidateOffset(other.mLastFlushOrInvalidateOffset), mLastFlushOrInvalidateOffset(other.mLastFlushOrInvalidateOffset),
mSize(other.mSize), mSize(other.mSize),
mAlignment(other.mAlignment), mAlignment(other.mAlignment),
mMemoryPropertyFlags(other.mMemoryPropertyFlags),
mInFlightBuffers(std::move(other.mInFlightBuffers)) mInFlightBuffers(std::move(other.mInFlightBuffers))
{ {
other.mBuffer = nullptr; other.mBuffer = nullptr;
...@@ -485,8 +487,21 @@ void DynamicBuffer::init(RendererVk *renderer, ...@@ -485,8 +487,21 @@ void DynamicBuffer::init(RendererVk *renderer,
size_t initialSize, size_t initialSize,
bool hostVisible) bool hostVisible)
{ {
VkMemoryPropertyFlags memoryPropertyFlags =
(hostVisible) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
initWithFlags(renderer, usage, alignment, initialSize, memoryPropertyFlags);
}
void DynamicBuffer::initWithFlags(RendererVk *renderer,
VkBufferUsageFlags usage,
size_t alignment,
size_t initialSize,
VkMemoryPropertyFlags memoryPropertyFlags)
{
mUsage = usage; mUsage = usage;
mHostVisible = hostVisible; mHostVisible = ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0);
mMemoryPropertyFlags = memoryPropertyFlags;
// Check that we haven't overriden the initial size of the buffer in setMinimumSizeForTesting. // Check that we haven't overriden the initial size of the buffer in setMinimumSizeForTesting.
if (mInitialSize == 0) if (mInitialSize == 0)
...@@ -523,9 +538,7 @@ angle::Result DynamicBuffer::allocateNewBuffer(ContextVk *contextVk) ...@@ -523,9 +538,7 @@ angle::Result DynamicBuffer::allocateNewBuffer(ContextVk *contextVk)
createInfo.queueFamilyIndexCount = 0; createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = nullptr; createInfo.pQueueFamilyIndices = nullptr;
const VkMemoryPropertyFlags memoryProperty = ANGLE_TRY(buffer->init(contextVk, createInfo, mMemoryPropertyFlags));
mHostVisible ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(buffer->init(contextVk, createInfo, memoryProperty));
ASSERT(!mBuffer); ASSERT(!mBuffer);
mBuffer = buffer.release(); mBuffer = buffer.release();
...@@ -612,7 +625,11 @@ angle::Result DynamicBuffer::allocate(ContextVk *contextVk, ...@@ -612,7 +625,11 @@ angle::Result DynamicBuffer::allocate(ContextVk *contextVk,
*ptrOut = mappedMemory + mNextAllocationOffset; *ptrOut = mappedMemory + mNextAllocationOffset;
} }
if (offsetOut != nullptr)
{
*offsetOut = static_cast<VkDeviceSize>(mNextAllocationOffset); *offsetOut = static_cast<VkDeviceSize>(mNextAllocationOffset);
}
mNextAllocationOffset += static_cast<uint32_t>(sizeToAllocate); mNextAllocationOffset += static_cast<uint32_t>(sizeToAllocate);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -70,6 +70,13 @@ class DynamicBuffer : angle::NonCopyable ...@@ -70,6 +70,13 @@ class DynamicBuffer : angle::NonCopyable
size_t initialSize, size_t initialSize,
bool hostVisible); bool hostVisible);
// Init that gives the ability to pass in specified memory property flags for the buffer.
void initWithFlags(RendererVk *renderer,
VkBufferUsageFlags usage,
size_t alignment,
size_t initialSize,
VkMemoryPropertyFlags memoryProperty);
// This call will allocate a new region at the end of the buffer. It internally may trigger // This call will allocate a new region at the end of the buffer. It internally may trigger
// a new buffer to be created (which is returned in the optional parameter // a new buffer to be created (which is returned in the optional parameter
// `newBufferAllocatedOut`). The new region will be in the returned buffer at given offset. If // `newBufferAllocatedOut`). The new region will be in the returned buffer at given offset. If
...@@ -117,6 +124,7 @@ class DynamicBuffer : angle::NonCopyable ...@@ -117,6 +124,7 @@ class DynamicBuffer : angle::NonCopyable
uint32_t mLastFlushOrInvalidateOffset; uint32_t mLastFlushOrInvalidateOffset;
size_t mSize; size_t mSize;
size_t mAlignment; size_t mAlignment;
VkMemoryPropertyFlags mMemoryPropertyFlags;
std::vector<BufferHelper *> mInFlightBuffers; std::vector<BufferHelper *> mInFlightBuffers;
std::vector<BufferHelper *> mBufferFreeList; std::vector<BufferHelper *> mBufferFreeList;
......
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