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:
Corentin Wallez 2020-09-28 19:35:14 +00:00 committed by Commit Bot service account
parent ad4a66ec8f
commit 62139fcca7
59 changed files with 204 additions and 217 deletions

View File

@ -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",

View File

@ -35,7 +35,6 @@ target_sources(dawn_common PRIVATE
"RefCounted.h"
"Result.cpp"
"Result.h"
"Serial.h"
"SerialMap.h"
"SerialQueue.h"
"SerialStorage.h"

View File

@ -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_

View File

@ -16,7 +16,6 @@
#define COMMON_SERIALSTORAGE_H_
#include "common/Assert.h"
#include "common/Serial.h"
#include <cstdint>
#include <utility>

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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_

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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).

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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"));

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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];

View File

@ -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"

View File

@ -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) {

View File

@ -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

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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];
}

View File

@ -219,7 +219,7 @@ namespace dawn_native { namespace null {
return {};
}
Serial Device::CheckAndUpdateCompletedSerials() {
ExecutionSerial Device::CheckAndUpdateCompletedSerials() {
return GetLastSubmittedCommandSerial();
}

View File

@ -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;

View File

@ -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.

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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;

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);
}