Hash :
b3af2e86
Author :
Date :
2024-12-31T08:51:37
Enhance MemoryBuffer API
Add support for -
1. reserve - users can reserve sufficient capacity upfront to
minimize subsequent reallocations due to resize
2. append - to append data from a source so user doesn't need to
track offsets explicitly
Bug: angleproject:386749841
Tests: MemoryBufferTest*
Change-Id: Ibf2a3228d5a00ed34a7e0c5e3eb185e42677d676
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6135238
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: mohan maiya <m.maiya@samsung.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMMON_MEMORYBUFFER_H_
#define COMMON_MEMORYBUFFER_H_
#include "common/Optional.h"
#include "common/angleutils.h"
#include "common/debug.h"
#include <stdint.h>
#include <cstddef>
namespace angle
{
class MemoryBuffer final : NonCopyable
{
public:
MemoryBuffer() = default;
~MemoryBuffer();
MemoryBuffer(MemoryBuffer &&other);
MemoryBuffer &operator=(MemoryBuffer &&other);
// Destroy underlying memory
void destroy();
// Updates mSize to newSize. Updates mCapacity iff newSize > mCapacity
[[nodiscard]] bool resize(size_t newSize);
// Resets mSize to 0. Reserves memory and updates mCapacity iff newSize > mCapacity
[[nodiscard]] bool clearAndReserve(size_t newSize);
// Updates mCapacity iff newSize > mCapacity
[[nodiscard]] bool reserve(size_t newSize);
// Appends content from "other" MemoryBuffer
[[nodiscard]] bool append(const MemoryBuffer &other);
// Appends content from "[buffer, buffer + bufferSize)"
[[nodiscard]] bool appendRaw(const uint8_t *buffer, const size_t bufferSize);
// Sets size bound by capacity.
void setSize(size_t size)
{
ASSERT(size <= mCapacity);
mSize = size;
}
void setSizeToCapacity() { setSize(mCapacity); }
// Invalidate current content
void clear() { (void)resize(0); }
size_t size() const { return mSize; }
size_t capacity() const { return mCapacity; }
bool empty() const { return mSize == 0; }
const uint8_t *data() const { return mData; }
uint8_t *data()
{
ASSERT(mData);
return mData;
}
uint8_t &operator[](size_t pos)
{
ASSERT(mData && pos < mSize);
return mData[pos];
}
const uint8_t &operator[](size_t pos) const
{
ASSERT(mData && pos < mSize);
return mData[pos];
}
void fill(uint8_t datum);
// Only used by unit tests
// Validate total bytes allocated during a resize
void assertTotalAllocatedBytes(size_t totalAllocatedBytes) const
{
#if defined(ANGLE_ENABLE_ASSERTS)
ASSERT(totalAllocatedBytes == mTotalAllocatedBytes);
#endif // ANGLE_ENABLE_ASSERTS
}
// Validate total bytes copied during a resize
void assertTotalCopiedBytes(size_t totalCopiedBytes) const
{
#if defined(ANGLE_ENABLE_ASSERTS)
ASSERT(totalCopiedBytes == mTotalCopiedBytes);
#endif // ANGLE_ENABLE_ASSERTS
}
private:
size_t mSize = 0;
size_t mCapacity = 0;
uint8_t *mData = nullptr;
#if defined(ANGLE_ENABLE_ASSERTS)
size_t mTotalAllocatedBytes = 0;
size_t mTotalCopiedBytes = 0;
#endif // ANGLE_ENABLE_ASSERTS
};
class ScratchBuffer final : NonCopyable
{
public:
ScratchBuffer();
// If we request a scratch buffer requesting a smaller size this many times, release and
// recreate the scratch buffer. This ensures we don't have a degenerate case where we are stuck
// hogging memory.
ScratchBuffer(uint32_t lifetime);
~ScratchBuffer();
ScratchBuffer(ScratchBuffer &&other);
ScratchBuffer &operator=(ScratchBuffer &&other);
// Returns true with a memory buffer of the requested size, or false on failure.
bool get(size_t requestedSize, MemoryBuffer **memoryBufferOut);
// Same as get, but ensures new values are initialized to a fixed constant.
bool getInitialized(size_t requestedSize, MemoryBuffer **memoryBufferOut, uint8_t initValue);
// Ticks the release counter for the scratch buffer. Also done implicitly in get().
void tick();
void clear();
MemoryBuffer *getMemoryBuffer() { return &mScratchMemory; }
private:
bool getImpl(size_t requestedSize, MemoryBuffer **memoryBufferOut, Optional<uint8_t> initValue);
uint32_t mLifetime;
uint32_t mResetCounter;
MemoryBuffer mScratchMemory;
};
} // namespace angle
#endif // COMMON_MEMORYBUFFER_H_