mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-19 11:35:58 +00:00
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 {
|
namespace dawn_native {
|
||||||
|
|
||||||
DynamicUploader::DynamicUploader(DeviceBase* device, uint64_t size) : mDevice(device) {
|
DynamicUploader::DynamicUploader(DeviceBase* device) : mDevice(device) {
|
||||||
mRingBuffers.emplace_back(
|
mRingBuffers.emplace_back(std::unique_ptr<RingBuffer>(
|
||||||
std::unique_ptr<RingBuffer>(new RingBuffer{nullptr, RingBufferAllocator(size)}));
|
new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicUploader::ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer) {
|
void DynamicUploader::ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer) {
|
||||||
@ -29,6 +29,19 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize, Serial serial) {
|
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.
|
// Note: Validation ensures size is already aligned.
|
||||||
// First-fit: find next smallest buffer large enough to satisfy the allocation request.
|
// First-fit: find next smallest buffer large enough to satisfy the allocation request.
|
||||||
RingBuffer* targetRingBuffer = mRingBuffers.back().get();
|
RingBuffer* targetRingBuffer = mRingBuffers.back().get();
|
||||||
@ -49,18 +62,11 @@ namespace dawn_native {
|
|||||||
startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
|
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.
|
// request.
|
||||||
if (startOffset == RingBufferAllocator::kInvalidOffset) {
|
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>(
|
mRingBuffers.emplace_back(std::unique_ptr<RingBuffer>(
|
||||||
new RingBuffer{nullptr, RingBufferAllocator(newMaxSize)}));
|
new RingBuffer{nullptr, RingBufferAllocator(kRingBufferSize)}));
|
||||||
|
|
||||||
targetRingBuffer = mRingBuffers.back().get();
|
targetRingBuffer = mRingBuffers.back().get();
|
||||||
startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
|
startOffset = targetRingBuffer->mAllocator.Allocate(allocationSize, serial);
|
||||||
|
@ -31,7 +31,7 @@ namespace dawn_native {
|
|||||||
|
|
||||||
class DynamicUploader {
|
class DynamicUploader {
|
||||||
public:
|
public:
|
||||||
DynamicUploader(DeviceBase* device, uint64_t size = kBaseUploadBufferSize);
|
DynamicUploader(DeviceBase* device);
|
||||||
~DynamicUploader() = default;
|
~DynamicUploader() = default;
|
||||||
|
|
||||||
// We add functions to Release StagingBuffers to the DynamicUploader as there's
|
// We add functions to Release StagingBuffers to the DynamicUploader as there's
|
||||||
@ -44,8 +44,7 @@ namespace dawn_native {
|
|||||||
void Deallocate(Serial lastCompletedSerial);
|
void Deallocate(Serial lastCompletedSerial);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO(bryan.bernhart@intel.com): Figure out this value.
|
static constexpr uint64_t kRingBufferSize = 4 * 1024 * 1024;
|
||||||
static constexpr uint64_t kBaseUploadBufferSize = 64000;
|
|
||||||
|
|
||||||
struct RingBuffer {
|
struct RingBuffer {
|
||||||
std::unique_ptr<StagingBufferBase> mStagingBuffer;
|
std::unique_ptr<StagingBufferBase> mStagingBuffer;
|
||||||
|
@ -142,10 +142,6 @@ void BufferUploadPerf::Step() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(BufferUploadPerf, Run) {
|
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();
|
RunTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user