Limit heap growth when uploading with SetSubData.
Removes unbounded heap growth by capping the heap size to 4MB and falling back to direct allocation for larger requests. BUG=dawn:239 Change-Id: I9ae660809e3c0c539fbcfbee4afcf6fb1f466355 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12720 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
This commit is contained in:
parent
6eb7d0ec3e
commit
3debb26a9e
|
@ -18,9 +18,9 @@
|
|||
|
||||
namespace dawn_native {
|
||||
|
||||
DynamicUploader::DynamicUploader(DeviceBase* device, uint64_t size) : mDevice(device) {
|
||||
mRingBuffers.emplace_back(
|
||||
std::unique_ptr<RingBuffer>(new RingBuffer{nullptr, RingBufferAllocator(size)}));
|
||||
DynamicUploader::DynamicUploader(DeviceBase* device) : mDevice(device) {
|
||||
mRingBuffers.emplace_back(std::unique_ptr<RingBuffer>(
|
||||
new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));
|
||||
}
|
||||
|
||||
void DynamicUploader::ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer) {
|
||||
|
@ -29,6 +29,19 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize, Serial serial) {
|
||||
// Disable further sub-allocation should the request be too large.
|
||||
if (allocationSize > kRingBufferSize) {
|
||||
std::unique_ptr<StagingBufferBase> stagingBuffer;
|
||||
DAWN_TRY_ASSIGN(stagingBuffer, mDevice->CreateStagingBuffer(allocationSize));
|
||||
|
||||
UploadHandle uploadHandle;
|
||||
uploadHandle.mappedBuffer = static_cast<uint8_t*>(stagingBuffer->GetMappedPointer());
|
||||
uploadHandle.stagingBuffer = stagingBuffer.get();
|
||||
|
||||
ReleaseStagingBuffer(std::move(stagingBuffer));
|
||||
return uploadHandle;
|
||||
}
|
||||
|
||||
// Note: Validation ensures size is already aligned.
|
||||
// First-fit: find next smallest buffer large enough to satisfy the allocation request.
|
||||
RingBuffer* targetRingBuffer = mRingBuffers.back().get();
|
||||
|
@ -49,18 +62,11 @@ namespace dawn_native {
|
|||
startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
|
||||
}
|
||||
|
||||
// Upon failure, append a newly created (and much larger) ring buffer to fulfill the
|
||||
// Upon failure, append a newly created ring buffer to fulfill the
|
||||
// request.
|
||||
if (startOffset == RingBufferAllocator::kInvalidOffset) {
|
||||
// Compute the new max size (in powers of two to preserve alignment).
|
||||
size_t newMaxSize = targetRingBuffer->mAllocator.GetSize() * 2;
|
||||
while (newMaxSize < allocationSize) {
|
||||
newMaxSize *= 2;
|
||||
}
|
||||
|
||||
// TODO(bryan.bernhart@intel.com): Fall-back to no sub-allocations should this fail.
|
||||
mRingBuffers.emplace_back(std::unique_ptr<RingBuffer>(
|
||||
new RingBuffer{nullptr, RingBufferAllocator(newMaxSize)}));
|
||||
new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));
|
||||
|
||||
targetRingBuffer = mRingBuffers.back().get();
|
||||
startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace dawn_native {
|
|||
|
||||
class DynamicUploader {
|
||||
public:
|
||||
DynamicUploader(DeviceBase* device, uint64_t size = kBaseUploadBufferSize);
|
||||
DynamicUploader(DeviceBase* device);
|
||||
~DynamicUploader() = default;
|
||||
|
||||
// We add functions to Release StagingBuffers to the DynamicUploader as there's
|
||||
|
@ -44,8 +44,7 @@ namespace dawn_native {
|
|||
void Deallocate(Serial lastCompletedSerial);
|
||||
|
||||
private:
|
||||
// TODO(bryan.bernhart@intel.com): Figure out this value.
|
||||
static constexpr uint64_t kBaseUploadBufferSize = 64000;
|
||||
static constexpr uint64_t kRingBufferSize = 4 * 1024 * 1024;
|
||||
|
||||
struct RingBuffer {
|
||||
std::unique_ptr<StagingBufferBase> mStagingBuffer;
|
||||
|
|
|
@ -142,10 +142,6 @@ void BufferUploadPerf::Step() {
|
|||
}
|
||||
|
||||
TEST_P(BufferUploadPerf, Run) {
|
||||
// TODO(crbug.com/dawn/239): Investigate why large buffer uploads via SetSubData fail.
|
||||
DAWN_SKIP_TEST_IF(GetParam().uploadMethod == UploadMethod::SetSubData &&
|
||||
GetParam().uploadSize == UploadSize::BufferSize_16MB);
|
||||
|
||||
RunTest();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue