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