Use typed integers for the ExecutionSerial
This will prevent mixing it up with other serial types in the future. Bug: dawn:442 Change-Id: I74e964708acc62eb0f33127cc48f1b9a7b171d11 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28923 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
ad4a66ec8f
commit
62139fcca7
|
@ -172,7 +172,6 @@ if (is_win || is_linux || is_chromeos || is_mac || is_fuchsia || is_android) {
|
|||
"RefCounted.h",
|
||||
"Result.cpp",
|
||||
"Result.h",
|
||||
"Serial.h",
|
||||
"SerialMap.h",
|
||||
"SerialQueue.h",
|
||||
"SerialStorage.h",
|
||||
|
|
|
@ -35,7 +35,6 @@ target_sources(dawn_common PRIVATE
|
|||
"RefCounted.h"
|
||||
"Result.cpp"
|
||||
"Result.h"
|
||||
"Serial.h"
|
||||
"SerialMap.h"
|
||||
"SerialQueue.h"
|
||||
"SerialStorage.h"
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2017 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef COMMON_SERIAL_H_
|
||||
#define COMMON_SERIAL_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using Serial = uint64_t;
|
||||
|
||||
#endif // COMMON_SERIAL_H_
|
|
@ -16,7 +16,6 @@
|
|||
#define COMMON_SERIALSTORAGE_H_
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "common/Serial.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
|
|
@ -326,15 +326,15 @@ namespace dawn_native {
|
|||
return mMapRequestTracker.get();
|
||||
}
|
||||
|
||||
Serial DeviceBase::GetCompletedCommandSerial() const {
|
||||
ExecutionSerial DeviceBase::GetCompletedCommandSerial() const {
|
||||
return mCompletedSerial;
|
||||
}
|
||||
|
||||
Serial DeviceBase::GetLastSubmittedCommandSerial() const {
|
||||
ExecutionSerial DeviceBase::GetLastSubmittedCommandSerial() const {
|
||||
return mLastSubmittedSerial;
|
||||
}
|
||||
|
||||
Serial DeviceBase::GetFutureCallbackSerial() const {
|
||||
ExecutionSerial DeviceBase::GetFutureCallbackSerial() const {
|
||||
return mFutureCallbackSerial;
|
||||
}
|
||||
|
||||
|
@ -343,28 +343,29 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
void DeviceBase::AssumeCommandsComplete() {
|
||||
Serial maxSerial = std::max(mLastSubmittedSerial + 1, mFutureCallbackSerial);
|
||||
ExecutionSerial maxSerial = ExecutionSerial(
|
||||
std::max(mLastSubmittedSerial + ExecutionSerial(1), mFutureCallbackSerial));
|
||||
mLastSubmittedSerial = maxSerial;
|
||||
mCompletedSerial = maxSerial;
|
||||
}
|
||||
|
||||
Serial DeviceBase::GetPendingCommandSerial() const {
|
||||
return mLastSubmittedSerial + 1;
|
||||
ExecutionSerial DeviceBase::GetPendingCommandSerial() const {
|
||||
return mLastSubmittedSerial + ExecutionSerial(1);
|
||||
}
|
||||
|
||||
void DeviceBase::AddFutureCallbackSerial(Serial serial) {
|
||||
void DeviceBase::AddFutureCallbackSerial(ExecutionSerial serial) {
|
||||
if (serial > mFutureCallbackSerial) {
|
||||
mFutureCallbackSerial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceBase::CheckPassedSerials() {
|
||||
Serial completedSerial = CheckAndUpdateCompletedSerials();
|
||||
ExecutionSerial completedSerial = CheckAndUpdateCompletedSerials();
|
||||
|
||||
ASSERT(completedSerial <= mLastSubmittedSerial);
|
||||
// completedSerial should not be less than mCompletedSerial unless it is 0.
|
||||
// It can be 0 when there's no fences to check.
|
||||
ASSERT(completedSerial >= mCompletedSerial || completedSerial == 0);
|
||||
ASSERT(completedSerial >= mCompletedSerial || completedSerial == ExecutionSerial(0));
|
||||
|
||||
if (completedSerial > mCompletedSerial) {
|
||||
mCompletedSerial = completedSerial;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#ifndef DAWNNATIVE_DEVICE_H_
|
||||
#define DAWNNATIVE_DEVICE_H_
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/Extensions.h"
|
||||
|
@ -89,10 +88,10 @@ namespace dawn_native {
|
|||
CommandEncoder* encoder,
|
||||
const CommandBufferDescriptor* descriptor) = 0;
|
||||
|
||||
Serial GetCompletedCommandSerial() const;
|
||||
Serial GetLastSubmittedCommandSerial() const;
|
||||
Serial GetFutureCallbackSerial() const;
|
||||
Serial GetPendingCommandSerial() const;
|
||||
ExecutionSerial GetCompletedCommandSerial() const;
|
||||
ExecutionSerial GetLastSubmittedCommandSerial() const;
|
||||
ExecutionSerial GetFutureCallbackSerial() const;
|
||||
ExecutionSerial GetPendingCommandSerial() const;
|
||||
virtual MaybeError TickImpl() = 0;
|
||||
|
||||
// Many Dawn objects are completely immutable once created which means that if two
|
||||
|
@ -226,7 +225,7 @@ namespace dawn_native {
|
|||
size_t GetDeprecationWarningCountForTesting();
|
||||
void EmitDeprecationWarning(const char* warning);
|
||||
void LoseForTesting();
|
||||
void AddFutureCallbackSerial(Serial serial);
|
||||
void AddFutureCallbackSerial(ExecutionSerial serial);
|
||||
|
||||
virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0;
|
||||
virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0;
|
||||
|
@ -313,7 +312,7 @@ namespace dawn_native {
|
|||
|
||||
// Each backend should implement to check their passed fences if there are any and return a
|
||||
// completed serial. Return 0 should indicate no fences to check.
|
||||
virtual Serial CheckAndUpdateCompletedSerials() = 0;
|
||||
virtual ExecutionSerial CheckAndUpdateCompletedSerials() = 0;
|
||||
// During shut down of device, some operations might have been started since the last submit
|
||||
// and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
|
||||
// make all commands look completed.
|
||||
|
@ -326,9 +325,9 @@ namespace dawn_native {
|
|||
// stale serials.
|
||||
// mFutureCallbackSerial tracks the largest serial we need to tick to for the callbacks to
|
||||
// fire
|
||||
Serial mCompletedSerial = 0;
|
||||
Serial mLastSubmittedSerial = 0;
|
||||
Serial mFutureCallbackSerial = 0;
|
||||
ExecutionSerial mCompletedSerial = ExecutionSerial(0);
|
||||
ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
|
||||
ExecutionSerial mFutureCallbackSerial = ExecutionSerial(0);
|
||||
|
||||
// ShutDownImpl is used to clean up and release resources used by device, does not wait for
|
||||
// GPU or check errors.
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace dawn_native {
|
|||
}
|
||||
|
||||
ResultOrError<UploadHandle> DynamicUploader::AllocateInternal(uint64_t allocationSize,
|
||||
Serial serial) {
|
||||
ExecutionSerial serial) {
|
||||
// Disable further sub-allocation should the request be too large.
|
||||
if (allocationSize > kRingBufferSize) {
|
||||
std::unique_ptr<StagingBufferBase> stagingBuffer;
|
||||
|
@ -95,7 +95,7 @@ namespace dawn_native {
|
|||
return uploadHandle;
|
||||
}
|
||||
|
||||
void DynamicUploader::Deallocate(Serial lastCompletedSerial) {
|
||||
void DynamicUploader::Deallocate(ExecutionSerial lastCompletedSerial) {
|
||||
// Reclaim memory within the ring buffers by ticking (or removing requests no longer
|
||||
// in-flight).
|
||||
for (size_t i = 0; i < mRingBuffers.size(); ++i) {
|
||||
|
@ -113,7 +113,7 @@ namespace dawn_native {
|
|||
// TODO(dawn:512): Optimize this function so that it doesn't allocate additional memory
|
||||
// when it's not necessary.
|
||||
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize,
|
||||
Serial serial,
|
||||
ExecutionSerial serial,
|
||||
uint64_t offsetAlignment) {
|
||||
ASSERT(offsetAlignment > 0);
|
||||
UploadHandle uploadHandle;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define DAWNNATIVE_DYNAMICUPLOADER_H_
|
||||
|
||||
#include "dawn_native/Forward.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/RingBufferAllocator.h"
|
||||
#include "dawn_native/StagingBuffer.h"
|
||||
|
||||
|
@ -41,9 +42,9 @@ namespace dawn_native {
|
|||
void ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer);
|
||||
|
||||
ResultOrError<UploadHandle> Allocate(uint64_t allocationSize,
|
||||
Serial serial,
|
||||
ExecutionSerial serial,
|
||||
uint64_t offsetAlignment);
|
||||
void Deallocate(Serial lastCompletedSerial);
|
||||
void Deallocate(ExecutionSerial lastCompletedSerial);
|
||||
|
||||
private:
|
||||
static constexpr uint64_t kRingBufferSize = 4 * 1024 * 1024;
|
||||
|
@ -53,10 +54,11 @@ namespace dawn_native {
|
|||
RingBufferAllocator mAllocator;
|
||||
};
|
||||
|
||||
ResultOrError<UploadHandle> AllocateInternal(uint64_t allocationSize, Serial serial);
|
||||
ResultOrError<UploadHandle> AllocateInternal(uint64_t allocationSize,
|
||||
ExecutionSerial serial);
|
||||
|
||||
std::vector<std::unique_ptr<RingBuffer>> mRingBuffers;
|
||||
SerialQueue<Serial, std::unique_ptr<StagingBufferBase>> mReleasedStagingBuffers;
|
||||
SerialQueue<ExecutionSerial, std::unique_ptr<StagingBufferBase>> mReleasedStagingBuffers;
|
||||
DeviceBase* mDevice;
|
||||
};
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -28,11 +28,10 @@ namespace dawn_native {
|
|||
// The tracker is destroyed when the Device is destroyed. We need to
|
||||
// call Destroy on all in-flight error scopes so they resolve their callbacks
|
||||
// with UNKNOWN.
|
||||
constexpr Serial maxSerial = std::numeric_limits<Serial>::max();
|
||||
for (Ref<ErrorScope>& scope : mScopesInFlight.IterateUpTo(maxSerial)) {
|
||||
for (Ref<ErrorScope>& scope : mScopesInFlight.IterateUpTo(kMaxExecutionSerial)) {
|
||||
scope->UnlinkForShutdown();
|
||||
}
|
||||
Tick(maxSerial);
|
||||
Tick(kMaxExecutionSerial);
|
||||
}
|
||||
|
||||
void ErrorScopeTracker::TrackUntilLastSubmitComplete(ErrorScope* scope) {
|
||||
|
@ -40,7 +39,7 @@ namespace dawn_native {
|
|||
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
void ErrorScopeTracker::Tick(Serial completedSerial) {
|
||||
void ErrorScopeTracker::Tick(ExecutionSerial completedSerial) {
|
||||
mScopesInFlight.ClearUpTo(completedSerial);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "common/RefCounted.h"
|
||||
#include "common/SerialQueue.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
|
@ -30,11 +31,11 @@ namespace dawn_native {
|
|||
|
||||
void TrackUntilLastSubmitComplete(ErrorScope* scope);
|
||||
|
||||
void Tick(Serial completedSerial);
|
||||
void Tick(ExecutionSerial completedSerial);
|
||||
|
||||
protected:
|
||||
DeviceBase* mDevice;
|
||||
SerialQueue<Serial, Ref<ErrorScope>> mScopesInFlight;
|
||||
SerialQueue<ExecutionSerial, Ref<ErrorScope>> mScopesInFlight;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace dawn_native {
|
|||
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
void FenceSignalTracker::Tick(Serial finishedSerial) {
|
||||
void FenceSignalTracker::Tick(ExecutionSerial finishedSerial) {
|
||||
for (auto& fenceInFlight : mFencesInFlight.IterateUpTo(finishedSerial)) {
|
||||
fenceInFlight.fence->SetCompletedValue(fenceInFlight.value);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ namespace dawn_native {
|
|||
|
||||
void UpdateFenceOnComplete(Fence* fence, FenceAPISerial value);
|
||||
|
||||
void Tick(Serial finishedSerial);
|
||||
void Tick(ExecutionSerial finishedSerial);
|
||||
|
||||
private:
|
||||
DeviceBase* mDevice;
|
||||
SerialQueue<Serial, FenceInFlight> mFencesInFlight;
|
||||
SerialQueue<ExecutionSerial, FenceInFlight> mFencesInFlight;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -57,6 +57,13 @@ namespace dawn_native {
|
|||
// The type for the WebGPU API fence serial values.
|
||||
using FenceAPISerial = TypedInteger<struct FenceAPISerialT, uint64_t>;
|
||||
|
||||
// A serial used to watch the progression of GPU execution on a queue, each time operations
|
||||
// that need to be followed individually are scheduled for execution on a queue, the serial
|
||||
// is incremented by one. This way to know if something is done executing, we just need to
|
||||
// compare its serial with the currently completed serial.
|
||||
using ExecutionSerial = TypedInteger<struct QueueSerialT, uint64_t>;
|
||||
constexpr ExecutionSerial kMaxExecutionSerial = ExecutionSerial(~uint64_t(0));
|
||||
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_INTEGERTYPES_H_
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace dawn_native {
|
|||
mDevice->AddFutureCallbackSerial(mDevice->GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
void MapRequestTracker::Tick(Serial finishedSerial) {
|
||||
void MapRequestTracker::Tick(ExecutionSerial finishedSerial) {
|
||||
for (auto& request : mInflightRequests.IterateUpTo(finishedSerial)) {
|
||||
request.buffer->OnMapRequestCompleted(request.id);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace dawn_native {
|
|||
~MapRequestTracker();
|
||||
|
||||
void Track(BufferBase* buffer, MapRequestID mapID);
|
||||
void Tick(Serial finishedSerial);
|
||||
void Tick(ExecutionSerial finishedSerial);
|
||||
|
||||
private:
|
||||
DeviceBase* mDevice;
|
||||
|
@ -37,7 +37,7 @@ namespace dawn_native {
|
|||
Ref<BufferBase> buffer;
|
||||
MapRequestID id;
|
||||
};
|
||||
SerialQueue<Serial, Request> mInflightRequests;
|
||||
SerialQueue<ExecutionSerial, Request> mInflightRequests;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace dawn_native {
|
|||
RingBufferAllocator::RingBufferAllocator(uint64_t maxSize) : mMaxBlockSize(maxSize) {
|
||||
}
|
||||
|
||||
void RingBufferAllocator::Deallocate(Serial lastCompletedSerial) {
|
||||
void RingBufferAllocator::Deallocate(ExecutionSerial lastCompletedSerial) {
|
||||
// Reclaim memory from previously recorded blocks.
|
||||
for (Request& request : mInflightRequests.IterateUpTo(lastCompletedSerial)) {
|
||||
mUsedStartOffset = request.endOffset;
|
||||
|
@ -62,7 +62,7 @@ namespace dawn_native {
|
|||
// queue, which identifies an existing (or new) frames-worth of resources. Internally, the
|
||||
// ring-buffer maintains offsets of 3 "memory" states: Free, Reclaimed, and Used. This is done
|
||||
// in FIFO order as older frames would free resources before newer ones.
|
||||
uint64_t RingBufferAllocator::Allocate(uint64_t allocationSize, Serial serial) {
|
||||
uint64_t RingBufferAllocator::Allocate(uint64_t allocationSize, ExecutionSerial serial) {
|
||||
// Check if the buffer is full by comparing the used size.
|
||||
// If the buffer is not split where waste occurs (e.g. cannot fit new sub-alloc in front), a
|
||||
// subsequent sub-alloc could fail where the used size was previously adjusted to include
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define DAWNNATIVE_RINGBUFFERALLOCATOR_H_
|
||||
|
||||
#include "common/SerialQueue.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
@ -29,8 +30,8 @@ namespace dawn_native {
|
|||
RingBufferAllocator(uint64_t maxSize);
|
||||
~RingBufferAllocator() = default;
|
||||
|
||||
uint64_t Allocate(uint64_t allocationSize, Serial serial);
|
||||
void Deallocate(Serial lastCompletedSerial);
|
||||
uint64_t Allocate(uint64_t allocationSize, ExecutionSerial serial);
|
||||
void Deallocate(ExecutionSerial lastCompletedSerial);
|
||||
|
||||
uint64_t GetSize() const;
|
||||
bool Empty() const;
|
||||
|
@ -44,8 +45,9 @@ namespace dawn_native {
|
|||
uint64_t size;
|
||||
};
|
||||
|
||||
SerialQueue<Serial, Request> mInflightRequests; // Queue of the recorded sub-alloc requests
|
||||
// (e.g. frame of resources).
|
||||
SerialQueue<ExecutionSerial, Request>
|
||||
mInflightRequests; // Queue of the recorded sub-alloc requests
|
||||
// (e.g. frame of resources).
|
||||
|
||||
uint64_t mUsedEndOffset = 0; // Tail of used sub-alloc requests (in bytes).
|
||||
uint64_t mUsedStartOffset = 0; // Head of used sub-alloc requests (in bytes).
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#define DAWNNATIVE_D3D12_BINDGROUPD3D12_H_
|
||||
|
||||
#include "common/PlacementAllocated.h"
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/BindGroup.h"
|
||||
#include "dawn_native/d3d12/CPUDescriptorHeapAllocationD3D12.h"
|
||||
#include "dawn_native/d3d12/GPUDescriptorHeapAllocationD3D12.h"
|
||||
|
|
|
@ -240,7 +240,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
// occur. When that buffer is used again, the previously recorded serial must be compared to
|
||||
// the last completed serial to determine if the buffer has implicity decayed to the common
|
||||
// state.
|
||||
const Serial pendingCommandSerial = ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
const ExecutionSerial pendingCommandSerial =
|
||||
ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
if (pendingCommandSerial > mLastUsedSerial) {
|
||||
lastState = D3D12_RESOURCE_STATE_COMMON;
|
||||
mLastUsedSerial = pendingCommandSerial;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "dawn_native/Buffer.h"
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
|
@ -72,7 +71,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
ResourceHeapAllocation mResourceAllocation;
|
||||
bool mFixedResourceState = false;
|
||||
wgpu::BufferUsage mLastUsage = wgpu::BufferUsage::None;
|
||||
Serial mLastUsedSerial = UINT64_MAX;
|
||||
ExecutionSerial mLastUsedSerial = std::numeric_limits<ExecutionSerial>::max();
|
||||
|
||||
D3D12_RANGE mWrittenMappedRange = {0, 0};
|
||||
void* mMappedData = nullptr;
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
ResultOrError<ID3D12CommandAllocator*> CommandAllocatorManager::ReserveCommandAllocator() {
|
||||
// If there are no free allocators, get the oldest serial in flight and wait on it
|
||||
if (mFreeAllocators.none()) {
|
||||
const uint64_t firstSerial = mInFlightCommandAllocators.FirstSerial();
|
||||
const ExecutionSerial firstSerial = mInFlightCommandAllocators.FirstSerial();
|
||||
DAWN_TRY(device->WaitForSerial(firstSerial));
|
||||
DAWN_TRY(Tick(firstSerial));
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mCommandAllocators[firstFreeIndex].Get();
|
||||
}
|
||||
|
||||
MaybeError CommandAllocatorManager::Tick(uint64_t lastCompletedSerial) {
|
||||
MaybeError CommandAllocatorManager::Tick(ExecutionSerial lastCompletedSerial) {
|
||||
// Reset all command allocators that are no longer in flight
|
||||
for (auto it : mInFlightCommandAllocators.IterateUpTo(lastCompletedSerial)) {
|
||||
DAWN_TRY(CheckHRESULT(it.commandAllocator->Reset(), "D3D12 reset command allocator"));
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "common/SerialQueue.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
|
@ -33,7 +34,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
// A CommandAllocator that is reserved must be used on the next ExecuteCommandLists
|
||||
// otherwise its commands may be reset before execution has completed on the GPU
|
||||
ResultOrError<ID3D12CommandAllocator*> ReserveCommandAllocator();
|
||||
MaybeError Tick(uint64_t lastCompletedSerial);
|
||||
MaybeError Tick(ExecutionSerial lastCompletedSerial);
|
||||
|
||||
private:
|
||||
Device* device;
|
||||
|
@ -49,7 +50,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
ComPtr<ID3D12CommandAllocator> mCommandAllocators[kMaxCommandAllocators];
|
||||
std::bitset<kMaxCommandAllocators> mFreeAllocators;
|
||||
SerialQueue<Serial, IndexedCommandAllocator> mInFlightCommandAllocators;
|
||||
SerialQueue<ExecutionSerial, IndexedCommandAllocator> mInFlightCommandAllocators;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return {};
|
||||
}
|
||||
|
||||
void CommandRecordingContext::TrackHeapUsage(Heap* heap, Serial serial) {
|
||||
void CommandRecordingContext::TrackHeapUsage(Heap* heap, ExecutionSerial serial) {
|
||||
// Before tracking the heap, check the last serial it was recorded on to ensure we aren't
|
||||
// tracking it more than once.
|
||||
if (heap->GetLastUsage() < serial) {
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
MaybeError ExecuteCommandList(Device* device);
|
||||
|
||||
void TrackHeapUsage(Heap* heap, Serial serial);
|
||||
void TrackHeapUsage(Heap* heap, ExecutionSerial serial);
|
||||
|
||||
private:
|
||||
ComPtr<ID3D12GraphicsCommandList> mD3d12CommandList;
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
mCommandQueue.As(&mD3d12SharingContract);
|
||||
|
||||
DAWN_TRY(
|
||||
CheckHRESULT(mD3d12Device->CreateFence(GetLastSubmittedCommandSerial(),
|
||||
CheckHRESULT(mD3d12Device->CreateFence(uint64_t(GetLastSubmittedCommandSerial()),
|
||||
D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence)),
|
||||
"D3D12 create fence"));
|
||||
|
||||
|
@ -219,7 +219,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
MaybeError Device::TickImpl() {
|
||||
// Perform cleanup operations to free unused objects
|
||||
Serial completedSerial = GetCompletedCommandSerial();
|
||||
ExecutionSerial completedSerial = GetCompletedCommandSerial();
|
||||
|
||||
mResourceAllocatorManager->Tick(completedSerial);
|
||||
DAWN_TRY(mCommandAllocatorManager->Tick(completedSerial));
|
||||
|
@ -239,14 +239,15 @@ namespace dawn_native { namespace d3d12 {
|
|||
MaybeError Device::NextSerial() {
|
||||
IncrementLastSubmittedCommandSerial();
|
||||
|
||||
return CheckHRESULT(mCommandQueue->Signal(mFence.Get(), GetLastSubmittedCommandSerial()),
|
||||
"D3D12 command queue signal fence");
|
||||
return CheckHRESULT(
|
||||
mCommandQueue->Signal(mFence.Get(), uint64_t(GetLastSubmittedCommandSerial())),
|
||||
"D3D12 command queue signal fence");
|
||||
}
|
||||
|
||||
MaybeError Device::WaitForSerial(uint64_t serial) {
|
||||
MaybeError Device::WaitForSerial(ExecutionSerial serial) {
|
||||
CheckPassedSerials();
|
||||
if (GetCompletedCommandSerial() < serial) {
|
||||
DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(serial, mFenceEvent),
|
||||
DAWN_TRY(CheckHRESULT(mFence->SetEventOnCompletion(uint64_t(serial), mFenceEvent),
|
||||
"D3D12 set event on completion"));
|
||||
WaitForSingleObject(mFenceEvent, INFINITE);
|
||||
CheckPassedSerials();
|
||||
|
@ -254,8 +255,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
return {};
|
||||
}
|
||||
|
||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||
return mFence->GetCompletedValue();
|
||||
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
|
||||
return ExecutionSerial(mFence->GetCompletedValue());
|
||||
}
|
||||
|
||||
void Device::ReferenceUntilUnused(ComPtr<IUnknown> object) {
|
||||
|
@ -576,7 +577,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
|
||||
// We need to handle clearing up com object refs that were enqeued after TickImpl
|
||||
mUsedComObjectRefs.ClearUpTo(std::numeric_limits<Serial>::max());
|
||||
mUsedComObjectRefs.ClearUpTo(std::numeric_limits<ExecutionSerial>::max());
|
||||
|
||||
ASSERT(mUsedComObjectRefs.Empty());
|
||||
ASSERT(!mPendingCommands.IsOpen());
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
const D3D12DeviceInfo& GetDeviceInfo() const;
|
||||
|
||||
MaybeError NextSerial();
|
||||
MaybeError WaitForSerial(Serial serial);
|
||||
MaybeError WaitForSerial(ExecutionSerial serial);
|
||||
|
||||
void ReferenceUntilUnused(ComPtr<IUnknown> object);
|
||||
|
||||
|
@ -180,7 +180,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
ComPtr<ID3D12Fence> mFence;
|
||||
HANDLE mFenceEvent = nullptr;
|
||||
Serial CheckAndUpdateCompletedSerials() override;
|
||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
ComPtr<ID3D12Device> mD3d12Device; // Device is owned by adapter and will not be outlived.
|
||||
ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||
|
@ -196,7 +196,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
CommandRecordingContext mPendingCommands;
|
||||
|
||||
SerialQueue<Serial, ComPtr<IUnknown>> mUsedComObjectRefs;
|
||||
SerialQueue<ExecutionSerial, ComPtr<IUnknown>> mUsedComObjectRefs;
|
||||
|
||||
std::unique_ptr<CommandAllocatorManager> mCommandAllocatorManager;
|
||||
std::unique_ptr<ResourceAllocatorManager> mResourceAllocatorManager;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
GPUDescriptorHeapAllocation::GPUDescriptorHeapAllocation(
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor,
|
||||
Serial lastUsageSerial,
|
||||
ExecutionSerial lastUsageSerial,
|
||||
HeapVersionID heapSerial)
|
||||
: mBaseDescriptor(baseDescriptor),
|
||||
mLastUsageSerial(lastUsageSerial),
|
||||
|
@ -29,7 +29,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mBaseDescriptor;
|
||||
}
|
||||
|
||||
Serial GPUDescriptorHeapAllocation::GetLastUsageSerial() const {
|
||||
ExecutionSerial GPUDescriptorHeapAllocation::GetLastUsageSerial() const {
|
||||
return mLastUsageSerial;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef DAWNNATIVE_D3D12_GPUDESCRIPTORHEAPALLOCATION_H_
|
||||
#define DAWNNATIVE_D3D12_GPUDESCRIPTORHEAPALLOCATION_H_
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/d3d12/IntegerTypes.h"
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
|
@ -26,16 +26,16 @@ namespace dawn_native { namespace d3d12 {
|
|||
public:
|
||||
GPUDescriptorHeapAllocation() = default;
|
||||
GPUDescriptorHeapAllocation(D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor,
|
||||
Serial lastUsageSerial,
|
||||
ExecutionSerial lastUsageSerial,
|
||||
HeapVersionID heapSerial);
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE GetBaseDescriptor() const;
|
||||
Serial GetLastUsageSerial() const;
|
||||
ExecutionSerial GetLastUsageSerial() const;
|
||||
HeapVersionID GetHeapSerial() const;
|
||||
|
||||
private:
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE mBaseDescriptor = {0};
|
||||
Serial mLastUsageSerial = 0;
|
||||
ExecutionSerial mLastUsageSerial = ExecutionSerial(0);
|
||||
HeapVersionID mHeapSerial = HeapVersionID(0);
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
// Set the initial serial of buffers to 0 so that we don't wait on them when they are first
|
||||
// used
|
||||
mBufferSerials.resize(kFrameCount, 0);
|
||||
mBufferSerials.resize(kFrameCount, ExecutionSerial(0));
|
||||
|
||||
return DAWN_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
#include "dawn/dawn_wsi.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
#include <vector>
|
||||
|
@ -50,7 +51,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
ComPtr<IDXGISwapChain3> mSwapChain = nullptr;
|
||||
std::vector<ComPtr<ID3D12Resource>> mBuffers;
|
||||
std::vector<uint64_t> mBufferSerials;
|
||||
std::vector<ExecutionSerial> mBufferSerials;
|
||||
uint32_t mCurrentBuffer;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,19 +34,19 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mD3d12Pageable.Get();
|
||||
}
|
||||
|
||||
Serial Pageable::GetLastUsage() const {
|
||||
ExecutionSerial Pageable::GetLastUsage() const {
|
||||
return mLastUsage;
|
||||
}
|
||||
|
||||
void Pageable::SetLastUsage(Serial serial) {
|
||||
void Pageable::SetLastUsage(ExecutionSerial serial) {
|
||||
mLastUsage = serial;
|
||||
}
|
||||
|
||||
uint64_t Pageable::GetLastSubmission() const {
|
||||
ExecutionSerial Pageable::GetLastSubmission() const {
|
||||
return mLastSubmission;
|
||||
}
|
||||
|
||||
void Pageable::SetLastSubmission(Serial serial) {
|
||||
void Pageable::SetLastSubmission(ExecutionSerial serial) {
|
||||
mLastSubmission = serial;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#define DAWNNATIVE_D3D12_PAGEABLED3D12_H_
|
||||
|
||||
#include "common/LinkedList.h"
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/D3D12Backend.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
@ -36,14 +36,14 @@ namespace dawn_native { namespace d3d12 {
|
|||
// We set mLastRecordingSerial to denote the serial this pageable was last recorded to be
|
||||
// used. We must check this serial against the current serial when recording usages to
|
||||
// ensure we do not process residency for this pageable multiple times.
|
||||
Serial GetLastUsage() const;
|
||||
void SetLastUsage(Serial serial);
|
||||
ExecutionSerial GetLastUsage() const;
|
||||
void SetLastUsage(ExecutionSerial serial);
|
||||
|
||||
// The residency manager must know the last serial that any portion of the pageable was
|
||||
// submitted to be used so that we can ensure this pageable stays resident in memory at
|
||||
// least until that serial has completed.
|
||||
uint64_t GetLastSubmission() const;
|
||||
void SetLastSubmission(Serial serial);
|
||||
ExecutionSerial GetLastSubmission() const;
|
||||
void SetLastSubmission(ExecutionSerial serial);
|
||||
|
||||
MemorySegment GetMemorySegment() const;
|
||||
|
||||
|
@ -63,14 +63,14 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
private:
|
||||
// mLastUsage denotes the last time this pageable was recorded for use.
|
||||
Serial mLastUsage = 0;
|
||||
ExecutionSerial mLastUsage = ExecutionSerial(0);
|
||||
// mLastSubmission denotes the last time this pageable was submitted to the GPU. Note that
|
||||
// although this variable often contains the same value as mLastUsage, it can differ in some
|
||||
// situations. When some asynchronous APIs (like WriteBuffer) are called, mLastUsage is
|
||||
// updated upon the call, but the backend operation is deferred until the next submission
|
||||
// to the GPU. This makes mLastSubmission unique from mLastUsage, and allows us to
|
||||
// accurately identify when a pageable can be evicted.
|
||||
Serial mLastSubmission = 0;
|
||||
ExecutionSerial mLastSubmission = ExecutionSerial(0);
|
||||
MemorySegment mMemorySegment;
|
||||
uint32_t mResidencyLockRefCount = 0;
|
||||
uint64_t mSize = 0;
|
||||
|
|
|
@ -156,7 +156,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
Pageable* pageable = memorySegment->lruCache.head()->value();
|
||||
|
||||
Serial lastSubmissionSerial = pageable->GetLastSubmission();
|
||||
ExecutionSerial lastSubmissionSerial = pageable->GetLastSubmission();
|
||||
|
||||
// If the next candidate for eviction was inserted into the LRU during the current serial,
|
||||
// it is because more memory is being used in a single command list than is available.
|
||||
|
@ -243,7 +243,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
uint64_t localSizeToMakeResident = 0;
|
||||
uint64_t nonLocalSizeToMakeResident = 0;
|
||||
|
||||
Serial pendingCommandSerial = mDevice->GetPendingCommandSerial();
|
||||
ExecutionSerial pendingCommandSerial = mDevice->GetPendingCommandSerial();
|
||||
for (size_t i = 0; i < heapCount; i++) {
|
||||
Heap* heap = heaps[i];
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#define DAWNNATIVE_D3D12_RESIDENCYMANAGERD3D12_H_
|
||||
|
||||
#include "common/LinkedList.h"
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/D3D12Backend.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return DAWN_OUT_OF_MEMORY_ERROR("Allocation failed");
|
||||
}
|
||||
|
||||
void ResourceAllocatorManager::Tick(Serial completedSerial) {
|
||||
void ResourceAllocatorManager::Tick(ExecutionSerial completedSerial) {
|
||||
for (ResourceHeapAllocation& allocation :
|
||||
mAllocationsToDelete.IterateUpTo(completedSerial)) {
|
||||
if (allocation.GetInfo().mMethod == AllocationMethod::kSubAllocated) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "common/SerialQueue.h"
|
||||
#include "dawn_native/BuddyMemoryAllocator.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/PooledResourceMemoryAllocator.h"
|
||||
#include "dawn_native/d3d12/HeapAllocatorD3D12.h"
|
||||
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
||||
|
@ -66,7 +67,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
void DeallocateMemory(ResourceHeapAllocation& allocation);
|
||||
|
||||
void Tick(Serial lastCompletedSerial);
|
||||
void Tick(ExecutionSerial lastCompletedSerial);
|
||||
|
||||
void DestroyPool();
|
||||
|
||||
|
@ -98,7 +99,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
std::array<std::unique_ptr<PooledResourceMemoryAllocator>, ResourceHeapKind::EnumCount>
|
||||
mPooledHeapAllocators;
|
||||
|
||||
SerialQueue<Serial, ResourceHeapAllocation> mAllocationsToDelete;
|
||||
SerialQueue<ExecutionSerial, ResourceHeapAllocation> mAllocationsToDelete;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
bool ShaderVisibleDescriptorAllocator::AllocateGPUDescriptors(
|
||||
uint32_t descriptorCount,
|
||||
Serial pendingSerial,
|
||||
ExecutionSerial pendingSerial,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* baseCPUDescriptor,
|
||||
GPUDescriptorHeapAllocation* allocation) {
|
||||
ASSERT(mHeap != nullptr);
|
||||
|
@ -128,7 +128,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mHeap->GetD3D12DescriptorHeap();
|
||||
}
|
||||
|
||||
void ShaderVisibleDescriptorAllocator::Tick(uint64_t completedSerial) {
|
||||
void ShaderVisibleDescriptorAllocator::Tick(ExecutionSerial completedSerial) {
|
||||
mAllocator.Deallocate(completedSerial);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,11 +55,11 @@ namespace dawn_native { namespace d3d12 {
|
|||
// Returns true if the allocation was successful, when false is returned the current heap is
|
||||
// full and AllocateAndSwitchShaderVisibleHeap() must be called.
|
||||
bool AllocateGPUDescriptors(uint32_t descriptorCount,
|
||||
Serial pendingSerial,
|
||||
ExecutionSerial pendingSerial,
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE* baseCPUDescriptor,
|
||||
GPUDescriptorHeapAllocation* allocation);
|
||||
|
||||
void Tick(uint64_t completedSerial);
|
||||
void Tick(ExecutionSerial completedSerial);
|
||||
|
||||
ID3D12DescriptorHeap* GetShaderVisibleHeap() const;
|
||||
MaybeError AllocateAndSwitchShaderVisibleHeap();
|
||||
|
@ -75,7 +75,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
private:
|
||||
struct SerialDescriptorHeap {
|
||||
Serial heapSerial;
|
||||
ExecutionSerial heapSerial;
|
||||
std::unique_ptr<ShaderVisibleDescriptorHeap> heap;
|
||||
};
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
return allocation;
|
||||
}
|
||||
|
||||
void StagingDescriptorAllocator::Tick(Serial completedSerial) {
|
||||
void StagingDescriptorAllocator::Tick(ExecutionSerial completedSerial) {
|
||||
for (CPUDescriptorHeapAllocation& allocation :
|
||||
mAllocationsToDelete.IterateUpTo(completedSerial)) {
|
||||
Deallocate(&allocation);
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
uint32_t GetSizeIncrement() const;
|
||||
|
||||
void Tick(Serial completedSerial);
|
||||
void Tick(ExecutionSerial completedSerial);
|
||||
|
||||
private:
|
||||
using Index = uint16_t;
|
||||
|
@ -77,7 +77,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE mHeapType;
|
||||
|
||||
SerialQueue<Serial, CPUDescriptorHeapAllocation> mAllocationsToDelete;
|
||||
SerialQueue<ExecutionSerial, CPUDescriptorHeapAllocation> mAllocationsToDelete;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
|
|
@ -489,7 +489,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
: TextureBase(device, descriptor, state),
|
||||
mSubresourceStateAndDecay(
|
||||
GetSubresourceCount(),
|
||||
{D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON, UINT64_MAX, false}) {
|
||||
{D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON, kMaxExecutionSerial, false}) {
|
||||
}
|
||||
|
||||
Texture::Texture(Device* device,
|
||||
|
@ -607,7 +607,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
void Texture::TransitionSingleOrAllSubresources(std::vector<D3D12_RESOURCE_BARRIER>* barriers,
|
||||
uint32_t index,
|
||||
D3D12_RESOURCE_STATES newState,
|
||||
const Serial pendingCommandSerial,
|
||||
ExecutionSerial pendingCommandSerial,
|
||||
bool allSubresources) {
|
||||
StateAndDecay* state = &mSubresourceStateAndDecay[index];
|
||||
// Reuse the subresource(s) directly and avoid transition when it isn't needed, and
|
||||
|
@ -702,7 +702,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
const SubresourceRange& range) {
|
||||
HandleTransitionSpecialCases(commandContext);
|
||||
|
||||
const Serial pendingCommandSerial = ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
const ExecutionSerial pendingCommandSerial =
|
||||
ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
|
||||
// This transitions assume it is a 2D texture
|
||||
ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
|
||||
|
@ -751,7 +752,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
HandleTransitionSpecialCases(commandContext);
|
||||
|
||||
const Serial pendingCommandSerial = ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
const ExecutionSerial pendingCommandSerial =
|
||||
ToBackend(GetDevice())->GetPendingCommandSerial();
|
||||
uint32_t subresourceCount = GetSubresourceCount();
|
||||
ASSERT(textureUsages.subresourceUsages.size() == subresourceCount);
|
||||
// This transitions assume it is a 2D texture
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#ifndef DAWNNATIVE_D3D12_TEXTURED3D12_H_
|
||||
#define DAWNNATIVE_D3D12_TEXTURED3D12_H_
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
|
||||
#include "dawn_native/DawnNative.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/PassResourceUsage.h"
|
||||
#include "dawn_native/d3d12/IntegerTypes.h"
|
||||
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
||||
|
@ -103,7 +103,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
void TransitionSingleOrAllSubresources(std::vector<D3D12_RESOURCE_BARRIER>* barriers,
|
||||
uint32_t index,
|
||||
D3D12_RESOURCE_STATES subresourceNewState,
|
||||
const Serial pendingCommandSerial,
|
||||
ExecutionSerial pendingCommandSerial,
|
||||
bool allSubresources);
|
||||
void HandleTransitionSpecialCases(CommandRecordingContext* commandContext);
|
||||
|
||||
|
@ -111,7 +111,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
struct StateAndDecay {
|
||||
D3D12_RESOURCE_STATES lastState;
|
||||
Serial lastDecaySerial;
|
||||
ExecutionSerial lastDecaySerial;
|
||||
bool isValidToDecay;
|
||||
};
|
||||
std::vector<StateAndDecay> mSubresourceStateAndDecay;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/metal/CommandRecordingContext.h"
|
||||
|
@ -107,7 +106,7 @@ namespace dawn_native { namespace metal {
|
|||
void InitTogglesFromDriver();
|
||||
void ShutDownImpl() override;
|
||||
MaybeError WaitForIdleForDestruction() override;
|
||||
Serial CheckAndUpdateCompletedSerials() override;
|
||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
id<MTLDevice> mMtlDevice = nil;
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
|
|
|
@ -174,16 +174,16 @@ namespace dawn_native { namespace metal {
|
|||
return new TextureView(texture, descriptor);
|
||||
}
|
||||
|
||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||
if (GetCompletedCommandSerial() > mCompletedSerial) {
|
||||
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
|
||||
uint64_t frontendCompletedSerial{GetCompletedCommandSerial()};
|
||||
if (frontendCompletedSerial > mCompletedSerial) {
|
||||
// sometimes we increase the serials, in which case the completed serial in
|
||||
// the device base will surpass the completed serial we have in the metal backend, so we
|
||||
// must update ours when we see that the completed serial from device base has
|
||||
// increased.
|
||||
mCompletedSerial = GetCompletedCommandSerial();
|
||||
mCompletedSerial = frontendCompletedSerial;
|
||||
}
|
||||
static_assert(std::is_same<Serial, uint64_t>::value, "");
|
||||
return mCompletedSerial.load();
|
||||
return ExecutionSerial(mCompletedSerial.load());
|
||||
}
|
||||
|
||||
MaybeError Device::TickImpl() {
|
||||
|
@ -241,17 +241,17 @@ namespace dawn_native { namespace metal {
|
|||
|
||||
// Update the completed serial once the completed handler is fired. Make a local copy of
|
||||
// mLastSubmittedSerial so it is captured by value.
|
||||
Serial pendingSerial = GetLastSubmittedCommandSerial();
|
||||
ExecutionSerial pendingSerial = GetLastSubmittedCommandSerial();
|
||||
// this ObjC block runs on a different thread
|
||||
[pendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
||||
TRACE_EVENT_ASYNC_END0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
||||
pendingSerial);
|
||||
ASSERT(pendingSerial > mCompletedSerial.load());
|
||||
this->mCompletedSerial = pendingSerial;
|
||||
uint64_t(pendingSerial));
|
||||
ASSERT(uint64_t(pendingSerial) > mCompletedSerial.load());
|
||||
this->mCompletedSerial = uint64_t(pendingSerial);
|
||||
}];
|
||||
|
||||
TRACE_EVENT_ASYNC_BEGIN0(GetPlatform(), GPUWork, "DeviceMTL::SubmitPendingCommandBuffer",
|
||||
pendingSerial);
|
||||
uint64_t(pendingSerial));
|
||||
[pendingCommands commit];
|
||||
[pendingCommands release];
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace dawn_native { namespace null {
|
|||
return {};
|
||||
}
|
||||
|
||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
|
||||
return GetLastSubmittedCommandSerial();
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace dawn_native { namespace null {
|
|||
TextureBase* texture,
|
||||
const TextureViewDescriptor* descriptor) override;
|
||||
|
||||
Serial CheckAndUpdateCompletedSerials() override;
|
||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
void ShutDownImpl() override;
|
||||
MaybeError WaitForIdleForDestruction() override;
|
||||
|
|
|
@ -160,11 +160,11 @@ namespace dawn_native { namespace opengl {
|
|||
return {};
|
||||
}
|
||||
|
||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||
Serial fenceSerial = 0;
|
||||
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
|
||||
ExecutionSerial fenceSerial{0};
|
||||
while (!mFencesInFlight.empty()) {
|
||||
GLsync sync = mFencesInFlight.front().first;
|
||||
Serial tentativeSerial = mFencesInFlight.front().second;
|
||||
ExecutionSerial tentativeSerial = mFencesInFlight.front().second;
|
||||
|
||||
// Fence are added in order, so we can stop searching as soon
|
||||
// as we see one that's not ready.
|
||||
|
|
|
@ -105,11 +105,11 @@ namespace dawn_native { namespace opengl {
|
|||
const TextureViewDescriptor* descriptor) override;
|
||||
|
||||
void InitTogglesFromDriver();
|
||||
Serial CheckAndUpdateCompletedSerials() override;
|
||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||
void ShutDownImpl() override;
|
||||
MaybeError WaitForIdleForDestruction() override;
|
||||
|
||||
std::queue<std::pair<GLsync, Serial>> mFencesInFlight;
|
||||
std::queue<std::pair<GLsync, ExecutionSerial>> mFencesInFlight;
|
||||
|
||||
GLFormatTable mFormatTable;
|
||||
};
|
||||
|
|
|
@ -174,7 +174,7 @@ namespace dawn_native { namespace vulkan {
|
|||
mBindGroupAllocator.Deallocate(bindGroup);
|
||||
}
|
||||
|
||||
void BindGroupLayout::FinishDeallocation(Serial completedSerial) {
|
||||
void BindGroupLayout::FinishDeallocation(ExecutionSerial completedSerial) {
|
||||
mDescriptorSetAllocator->FinishDeallocation(completedSerial);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "dawn_native/BindGroupLayout.h"
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "common/SlabAllocator.h"
|
||||
#include "common/vulkan_platform.h"
|
||||
|
||||
|
@ -57,7 +56,7 @@ namespace dawn_native { namespace vulkan {
|
|||
const BindGroupDescriptor* descriptor);
|
||||
void DeallocateBindGroup(BindGroup* bindGroup,
|
||||
DescriptorSetAllocation* descriptorSetAllocation);
|
||||
void FinishDeallocation(Serial completedSerial);
|
||||
void FinishDeallocation(ExecutionSerial completedSerial);
|
||||
|
||||
private:
|
||||
~BindGroupLayout() override;
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace dawn_native { namespace vulkan {
|
|||
// documentation for vkCmdBindDescriptorSets that the set may be consumed any time between
|
||||
// host execution of the command and the end of the draw/dispatch.
|
||||
Device* device = ToBackend(mLayout->GetDevice());
|
||||
const Serial serial = device->GetPendingCommandSerial();
|
||||
const ExecutionSerial serial = device->GetPendingCommandSerial();
|
||||
mPendingDeallocations.Enqueue({allocationInfo->poolIndex, allocationInfo->setIndex},
|
||||
serial);
|
||||
|
||||
|
@ -115,7 +115,7 @@ namespace dawn_native { namespace vulkan {
|
|||
*allocationInfo = {};
|
||||
}
|
||||
|
||||
void DescriptorSetAllocator::FinishDeallocation(Serial completedSerial) {
|
||||
void DescriptorSetAllocator::FinishDeallocation(ExecutionSerial completedSerial) {
|
||||
for (const Deallocation& dealloc : mPendingDeallocations.IterateUpTo(completedSerial)) {
|
||||
ASSERT(dealloc.poolIndex < mDescriptorPools.size());
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "common/SerialQueue.h"
|
||||
#include "common/vulkan_platform.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/vulkan/DescriptorSetAllocation.h"
|
||||
|
||||
#include <map>
|
||||
|
@ -38,7 +39,7 @@ namespace dawn_native { namespace vulkan {
|
|||
|
||||
ResultOrError<DescriptorSetAllocation> Allocate();
|
||||
void Deallocate(DescriptorSetAllocation* allocationInfo);
|
||||
void FinishDeallocation(Serial completedSerial);
|
||||
void FinishDeallocation(ExecutionSerial completedSerial);
|
||||
|
||||
private:
|
||||
MaybeError AllocateDescriptorPool();
|
||||
|
@ -61,8 +62,8 @@ namespace dawn_native { namespace vulkan {
|
|||
PoolIndex poolIndex;
|
||||
SetIndex setIndex;
|
||||
};
|
||||
SerialQueue<Serial, Deallocation> mPendingDeallocations;
|
||||
Serial mLastDeallocationSerial = 0;
|
||||
SerialQueue<ExecutionSerial, Deallocation> mPendingDeallocations;
|
||||
ExecutionSerial mLastDeallocationSerial = ExecutionSerial(0);
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::vulkan
|
||||
|
|
|
@ -161,7 +161,7 @@ namespace dawn_native { namespace vulkan {
|
|||
MaybeError Device::TickImpl() {
|
||||
RecycleCompletedCommands();
|
||||
|
||||
Serial completedSerial = GetCompletedCommandSerial();
|
||||
ExecutionSerial completedSerial = GetCompletedCommandSerial();
|
||||
|
||||
for (Ref<BindGroupLayout>& bgl :
|
||||
mBindGroupLayoutsPendingDeallocation.IterateUpTo(completedSerial)) {
|
||||
|
@ -254,7 +254,7 @@ namespace dawn_native { namespace vulkan {
|
|||
}
|
||||
|
||||
IncrementLastSubmittedCommandSerial();
|
||||
Serial lastSubmittedSerial = GetLastSubmittedCommandSerial();
|
||||
ExecutionSerial lastSubmittedSerial = GetLastSubmittedCommandSerial();
|
||||
mFencesInFlight.emplace(fence, lastSubmittedSerial);
|
||||
|
||||
CommandPoolAndBuffer submittedCommands = {mRecordingContext.commandPool,
|
||||
|
@ -498,11 +498,11 @@ namespace dawn_native { namespace vulkan {
|
|||
return fence;
|
||||
}
|
||||
|
||||
Serial Device::CheckAndUpdateCompletedSerials() {
|
||||
Serial fenceSerial = 0;
|
||||
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
|
||||
ExecutionSerial fenceSerial(0);
|
||||
while (!mFencesInFlight.empty()) {
|
||||
VkFence fence = mFencesInFlight.front().first;
|
||||
Serial tentativeSerial = mFencesInFlight.front().second;
|
||||
ExecutionSerial tentativeSerial = mFencesInFlight.front().second;
|
||||
VkResult result = VkResult::WrapUnsafe(
|
||||
INJECT_ERROR_OR_RUN(fn.GetFenceStatus(mVkDevice, fence), VK_ERROR_DEVICE_LOST));
|
||||
// TODO: Handle DeviceLost error.
|
||||
|
@ -824,7 +824,7 @@ namespace dawn_native { namespace vulkan {
|
|||
// Make sure all fences are complete by explicitly waiting on them all
|
||||
while (!mFencesInFlight.empty()) {
|
||||
VkFence fence = mFencesInFlight.front().first;
|
||||
Serial fenceSerial = mFencesInFlight.front().second;
|
||||
ExecutionSerial fenceSerial = mFencesInFlight.front().second;
|
||||
ASSERT(fenceSerial > GetCompletedCommandSerial());
|
||||
|
||||
VkResult result = VkResult::WrapUnsafe(VK_TIMEOUT);
|
||||
|
@ -919,7 +919,7 @@ namespace dawn_native { namespace vulkan {
|
|||
// force all operations to look as if they were completed, and delete all objects before
|
||||
// destroying the Deleter and vkDevice.
|
||||
ASSERT(mDeleter != nullptr);
|
||||
mDeleter->Tick(std::numeric_limits<Serial>::max());
|
||||
mDeleter->Tick(kMaxExecutionSerial);
|
||||
mDeleter = nullptr;
|
||||
|
||||
// VkQueues are destroyed when the VkDevice is destroyed
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
#include "common/Serial.h"
|
||||
#include "common/SerialQueue.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/Device.h"
|
||||
|
@ -161,7 +160,7 @@ namespace dawn_native { namespace vulkan {
|
|||
VkQueue mQueue = VK_NULL_HANDLE;
|
||||
uint32_t mComputeSubgroupSize = 0;
|
||||
|
||||
SerialQueue<Serial, Ref<BindGroupLayout>> mBindGroupLayoutsPendingDeallocation;
|
||||
SerialQueue<ExecutionSerial, Ref<BindGroupLayout>> mBindGroupLayoutsPendingDeallocation;
|
||||
std::unique_ptr<FencedDeleter> mDeleter;
|
||||
std::unique_ptr<ResourceMemoryAllocator> mResourceMemoryAllocator;
|
||||
std::unique_ptr<RenderPassCache> mRenderPassCache;
|
||||
|
@ -170,13 +169,13 @@ namespace dawn_native { namespace vulkan {
|
|||
std::unique_ptr<external_semaphore::Service> mExternalSemaphoreService;
|
||||
|
||||
ResultOrError<VkFence> GetUnusedFence();
|
||||
Serial CheckAndUpdateCompletedSerials() override;
|
||||
ExecutionSerial CheckAndUpdateCompletedSerials() override;
|
||||
|
||||
// We track which operations are in flight on the GPU with an increasing serial.
|
||||
// This works only because we have a single queue. Each submit to a queue is associated
|
||||
// to a serial and a fence, such that when the fence is "ready" we know the operations
|
||||
// have finished.
|
||||
std::queue<std::pair<VkFence, Serial>> mFencesInFlight;
|
||||
std::queue<std::pair<VkFence, ExecutionSerial>> mFencesInFlight;
|
||||
// Fences in the unused list aren't reset yet.
|
||||
std::vector<VkFence> mUnusedFences;
|
||||
|
||||
|
@ -187,7 +186,7 @@ namespace dawn_native { namespace vulkan {
|
|||
VkCommandPool pool = VK_NULL_HANDLE;
|
||||
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
||||
};
|
||||
SerialQueue<Serial, CommandPoolAndBuffer> mCommandsInFlight;
|
||||
SerialQueue<ExecutionSerial, CommandPoolAndBuffer> mCommandsInFlight;
|
||||
// Command pools in the unused list haven't been reset yet.
|
||||
std::vector<CommandPoolAndBuffer> mUnusedCommands;
|
||||
// There is always a valid recording context stored in mRecordingContext
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace dawn_native { namespace vulkan {
|
|||
mSwapChainsToDelete.Enqueue(swapChain, mDevice->GetPendingCommandSerial());
|
||||
}
|
||||
|
||||
void FencedDeleter::Tick(Serial completedSerial) {
|
||||
void FencedDeleter::Tick(ExecutionSerial completedSerial) {
|
||||
VkDevice vkDevice = mDevice->GetVkDevice();
|
||||
VkInstance instance = mDevice->GetVkInstance();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "common/SerialQueue.h"
|
||||
#include "common/vulkan_platform.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
|
||||
namespace dawn_native { namespace vulkan {
|
||||
|
||||
|
@ -43,25 +44,25 @@ namespace dawn_native { namespace vulkan {
|
|||
void DeleteWhenUnused(VkSurfaceKHR surface);
|
||||
void DeleteWhenUnused(VkSwapchainKHR swapChain);
|
||||
|
||||
void Tick(Serial completedSerial);
|
||||
void Tick(ExecutionSerial completedSerial);
|
||||
|
||||
private:
|
||||
Device* mDevice = nullptr;
|
||||
SerialQueue<Serial, VkBuffer> mBuffersToDelete;
|
||||
SerialQueue<Serial, VkDescriptorPool> mDescriptorPoolsToDelete;
|
||||
SerialQueue<Serial, VkDeviceMemory> mMemoriesToDelete;
|
||||
SerialQueue<Serial, VkFramebuffer> mFramebuffersToDelete;
|
||||
SerialQueue<Serial, VkImage> mImagesToDelete;
|
||||
SerialQueue<Serial, VkImageView> mImageViewsToDelete;
|
||||
SerialQueue<Serial, VkPipeline> mPipelinesToDelete;
|
||||
SerialQueue<Serial, VkPipelineLayout> mPipelineLayoutsToDelete;
|
||||
SerialQueue<Serial, VkQueryPool> mQueryPoolsToDelete;
|
||||
SerialQueue<Serial, VkRenderPass> mRenderPassesToDelete;
|
||||
SerialQueue<Serial, VkSampler> mSamplersToDelete;
|
||||
SerialQueue<Serial, VkSemaphore> mSemaphoresToDelete;
|
||||
SerialQueue<Serial, VkShaderModule> mShaderModulesToDelete;
|
||||
SerialQueue<Serial, VkSurfaceKHR> mSurfacesToDelete;
|
||||
SerialQueue<Serial, VkSwapchainKHR> mSwapChainsToDelete;
|
||||
SerialQueue<ExecutionSerial, VkBuffer> mBuffersToDelete;
|
||||
SerialQueue<ExecutionSerial, VkDescriptorPool> mDescriptorPoolsToDelete;
|
||||
SerialQueue<ExecutionSerial, VkDeviceMemory> mMemoriesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkFramebuffer> mFramebuffersToDelete;
|
||||
SerialQueue<ExecutionSerial, VkImage> mImagesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkImageView> mImageViewsToDelete;
|
||||
SerialQueue<ExecutionSerial, VkPipeline> mPipelinesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkPipelineLayout> mPipelineLayoutsToDelete;
|
||||
SerialQueue<ExecutionSerial, VkQueryPool> mQueryPoolsToDelete;
|
||||
SerialQueue<ExecutionSerial, VkRenderPass> mRenderPassesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkSampler> mSamplersToDelete;
|
||||
SerialQueue<ExecutionSerial, VkSemaphore> mSemaphoresToDelete;
|
||||
SerialQueue<ExecutionSerial, VkShaderModule> mShaderModulesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkSurfaceKHR> mSurfacesToDelete;
|
||||
SerialQueue<ExecutionSerial, VkSwapchainKHR> mSwapChainsToDelete;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::vulkan
|
||||
|
|
|
@ -198,7 +198,7 @@ namespace dawn_native { namespace vulkan {
|
|||
allocation->Invalidate();
|
||||
}
|
||||
|
||||
void ResourceMemoryAllocator::Tick(Serial completedSerial) {
|
||||
void ResourceMemoryAllocator::Tick(ExecutionSerial completedSerial) {
|
||||
for (const ResourceMemoryAllocation& allocation :
|
||||
mSubAllocationsToDelete.IterateUpTo(completedSerial)) {
|
||||
ASSERT(allocation.GetInfo().mMethod == AllocationMethod::kSubAllocated);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "common/SerialQueue.h"
|
||||
#include "common/vulkan_platform.h"
|
||||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/IntegerTypes.h"
|
||||
#include "dawn_native/PooledResourceMemoryAllocator.h"
|
||||
#include "dawn_native/ResourceMemoryAllocation.h"
|
||||
|
||||
|
@ -39,7 +40,7 @@ namespace dawn_native { namespace vulkan {
|
|||
|
||||
void DestroyPool();
|
||||
|
||||
void Tick(Serial completedSerial);
|
||||
void Tick(ExecutionSerial completedSerial);
|
||||
|
||||
int FindBestTypeIndex(VkMemoryRequirements requirements, bool mappable);
|
||||
|
||||
|
@ -49,7 +50,7 @@ namespace dawn_native { namespace vulkan {
|
|||
class SingleTypeAllocator;
|
||||
std::vector<std::unique_ptr<SingleTypeAllocator>> mAllocatorsPerType;
|
||||
|
||||
SerialQueue<Serial, ResourceMemoryAllocation> mSubAllocationsToDelete;
|
||||
SerialQueue<ExecutionSerial, ResourceMemoryAllocation> mSubAllocationsToDelete;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::vulkan
|
||||
|
|
|
@ -31,14 +31,15 @@ TEST(RingBufferAllocatorTests, BasicTest) {
|
|||
ASSERT_EQ(allocator.GetSize(), sizeInBytes);
|
||||
|
||||
// Ensure failure upon sub-allocating an oversized request.
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes + 1, 0), RingBufferAllocator::kInvalidOffset);
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes + 1, ExecutionSerial(0)),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
|
||||
// Fill the entire buffer with two requests of equal size.
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes / 2, 1), 0u);
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes / 2, 2), 32000u);
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes / 2, ExecutionSerial(1)), 0u);
|
||||
ASSERT_EQ(allocator.Allocate(sizeInBytes / 2, ExecutionSerial(2)), 32000u);
|
||||
|
||||
// Ensure the buffer is full.
|
||||
ASSERT_EQ(allocator.Allocate(1, 3), RingBufferAllocator::kInvalidOffset);
|
||||
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(3)), RingBufferAllocator::kInvalidOffset);
|
||||
}
|
||||
|
||||
// Tests that several ringbuffer allocations do not fail.
|
||||
|
@ -49,9 +50,9 @@ TEST(RingBufferAllocatorTests, RingBufferManyAlloc) {
|
|||
RingBufferAllocator allocator(maxNumOfFrames * frameSizeInBytes);
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < maxNumOfFrames; ++i) {
|
||||
for (ExecutionSerial i(0); i < ExecutionSerial(maxNumOfFrames); ++i) {
|
||||
offset = allocator.Allocate(frameSizeInBytes, i);
|
||||
ASSERT_EQ(offset, i * frameSizeInBytes);
|
||||
ASSERT_EQ(offset, uint64_t(i) * frameSizeInBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,22 +65,22 @@ TEST(RingBufferAllocatorTests, AllocInSameFrame) {
|
|||
|
||||
// F1
|
||||
// [xxxx|--------]
|
||||
size_t offset = allocator.Allocate(frameSizeInBytes, 1);
|
||||
size_t offset = allocator.Allocate(frameSizeInBytes, ExecutionSerial(1));
|
||||
|
||||
// F1 F2
|
||||
// [xxxx|xxxx|----]
|
||||
|
||||
offset = allocator.Allocate(frameSizeInBytes, 2);
|
||||
offset = allocator.Allocate(frameSizeInBytes, ExecutionSerial(2));
|
||||
|
||||
// F1 F2
|
||||
// [xxxx|xxxxxxxx]
|
||||
|
||||
offset = allocator.Allocate(frameSizeInBytes, 2);
|
||||
offset = allocator.Allocate(frameSizeInBytes, ExecutionSerial(2));
|
||||
|
||||
ASSERT_EQ(offset, 8u);
|
||||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * 3);
|
||||
|
||||
allocator.Deallocate(2);
|
||||
allocator.Deallocate(ExecutionSerial(2));
|
||||
|
||||
ASSERT_EQ(allocator.GetUsedSize(), 0u);
|
||||
EXPECT_TRUE(allocator.Empty());
|
||||
|
@ -93,10 +94,10 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
RingBufferAllocator allocator(maxNumOfFrames * frameSizeInBytes);
|
||||
|
||||
// Sub-alloc the first eight frames.
|
||||
Serial serial = 1;
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
ExecutionSerial serial(0);
|
||||
while (serial < ExecutionSerial(8)) {
|
||||
allocator.Allocate(frameSizeInBytes, serial);
|
||||
serial += 1;
|
||||
serial++;
|
||||
}
|
||||
|
||||
// Each frame corrresponds to the serial number (for simplicity).
|
||||
|
@ -106,12 +107,12 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
//
|
||||
|
||||
// Ensure an oversized allocation fails (only 8 bytes left)
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes * 3, serial + 1),
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes * 3, serial),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * 8);
|
||||
|
||||
// Reclaim the first 3 frames.
|
||||
allocator.Deallocate(3);
|
||||
allocator.Deallocate(ExecutionSerial(2));
|
||||
|
||||
// F4 F5 F6 F7 F8
|
||||
// [------------|xxxx|xxxx|xxxx|xxxx|xxxx|--------]
|
||||
|
@ -119,7 +120,7 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * 5);
|
||||
|
||||
// Re-try the over-sized allocation.
|
||||
size_t offset = allocator.Allocate(frameSizeInBytes * 3, serial);
|
||||
size_t offset = allocator.Allocate(frameSizeInBytes * 3, ExecutionSerial(serial));
|
||||
|
||||
// F9 F4 F5 F6 F7 F8
|
||||
// [xxxxxxxxxxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxxxxxx]
|
||||
|
@ -133,11 +134,10 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * maxNumOfFrames);
|
||||
|
||||
// Ensure we are full.
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial + 1),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial), RingBufferAllocator::kInvalidOffset);
|
||||
|
||||
// Reclaim the next two frames.
|
||||
allocator.Deallocate(5);
|
||||
allocator.Deallocate(ExecutionSerial(4));
|
||||
|
||||
// F9 F4 F5 F6 F7 F8
|
||||
// [xxxxxxxxxxxx|----|----|xxxx|xxxx|xxxx|xxxxxxxx]
|
||||
|
@ -145,7 +145,7 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
ASSERT_EQ(allocator.GetUsedSize(), frameSizeInBytes * 8);
|
||||
|
||||
// Sub-alloc the chunk in the middle.
|
||||
serial += 1;
|
||||
serial++;
|
||||
offset = allocator.Allocate(frameSizeInBytes * 2, serial);
|
||||
|
||||
ASSERT_EQ(offset, frameSizeInBytes * 3);
|
||||
|
@ -156,22 +156,19 @@ TEST(RingBufferAllocatorTests, RingBufferSubAlloc) {
|
|||
//
|
||||
|
||||
// Ensure we are full.
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial + 1),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
ASSERT_EQ(allocator.Allocate(frameSizeInBytes, serial), RingBufferAllocator::kInvalidOffset);
|
||||
|
||||
// Reclaim all.
|
||||
allocator.Deallocate(maxNumOfFrames);
|
||||
allocator.Deallocate(kMaxExecutionSerial);
|
||||
|
||||
EXPECT_TRUE(allocator.Empty());
|
||||
}
|
||||
|
||||
// Checks if ringbuffer sub-allocation does not overflow.
|
||||
TEST(RingBufferAllocatorTests, RingBufferOverflow) {
|
||||
Serial serial = 1;
|
||||
|
||||
RingBufferAllocator allocator(std::numeric_limits<uint64_t>::max());
|
||||
|
||||
ASSERT_EQ(allocator.Allocate(1, serial), 0u);
|
||||
ASSERT_EQ(allocator.Allocate(std::numeric_limits<uint64_t>::max(), serial + 1),
|
||||
ASSERT_EQ(allocator.Allocate(1, ExecutionSerial(1)), 0u);
|
||||
ASSERT_EQ(allocator.Allocate(std::numeric_limits<uint64_t>::max(), ExecutionSerial(1)),
|
||||
RingBufferAllocator::kInvalidOffset);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue