diff --git a/src/gpgmm/common/BUILD.gn b/src/gpgmm/common/BUILD.gn index ca84ed36..74cabcf1 100644 --- a/src/gpgmm/common/BUILD.gn +++ b/src/gpgmm/common/BUILD.gn @@ -183,6 +183,7 @@ source_set("gpgmm_common_sources") { "ConditionalMemoryAllocator.h", "DedicatedMemoryAllocator.cpp", "DedicatedMemoryAllocator.h", + "Error.cpp", "Error.h", "EventMessage.cpp", "EventMessage.h", diff --git a/src/gpgmm/common/CMakeLists.txt b/src/gpgmm/common/CMakeLists.txt index 6aad88ba..e568fab9 100644 --- a/src/gpgmm/common/CMakeLists.txt +++ b/src/gpgmm/common/CMakeLists.txt @@ -23,6 +23,7 @@ target_sources(gpgmm_common PRIVATE "ConditionalMemoryAllocator.h" "DedicatedMemoryAllocator.cpp" "DedicatedMemoryAllocator.h" + "Error.cpp" "Error.h" "EventTraceWriter.cpp" "EventTraceWriter.h" diff --git a/src/gpgmm/common/DedicatedMemoryAllocator.cpp b/src/gpgmm/common/DedicatedMemoryAllocator.cpp index f32c799b..8b663d5a 100644 --- a/src/gpgmm/common/DedicatedMemoryAllocator.cpp +++ b/src/gpgmm/common/DedicatedMemoryAllocator.cpp @@ -44,7 +44,7 @@ namespace gpgmm { GPGMM_TRY_ASSIGN(GetNextInChain()->TryAllocateMemory(memoryRequest), allocation); if (memoryRequest.SizeInBytes > request.SizeInBytes) { - DebugLog(MessageId::kAlignmentMismatch, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Memory allocation was larger then the requested: " << GetBytesToSizeInUnits(memoryRequest.SizeInBytes) << " vs " << GetBytesToSizeInUnits(request.SizeInBytes) << "."; diff --git a/src/gpgmm/common/Error.cpp b/src/gpgmm/common/Error.cpp new file mode 100644 index 00000000..404aa9be --- /dev/null +++ b/src/gpgmm/common/Error.cpp @@ -0,0 +1,47 @@ +// Copyright 2022 The GPGMM 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. + +#include "Error.h" + +#include "gpgmm/common/Error.h" + +namespace gpgmm { + + const char* GetErrorFromID(ErrorCode errorCode) { + switch (errorCode) { + case ErrorCode::kNone: + return ""; + case ErrorCode::kUnknown: + return "UNKNOWN"; + case ErrorCode::kSizeExceeded: + return "SIZE_EXCEEDED"; + case ErrorCode::kAlignmentMismatch: + return "ALIGNMENT_MISMATCH"; + case ErrorCode::kAllocatorFailed: + return "ALLOCATOR_FAILED"; + case ErrorCode::kPrefetchFailed: + return "PREFETCH_FAILED"; + case ErrorCode::kBudgetInvalid: + return "BUDGET_INVALID"; + case ErrorCode::kInvalidArgument: + return "INVALID_ARGUMENT"; + case ErrorCode::kBadOperation: + return "BAD_OPERATION"; + default: + UNREACHABLE(); + return ""; + } + } + +} // namespace gpgmm diff --git a/src/gpgmm/common/Error.h b/src/gpgmm/common/Error.h index 83a20dc5..682caf48 100644 --- a/src/gpgmm/common/Error.h +++ b/src/gpgmm/common/Error.h @@ -40,20 +40,32 @@ for (;;) \ break -#define GPGMM_RETURN_ERROR_IF(expr, msg) \ - if (GPGMM_UNLIKELY(expr)) { \ - gpgmm::DebugLog() << msg; \ - return std::move(::gpgmm::ErrorCodeType(kInternalFailureResult)); \ - } \ - for (;;) \ +#define GPGMM_RETURN_ERROR_IF(expr, msg) \ + if (GPGMM_UNLIKELY(expr)) { \ + gpgmm::DebugLog() << msg; \ + return std::move(::gpgmm::ErrorCode(kInternalFailureResult)); \ + } \ + for (;;) \ break namespace gpgmm { - enum class ErrorCodeType : uint32_t; + enum class ErrorCode : uint32_t { + kNone, + kUnknown, + kSizeExceeded, + kAlignmentMismatch, + kAllocatorFailed, + kPrefetchFailed, + kBudgetInvalid, + kInvalidArgument, + kBadOperation, + }; + + const char* GetErrorFromID(ErrorCode errorCode); - constexpr ErrorCodeType kInternalFailureResult = static_cast(-1); - constexpr ErrorCodeType kInternalSuccessResult = static_cast(0u); + constexpr ErrorCode kInternalFailureResult = static_cast(-1); + constexpr ErrorCode kInternalSuccessResult = static_cast(0u); // Wraps a backend error code with a result object. // Use Result::IsSuccess then Result::AcquireResult to use or else, use Result::GetErrorCode to @@ -90,7 +102,7 @@ namespace gpgmm { return *this; } - ErrorCodeType GetErrorCode() const { + ErrorCode GetErrorCode() const { return mErrorCode; } @@ -143,11 +155,11 @@ namespace gpgmm { }; // Result with only an error code. - using MaybeError = Result; + using MaybeError = Result; // Alias of Result + error code to avoid having to always specify error type. template - using ResultOrError = Result; + using ResultOrError = Result; } // namespace gpgmm diff --git a/src/gpgmm/common/EventMessage.cpp b/src/gpgmm/common/EventMessage.cpp index 326f77c1..880ca255 100644 --- a/src/gpgmm/common/EventMessage.cpp +++ b/src/gpgmm/common/EventMessage.cpp @@ -48,6 +48,7 @@ namespace gpgmm { EventMessage::EventMessage(const MessageSeverity& severity, MessageId messageId, + ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) @@ -55,13 +56,14 @@ namespace gpgmm { mMessageId(messageId), mIsExternal(isExternal), mName(name), - mObject(object) { + mObject(object), + mErrorCode(errorCode) { } EventMessage::~EventMessage() { const std::string description = mStream.str(); - gpgmm::Log(mSeverity, mMessageId, mIsExternal, mName, mObject) << description; + gpgmm::Log(mSeverity, mMessageId, mErrorCode, mIsExternal, mName, mObject) << description; #if defined(GPGMM_ENABLE_ASSERT_ON_WARNING) ASSERT(mSeverity < MessageSeverity::kWarning); @@ -77,28 +79,28 @@ namespace gpgmm { bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kDebug, messageId, isExternal, name, object}; + return {MessageSeverity::kDebug, messageId, ErrorCode::kNone, isExternal, name, object}; } EventMessage InfoEvent(MessageId messageId, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kInfo, messageId, isExternal, name, object}; + return {MessageSeverity::kInfo, messageId, ErrorCode::kNone, isExternal, name, object}; } EventMessage WarnEvent(MessageId messageId, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kWarning, messageId, isExternal, name, object}; + return {MessageSeverity::kWarning, messageId, ErrorCode::kNone, isExternal, name, object}; } - EventMessage ErrorEvent(MessageId messageId, + EventMessage ErrorEvent(ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kError, messageId, isExternal, name, object}; + return {MessageSeverity::kError, MessageId::kUnknown, errorCode, isExternal, name, object}; } } // namespace gpgmm diff --git a/src/gpgmm/common/EventMessage.h b/src/gpgmm/common/EventMessage.h index 99d71313..d85b943f 100644 --- a/src/gpgmm/common/EventMessage.h +++ b/src/gpgmm/common/EventMessage.h @@ -15,6 +15,7 @@ #ifndef SRC_GPGMM_COMMON_EVENTMESSAGE_H_ #define SRC_GPGMM_COMMON_EVENTMESSAGE_H_ +#include "gpgmm/common/Error.h" #include "gpgmm/common/Message.h" #include "gpgmm/common/Object.h" #include "gpgmm/common/TraceEvent.h" @@ -29,6 +30,7 @@ namespace gpgmm { public: EventMessage(const MessageSeverity& severity, MessageId messageId, + ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object); @@ -50,6 +52,7 @@ namespace gpgmm { std::string mName; const ObjectBase* mObject = nullptr; std::ostringstream mStream; + ErrorCode mErrorCode = ErrorCode::kNone; }; // Short-hands to create a EventMessage with the respective severity. @@ -68,7 +71,7 @@ namespace gpgmm { const std::string& name = "", const ObjectBase* mObject = nullptr); - EventMessage ErrorEvent(MessageId messageId = MessageId::kUnknown, + EventMessage ErrorEvent(ErrorCode errorCode = ErrorCode::kUnknown, bool isExternal = false, const std::string& name = "", const ObjectBase* mObject = nullptr); diff --git a/src/gpgmm/common/MemoryAllocator.cpp b/src/gpgmm/common/MemoryAllocator.cpp index b96cb57c..3890810b 100644 --- a/src/gpgmm/common/MemoryAllocator.cpp +++ b/src/gpgmm/common/MemoryAllocator.cpp @@ -204,7 +204,7 @@ namespace gpgmm { void MemoryAllocatorBase::CheckAndReportAllocationMisalignment( const MemoryAllocationBase& allocation) { if (allocation.GetSize() > allocation.GetRequestSize()) { - WarnLog(MessageId::kAlignmentMismatch, this) + WarnLog(MessageId::kPerformanceWarning, this) << "Memory allocation was larger then requested: " + GetBytesToSizeInUnits(allocation.GetSize()) + " vs " + GetBytesToSizeInUnits(allocation.GetRequestSize()) + "."; diff --git a/src/gpgmm/common/MemoryAllocator.h b/src/gpgmm/common/MemoryAllocator.h index e3cbe630..7bdd1e5e 100644 --- a/src/gpgmm/common/MemoryAllocator.h +++ b/src/gpgmm/common/MemoryAllocator.h @@ -231,7 +231,7 @@ namespace gpgmm { if (!result.IsSuccess()) { // NeverAllocate always fails, so suppress it. if (!neverAllocate) { - DebugLog(MessageId::kAllocatorFailed, this) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Failed to sub-allocate memory range = [" << std::to_string(block->Offset) << ", " << std::to_string(block->Offset + block->Size) << ")."; diff --git a/src/gpgmm/common/Message.cpp b/src/gpgmm/common/Message.cpp index 5c183c0c..98dc3cd4 100644 --- a/src/gpgmm/common/Message.cpp +++ b/src/gpgmm/common/Message.cpp @@ -22,30 +22,16 @@ namespace gpgmm { switch (messageId) { case MessageId::kUnknown: return "UNKNOWN"; - case MessageId::kSizeExceeded: - return "SIZE_EXCEEDED"; - case MessageId::kAlignmentMismatch: - return "ALIGNMENT_MISMATCH"; - case MessageId::kAllocatorFailed: - return "ALLOCATOR_FAILED"; - case MessageId::kPrefetchFailed: - return "PREFETCH_FAILED"; - case MessageId::kBudgetExceeded: - return "BUDGET_EXCEEDED"; case MessageId::kBudgetUpdated: return "BUDGET_UPDATED"; - case MessageId::kBudgetInvalid: - return "BUDGET_INVALID"; - case MessageId::kInvalidArgument: - return "INVALID_ARGUMENT"; - case MessageId::kBadOperation: - return "BAD_OPERATION"; case MessageId::kPerformanceWarning: return "PERFORMANCE_WARNING"; case MessageId::kMemoryUsageUpdated: return "MEMORY_USAGE_UPDATED"; case MessageId::kObjectCreated: return "OBJECT_CREATED"; + case MessageId::kBudgetExceeded: + return "BUDGET_EXCEEDED"; default: UNREACHABLE(); return ""; diff --git a/src/gpgmm/common/Message.h b/src/gpgmm/common/Message.h index 05f89be6..247d2d65 100644 --- a/src/gpgmm/common/Message.h +++ b/src/gpgmm/common/Message.h @@ -19,18 +19,11 @@ namespace gpgmm { enum class MessageId { kUnknown, - kSizeExceeded, - kAlignmentMismatch, - kAllocatorFailed, - kPrefetchFailed, - kBudgetExceeded, kBudgetUpdated, - kBudgetInvalid, - kInvalidArgument, - kBadOperation, kPerformanceWarning, kMemoryUsageUpdated, kObjectCreated, + kBudgetExceeded, }; enum class MessageSeverity { diff --git a/src/gpgmm/common/SlabMemoryAllocator.cpp b/src/gpgmm/common/SlabMemoryAllocator.cpp index ff2797c0..7fdbf321 100644 --- a/src/gpgmm/common/SlabMemoryAllocator.cpp +++ b/src/gpgmm/common/SlabMemoryAllocator.cpp @@ -148,7 +148,7 @@ namespace gpgmm { if (availableForAllocation < slabSize) { const uint64_t slabSizeUnderBudget = FindNextFreeSlabOfSize(requestSize); if (slabSizeUnderBudget == kInvalidSize) { - DebugLog(MessageId::kSizeExceeded, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Slab size exceeded available memory: " << GetBytesToSizeInUnits(slabSize) << " vs " << GetBytesToSizeInUnits(availableForAllocation) << "."; return kInvalidSize; @@ -211,7 +211,7 @@ namespace gpgmm { // Slab cannot exceed memory size. if (slabSize > mMaxSlabSize) { - DebugLog(MessageId::kSizeExceeded, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Slab allocation was disabled because the slab size exceeded the max slab size " "allowed: " << GPGMM_BYTES_TO_MB(slabSize) << " vs " << GPGMM_BYTES_TO_MB(mMaxSlabSize) @@ -298,7 +298,7 @@ namespace gpgmm { } if (prefetchedSlabAllocation != nullptr) { - DebugLog(MessageId::kPrefetchFailed, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Pre-fetching failed because the slab size did not match: " << GetBytesToSizeInUnits(slabSize) << " vs " << GetBytesToSizeInUnits(prefetchedSlabAllocation->GetSize()) @@ -477,7 +477,7 @@ namespace gpgmm { SafeDivide(mStats.PrefetchedMemoryMissesEliminated, mStats.PrefetchedMemoryMissesEliminated + mStats.PrefetchedMemoryMisses); if (currentCoverage < kPrefetchCoverageWarnMinThreshold) { - WarnEvent(MessageId::kPrefetchFailed, false, GetTypename(), this) + WarnEvent(MessageId::kPerformanceWarning, false, GetTypename(), this) << "Prefetch coverage is below threshold (%): " << currentCoverage * 100 << " vs " << kPrefetchCoverageWarnMinThreshold * 100; return false; diff --git a/src/gpgmm/d3d12/BudgetUpdateD3D12.cpp b/src/gpgmm/d3d12/BudgetUpdateD3D12.cpp index 428482d0..5d317864 100644 --- a/src/gpgmm/d3d12/BudgetUpdateD3D12.cpp +++ b/src/gpgmm/d3d12/BudgetUpdateD3D12.cpp @@ -75,7 +75,7 @@ namespace gpgmm::d3d12 { } if (FAILED(hr)) { - ErrorLog(MessageId::kBudgetInvalid, mResidencyManager) + ErrorLog(ErrorCode::kBudgetInvalid, mResidencyManager) << "Unable to update budget: " + GetDeviceErrorMessage(mResidencyManager->mDevice, hr); } diff --git a/src/gpgmm/d3d12/BufferAllocatorD3D12.cpp b/src/gpgmm/d3d12/BufferAllocatorD3D12.cpp index 3179bbe3..e2832dc8 100644 --- a/src/gpgmm/d3d12/BufferAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/BufferAllocatorD3D12.cpp @@ -73,11 +73,11 @@ namespace gpgmm::d3d12 { &resourceHeap); if (FAILED(hr)) { - return {static_cast(hr)}; + return {static_cast(hr)}; } if (info.SizeInBytes > request.SizeInBytes) { - DebugLog(MessageId::kAlignmentMismatch, false, GetTypename(), this) + DebugLog(MessageId::kPerformanceWarning, this) << "Memory allocation was larger then the requested: " << GetBytesToSizeInUnits(info.SizeInBytes) << " vs " << GetBytesToSizeInUnits(request.SizeInBytes) << "."; diff --git a/src/gpgmm/d3d12/EventMessageD3D12.h b/src/gpgmm/d3d12/EventMessageD3D12.h index 97798118..f499accd 100644 --- a/src/gpgmm/d3d12/EventMessageD3D12.h +++ b/src/gpgmm/d3d12/EventMessageD3D12.h @@ -16,30 +16,35 @@ #define SRC_GPGMM_D3D12_EVENTMESSAGED3D12_H_ #include "gpgmm/common/EventMessage.h" +#include "gpgmm/utils/Assert.h" #include "gpgmm/utils/WindowsUtils.h" namespace gpgmm::d3d12 { template - EventMessage DebugEvent(const BackendT* object, MessageId messageId = MessageId::kUnknown) { + EventMessage DebugEvent(MessageId messageId, const BackendT* object) { + ASSERT(object != nullptr); return gpgmm::DebugEvent(messageId, true, gpgmm::WCharToUTF8(object->GetDebugName()), object); } template - EventMessage InfoEvent(const BackendT* object, MessageId messageId = MessageId::kUnknown) { + EventMessage InfoEvent(MessageId messageId, const BackendT* object) { + ASSERT(object != nullptr); return gpgmm::InfoEvent(messageId, true, gpgmm::WCharToUTF8(object->GetDebugName()), object); } template - EventMessage WarnEvent(const BackendT* object, MessageId messageId = MessageId::kUnknown) { + EventMessage WarnEvent(MessageId messageId, const BackendT* object) { + ASSERT(object != nullptr); return gpgmm::WarnEvent(messageId, true, gpgmm::WCharToUTF8(object->GetDebugName()), object); } template - EventMessage ErrorEvent(const BackendT* object, MessageId messageId = MessageId::kUnknown) { + EventMessage ErrorEvent(MessageId messageId, const BackendT* object) { + ASSERT(object != nullptr); return gpgmm::ErrorEvent(messageId, true, gpgmm::WCharToUTF8(object->GetDebugName()), object); } diff --git a/src/gpgmm/d3d12/LogD3D12.h b/src/gpgmm/d3d12/LogD3D12.h index 486d8815..642b9622 100644 --- a/src/gpgmm/d3d12/LogD3D12.h +++ b/src/gpgmm/d3d12/LogD3D12.h @@ -15,6 +15,7 @@ #ifndef SRC_GPGMM_D3D12_LOGD3D12_H_ #define SRC_GPGMM_D3D12_LOGD3D12_H_ +#include "gpgmm/common/Error.h" #include "gpgmm/utils/Log.h" #include "gpgmm/utils/WindowsUtils.h" @@ -45,10 +46,10 @@ namespace gpgmm::d3d12 { } template - LogMessage ErrorLog(MessageId messageId = MessageId::kUnknown, + LogMessage ErrorLog(ErrorCode errorCode = ErrorCode::kUnknown, const BackendT* object = nullptr) { return gpgmm::ErrorLog( - messageId, true, (object != nullptr) ? gpgmm::WCharToUTF8(object->GetDebugName()) : "", + errorCode, true, (object != nullptr) ? gpgmm::WCharToUTF8(object->GetDebugName()) : "", object); } diff --git a/src/gpgmm/d3d12/ResidencyHeapD3D12.cpp b/src/gpgmm/d3d12/ResidencyHeapD3D12.cpp index c98fe044..165be299 100644 --- a/src/gpgmm/d3d12/ResidencyHeapD3D12.cpp +++ b/src/gpgmm/d3d12/ResidencyHeapD3D12.cpp @@ -143,7 +143,7 @@ namespace gpgmm::d3d12 { } if (newDescriptor.SizeInBytes == kInvalidSize) { - ErrorLog(MessageId::kInvalidArgument) << "Heap size for residency was invalid"; + ErrorLog(ErrorCode::kInvalidArgument) << "Heap size for residency was invalid"; return E_INVALIDARG; } @@ -152,7 +152,7 @@ namespace gpgmm::d3d12 { } if (newDescriptor.Alignment == kInvalidSize) { - ErrorLog(MessageId::kInvalidArgument) << "Heap alignment for residency was invalid."; + ErrorLog(ErrorCode::kInvalidArgument) << "Heap alignment for residency was invalid."; return E_INVALIDARG; } @@ -175,7 +175,7 @@ namespace gpgmm::d3d12 { // Heap created not resident requires no budget to be created. if (heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_EVICTED && (descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_IN_BUDGET)) { - ErrorLog(MessageId::kInvalidArgument, heap.get()) + ErrorLog(ErrorCode::kInvalidArgument, heap.get()) << "Creating a heap always in budget cannot be used with " "D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT."; return E_INVALIDARG; @@ -199,7 +199,7 @@ namespace gpgmm::d3d12 { } } else { if (descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_RESIDENT) { - WarnLog(MessageId::kInvalidArgument, heap.get()) + WarnLog(MessageId::kPerformanceWarning, heap.get()) << "RESIDENCY_HEAP_FLAG_CREATE_RESIDENT was specified but had no effect " "becauase residency management is not being used."; } @@ -231,13 +231,13 @@ namespace gpgmm::d3d12 { // Validate residency resource heap flags must also have a residency manager. if (isResidencyDisabled && descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_IN_BUDGET) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Creating a heap always in budget requires a residency manager to exist."; return E_INVALIDARG; } if (isResidencyDisabled && descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_RESIDENT) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Creating a heap always residency requires a residency manager to exist."; return E_INVALIDARG; } @@ -256,7 +256,7 @@ namespace gpgmm::d3d12 { DXGI_QUERY_VIDEO_MEMORY_INFO currentVideoInfo = {}; if (SUCCEEDED(residencyManager->QueryVideoMemoryInfo(descriptor.HeapSegment, ¤tVideoInfo))) { - ErrorLog(MessageId::kBudgetExceeded) + ErrorLog(ErrorCode::kSizeExceeded) << "Unable to create heap because not enough budget exists (" << GetBytesToSizeInUnits(descriptor.SizeInBytes) << " vs " << GetBytesToSizeInUnits( diff --git a/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp b/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp index 4ad60e23..6cf9e74a 100644 --- a/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp +++ b/src/gpgmm/d3d12/ResidencyManagerD3D12.cpp @@ -64,13 +64,13 @@ namespace gpgmm::d3d12 { if ((descriptor.Flags & RESIDENCY_MANAGER_FLAG_NEVER_USE_UNIFIED_MEMORY) && caps->IsAdapterUMA()) { - WarnLog(MessageId::kInvalidArgument) + WarnLog(MessageId::kUnknown) << "RESIDENCY_MANAGER_FLAG_NEVER_USE_UNIFIED_MEMORY flag was specified but " "did not match the architecture of the adapter."; } if (descriptor.MaxPctOfVideoMemoryToBudget != 0 && descriptor.MaxBudgetInBytes != 0) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Both the OS based memory budget and restricted budget were " "specified but cannot be used at the same time."; return E_UNEXPECTED; @@ -121,13 +121,13 @@ namespace gpgmm::d3d12 { // Emit a warning if the budget was initialized to zero. // This means nothing will be ever evicted, which will lead to device lost. if (localVideoMemorySegmentInfo->Budget == 0) { - WarnLog(MessageId::kBudgetInvalid, residencyManager.get()) + WarnLog(MessageId::kBudgetUpdated, residencyManager.get()) << "GPU memory segment (" << GetMemorySegmentName(DXGI_MEMORY_SEGMENT_GROUP_LOCAL, residencyManager->mIsUMA) << ") did not initialize a budget. This means either a restricted budget was not " "used or the first OS budget update hasn't occured."; if (!residencyManager->mIsUMA && nonLocalVideoMemorySegmentInfo->Budget == 0) { - WarnLog(MessageId::kBudgetInvalid, residencyManager.get()) + WarnLog(MessageId::kBudgetUpdated, residencyManager.get()) << "GPU memory segment (" << GetMemorySegmentName(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, residencyManager->mIsUMA) @@ -245,7 +245,7 @@ namespace gpgmm::d3d12 { } if (heap->IsInList()) { - ErrorLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "Heap was never being tracked for residency. This usually occurs when a " "non-resource heap was created by the developer and never made resident at " "creation or failure to call LockHeap beforehand."; @@ -418,7 +418,7 @@ namespace gpgmm::d3d12 { // Ignore when no budget was specified. if (pVideoMemoryInfo->Budget > 0 && pVideoMemoryInfo->CurrentUsage > pVideoMemoryInfo->Budget) { - WarnEvent(this, MessageId::kBudgetExceeded) + WarnEvent(MessageId::kBudgetExceeded, this) << GetMemorySegmentName(heapSegment, mIsUMA) << " GPU memory usage exceeds budget: " << GetBytesToSizeInUnits(pVideoMemoryInfo->CurrentUsage) << " vs " << GetBytesToSizeInUnits(pVideoMemoryInfo->Budget) << "."; @@ -427,7 +427,7 @@ namespace gpgmm::d3d12 { SafeDivide(pVideoMemoryInfo->CurrentUsage, pVideoMemoryInfo->Budget); if (pVideoMemoryInfo->Budget > 0 && currentUsageOfBudget > kMinCurrentUsageOfBudgetReportingThreshold) { - EventMessage message = WarnEvent(this, MessageId::kBudgetExceeded); + EventMessage message = WarnEvent(MessageId::kBudgetExceeded, this); message << GetMemorySegmentName(heapSegment, mIsUMA) << " GPU memory usage is above budget threshold: " << uint64_t(currentUsageOfBudget * 100) << "% vs " @@ -506,7 +506,7 @@ namespace gpgmm::d3d12 { // If a budget wasn't provided, it not possible to evict. This is because either the budget // update event has not happened yet or was invalid. if (pVideoMemoryInfo->Budget == 0) { - WarnEvent(this, MessageId::kBudgetInvalid) + WarnEvent(MessageId::kBudgetExceeded, this) << "GPU memory segment (" << GetMemorySegmentName(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, IsUMA()) << ") was unable to evict memory because a budget was not specified."; @@ -580,7 +580,7 @@ namespace gpgmm::d3d12 { GPGMM_RETURN_IF_FAILED(mDevice->Evict(objectEvictCount, objectsToEvict.data()), mDevice); - DebugEvent(this, MessageId::kBudgetExceeded) + DebugEvent(MessageId::kBudgetExceeded, this) << "GPU page-out. Number of allocations: " << objectsToEvict.size() << " (" << GetBytesToSizeInUnits(bytesEvicted) << ")."; } @@ -605,7 +605,7 @@ namespace gpgmm::d3d12 { std::lock_guard lock(mMutex); if (count == 0) { - ErrorLog(MessageId::kInvalidArgument, this) + ErrorLog(ErrorCode::kInvalidArgument, this) << "ExecuteCommandLists is required to have at-least one residency " "list to be called."; return E_INVALIDARG; @@ -613,7 +613,7 @@ namespace gpgmm::d3d12 { // TODO: support multiple command lists. if (count > 1) { - ErrorLog(MessageId::kInvalidArgument, this) + ErrorLog(ErrorCode::kInvalidArgument, this) << "ExecuteCommandLists does not support multiple residency lists at this time. " "Please call ExecuteCommandLists per residency list as a workaround, if needed."; return E_NOTIMPL; @@ -674,7 +674,7 @@ namespace gpgmm::d3d12 { // If the heap should be already resident, calling MakeResident again will be redundant. // Tell the developer the heap wasn't properly tracked by the residency manager. if (heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_UNKNOWN) { - DebugLog(MessageId::kBadOperation, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Residency state could not be determined for the heap (Heap=" << ToHexStr(heap) << "). This likely means the developer was attempting to make a " @@ -744,7 +744,7 @@ namespace gpgmm::d3d12 { GPGMM_RETURN_IF_FAILED(EvictInternal(sizeToMakeResident, heapSegment, nullptr), mDevice); - DebugEvent(this, MessageId::kBudgetExceeded) + DebugEvent(MessageId::kBudgetExceeded, this) << "GPU page-in. Number of allocations: " << numberOfObjectsToMakeResident << " (" << GetBytesToSizeInUnits(sizeToMakeResident) << ")."; @@ -773,7 +773,7 @@ namespace gpgmm::d3d12 { GPGMM_RETURN_IF_FAILED( EvictInternal(mEvictSizeInBytes, heapSegment, &evictedSizeInBytes), mDevice); if (evictedSizeInBytes == 0) { - ErrorLog(MessageId::kBudgetInvalid, this) + ErrorLog(ErrorCode::kBudgetInvalid, this) << "Unable to evict enough heaps to stay within budget. This " "usually occurs when there is not enough available memory. " "Please reduce consumption by checking allocation sizes and " @@ -885,7 +885,7 @@ namespace gpgmm::d3d12 { ResidencyHeap* heap = static_cast(pHeap); if (heap->GetInfo().IsLocked) { - ErrorLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "Heap residency cannot be updated because it was locked. " "Please unlock the heap before updating."; return E_FAIL; @@ -893,7 +893,7 @@ namespace gpgmm::d3d12 { if (newStatus == RESIDENCY_HEAP_STATUS_UNKNOWN && heap->GetInfo().Status != RESIDENCY_HEAP_STATUS_UNKNOWN) { - ErrorLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "Heap residency cannot be unknown when previously known by the " "residency manager. Check the status before updating the state."; return E_FAIL; diff --git a/src/gpgmm/d3d12/ResourceAllocationD3D12.cpp b/src/gpgmm/d3d12/ResourceAllocationD3D12.cpp index 1d9b9da3..655e5982 100644 --- a/src/gpgmm/d3d12/ResourceAllocationD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceAllocationD3D12.cpp @@ -79,7 +79,7 @@ namespace gpgmm::d3d12 { // Allocation coordinates relative to the resource cannot be used when specifying // subresource-relative coordinates. if (subresource > 0 && GetInfo().Type == ALLOCATION_TYPE_SUBALLOCATED_WITHIN) { - ErrorLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "Mapping a sub-allocation within a resource cannot use " "non-zero subresource-relative coordinates."; return E_INVALIDARG; @@ -116,7 +116,7 @@ namespace gpgmm::d3d12 { // Allocation coordinates relative to the resource cannot be used when specifying // subresource-relative coordinates. if (subresource > 0 && GetInfo().Type == ALLOCATION_TYPE_SUBALLOCATED_WITHIN) { - ErrorLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "Unmapping a sub-allocation within a resource cannot use " "non-zero subresource-relative coordinates."; return; diff --git a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp index 73e35163..f2aa3cb8 100644 --- a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp @@ -431,7 +431,7 @@ namespace gpgmm::d3d12 { } if (allocatorDescriptor.ResourceHeapTier > caps->GetMaxResourceHeapTierSupported()) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Resource heap tier exceeds the capabilities of the device " "(ResourceHeapTier:" << allocatorDescriptor.ResourceHeapTier << " vs " @@ -442,7 +442,7 @@ namespace gpgmm::d3d12 { if (allocatorDescriptor.ResourceHeapTier != 0 && allocatorDescriptor.ResourceHeapTier < caps->GetMaxResourceHeapTierSupported()) { - DebugLog(MessageId::kInvalidArgument) + DebugLog(MessageId::kPerformanceWarning) << "Resource heap tier requested was lower than what the device " "supports. This is allowed but not recommended because it prevents " "resources of different categories from sharing the same heap."; @@ -450,7 +450,7 @@ namespace gpgmm::d3d12 { if (allocatorDescriptor.Flags & RESOURCE_ALLOCATOR_FLAG_ALWAYS_IN_BUDGET && !pResidencyManager) { - WarnLog(MessageId::kInvalidArgument) + WarnLog(MessageId::kPerformanceWarning) << "RESOURCE_ALLOCATOR_FLAG_ALWAYS_IN_BUDGET has no effect when residency " "management does not exist. This is probably not what the " "developer intended to do. Please consider creating a residency " @@ -484,7 +484,7 @@ namespace gpgmm::d3d12 { if ((allocatorDescriptor.Flags & RESOURCE_ALLOCATOR_FLAG_CREATE_NOT_RESIDENT) && !caps->IsCreateHeapNotResidentSupported()) { - DebugLog(MessageId::kInvalidArgument) + DebugLog(MessageId::kPerformanceWarning) << "RESOURCE_ALLOCATOR_FLAG_CREATE_NOT_RESIDENT was requested but disallowed " "because the device did not support creation of non-resident heaps."; newDescriptor.Flags ^= RESOURCE_ALLOCATOR_FLAG_CREATE_NOT_RESIDENT; @@ -512,7 +512,7 @@ namespace gpgmm::d3d12 { : kDefaultMemoryFragmentationLimit; if (newDescriptor.PreferredResourceHeapSize > newDescriptor.MaxResourceHeapSize) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Requested preferred resource heap size exceeded the capabilities " "of the device. This is probably not what the developer intended " "to do. Please consider using a smaller resource heap size."; @@ -981,7 +981,7 @@ namespace gpgmm::d3d12 { if (FAILED(result.GetErrorCode())) { // NeverAllocate always fails, so suppress it. if (!request.NeverAllocate) { - DebugEvent(this, MessageId::kAllocatorFailed) + DebugEvent(MessageId::kPerformanceWarning, this) << "Unable to allocate memory for request."; } return static_cast(result.GetErrorCode()); @@ -992,7 +992,7 @@ namespace gpgmm::d3d12 { HRESULT hr = createResourceFn(*allocation); if (FAILED(hr)) { - InfoEvent(this, MessageId::kAllocatorFailed) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Failed to create resource using allocation."; allocator->DeallocateMemory(std::move(allocation)); } @@ -1014,7 +1014,7 @@ namespace gpgmm::d3d12 { const D3D12_RESOURCE_ALLOCATION_INFO resourceInfo = GetResourceAllocationInfo(newResourceDesc); if (resourceInfo.SizeInBytes > mMaxResourceHeapSize) { - ErrorLog(MessageId::kSizeExceeded, this) + ErrorLog(ErrorCode::kSizeExceeded, this) << "Unable to create resource allocation because the resource size exceeded " "the capabilities of the device: " << GetBytesToSizeInUnits(resourceInfo.SizeInBytes) << " vs " @@ -1056,7 +1056,7 @@ namespace gpgmm::d3d12 { const RESOURCE_HEAP_TYPE resourceHeapType = GetResourceHeapType( newResourceDesc.Dimension, heapType, newResourceDesc.Flags, mResourceHeapTier); if (resourceHeapType == RESOURCE_HEAP_TYPE_INVALID) { - ErrorLog(MessageId::kInvalidArgument, this) + ErrorLog(ErrorCode::kInvalidArgument, this) << "Unable to create resource allocation because the resource type was invalid due " "to the combination of resource flags, descriptor, and resource heap tier."; return E_INVALIDARG; @@ -1114,7 +1114,7 @@ namespace gpgmm::d3d12 { if (GPGMM_UNLIKELY(requiresPadding)) { request.SizeInBytes += allocationDescriptor.ExtraRequiredResourcePadding; if (!neverSubAllocate) { - WarnLog(MessageId::kInvalidArgument, this) + WarnLog(MessageId::kPerformanceWarning, this) << "Sub-allocation was enabled but has no effect when padding is requested: " << GetBytesToSizeInUnits(allocationDescriptor.ExtraRequiredResourcePadding) << "."; @@ -1138,7 +1138,7 @@ namespace gpgmm::d3d12 { const uint64_t maxSegmentSize = mCaps->GetMaxSegmentSize(heapSegment); if (request.SizeInBytes > maxSegmentSize) { - ErrorLog(MessageId::kSizeExceeded, this) + ErrorLog(ErrorCode::kSizeExceeded, this) << "Unable to create resource allocation because the resource size exceeded " "the capabilities of the adapter: " << GetBytesToSizeInUnits(request.SizeInBytes) << " vs " @@ -1318,7 +1318,7 @@ namespace gpgmm::d3d12 { // allocations where sub-allocation or pooling is otherwise ineffective. // The time and space complexity of committed resource is driver-defined. if (request.NeverAllocate) { - ErrorLog(MessageId::kAllocatorFailed, this) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Unable to allocate memory for resource because no memory was allowed to " "be created."; return E_OUTOFMEMORY; @@ -1326,7 +1326,7 @@ namespace gpgmm::d3d12 { // Committed resources cannot specify resource heap size. if (GPGMM_UNLIKELY(requiresPadding)) { - ErrorLog(MessageId::kAllocatorFailed, this) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Unable to allocate memory for resource because a padding was specified " "but no resource allocator could be used."; return E_INVALIDARG; @@ -1334,7 +1334,7 @@ namespace gpgmm::d3d12 { if (!isAlwaysCommitted) { if (allocationDescriptor.Flags & ALLOCATION_FLAG_NEVER_FALLBACK) { - ErrorLog(MessageId::kAllocatorFailed, this) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Unable to allocate memory for resource because no memory was could " "be created and fall-back was disabled."; return E_OUTOFMEMORY; @@ -1350,7 +1350,7 @@ namespace gpgmm::d3d12 { mDevice); if (resourceInfo.SizeInBytes > request.SizeInBytes) { - DebugLog(MessageId::kAlignmentMismatch, this) + DebugLog(MessageId::kPerformanceWarning, this) << "Resource heap is larger then the requested: " << GetBytesToSizeInUnits(resourceInfo.SizeInBytes) << " vs " << GetBytesToSizeInUnits(request.SizeInBytes) << "."; @@ -1398,7 +1398,7 @@ namespace gpgmm::d3d12 { // TODO: enable validation conditionally? if (allocationDescriptor.HeapType != 0 && heapProperties.Type != allocationDescriptor.HeapType) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Unable to import a resource using a heap type that differs from the " "heap type used at creation. For important resources, it is recommended " "to not specify a heap type."; @@ -1406,7 +1406,7 @@ namespace gpgmm::d3d12 { } if (!HasAllFlags(heapFlags, allocationDescriptor.ExtraRequiredHeapFlags)) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Unable to import a resource using heap flags that differs from the " "heap flags used at creation. For important resources, it is recommended " "to not specify heap flags."; @@ -1414,7 +1414,7 @@ namespace gpgmm::d3d12 { } if (allocationDescriptor.ExtraRequiredResourcePadding > 0) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Unable to import a resource when using allocation flags which modify memory."; return E_INVALIDARG; } @@ -1423,7 +1423,7 @@ namespace gpgmm::d3d12 { (ALLOCATION_FLAG_NEVER_RESIDENT & ALLOCATION_FLAG_ALWAYS_ATTRIBUTE_HEAPS & ALLOCATION_FLAG_NEVER_ALLOCATE_HEAP); if (allocationDescriptor.Flags & ~allowMask) { - ErrorLog(MessageId::kInvalidArgument) + ErrorLog(ErrorCode::kInvalidArgument) << "Unable to import a resource when using allocation flags which modify memory."; return E_INVALIDARG; } @@ -1570,7 +1570,7 @@ namespace gpgmm::d3d12 { // sub-allocation is used. const uint64_t blocksPerHeap = SafeDivide(result.UsedBlockCount, result.UsedMemoryCount); if (blocksPerHeap > 1 && blocksPerHeap < kMinBlockToMemoryCountReportingThreshold) { - WarnEvent(this, MessageId::kPerformanceWarning) + WarnEvent(MessageId::kPerformanceWarning, this) << "Average number of resource allocations per heap is below threshold: " << blocksPerHeap << " blocks per heap (vs " << kMinBlockToMemoryCountReportingThreshold @@ -1584,7 +1584,7 @@ namespace gpgmm::d3d12 { 100; if (allocationUsagePct > 0 && allocationUsagePct < kMinAllocationUsageReportingThreshold * 100) { - WarnEvent(this, MessageId::kPerformanceWarning) + WarnEvent(MessageId::kPerformanceWarning, this) << "Average resource allocation usage is below threshold: " << allocationUsagePct << "% vs " << uint64_t(kMinAllocationUsageReportingThreshold * 100) << "%. This either means memory has become fragmented or the working set has " @@ -1704,7 +1704,7 @@ namespace gpgmm::d3d12 { return S_OK; } default: { - WarnLog(MessageId::kBadOperation, this) + ErrorLog(ErrorCode::kBadOperation, this) << "CheckFeatureSupport does not support feature (" + std::to_string(feature) + ")."; return E_INVALIDARG; diff --git a/src/gpgmm/d3d12/ResourceHeapAllocatorD3D12.cpp b/src/gpgmm/d3d12/ResourceHeapAllocatorD3D12.cpp index b8d2905a..f42cbab7 100644 --- a/src/gpgmm/d3d12/ResourceHeapAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceHeapAllocatorD3D12.cpp @@ -77,7 +77,7 @@ namespace gpgmm::d3d12 { resourceHeapDesc, mResidencyManager, CreateResourceHeapCallbackContext::CreateHeap, &createResourceHeapCallbackContext, &resourceHeap); if (FAILED(hr)) { - return {static_cast(hr)}; + return {static_cast(hr)}; } mStats.UsedMemoryUsage += resourceHeapDesc.SizeInBytes; diff --git a/src/gpgmm/utils/Log.cpp b/src/gpgmm/utils/Log.cpp index c0915531..2fa1e29d 100644 --- a/src/gpgmm/utils/Log.cpp +++ b/src/gpgmm/utils/Log.cpp @@ -47,7 +47,7 @@ namespace gpgmm { namespace { - const char* SeverityName(MessageSeverity severity) { + const char* GetSeverityName(MessageSeverity severity) { switch (severity) { case MessageSeverity::kDebug: return "Debug"; @@ -97,6 +97,7 @@ namespace gpgmm { LogMessage::LogMessage(MessageSeverity severity, MessageId messageId, + ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) noexcept @@ -104,7 +105,8 @@ namespace gpgmm { mMessageId(messageId), mIsExternal(isExternal), mName(name), - mObject(object) { + mObject(object), + mErrorCode(errorCode) { } LogMessage::~LogMessage() { @@ -122,7 +124,7 @@ namespace gpgmm { } #endif - const char* severityName = SeverityName(mSeverity); + const char* severityName = GetSeverityName(mSeverity); FILE* outputStream = stdout; if (mSeverity == MessageSeverity::kWarning || mSeverity == MessageSeverity::kError) { @@ -135,18 +137,22 @@ namespace gpgmm { #if defined(GPGMM_PLATFORM_WINDOWS) if (IsDebuggerPresent()) { std::string outputString; + const std::string errorString = + (mSeverity == MessageSeverity::kError) ? GetErrorFromID(mErrorCode) : ""; if (mMessageId != MessageId::kUnknown) { outputString = std::string(kLogTag) + " " + std::string(severityName) + "(tid: " + ToString(std::this_thread::get_id()) + "): " + ((mObject != nullptr) ? ((mName + ": Addr=") + ToString(mObject) + ", ") : "") + - fullMessage + " [" + GetMessageFromID(mMessageId) + "]" + "\n"; + fullMessage + " [" + + (errorString.empty() ? GetMessageFromID(mMessageId) : errorString) + "]" + "\n"; } else { outputString = std::string(kLogTag) + " " + std::string(severityName) + "(tid: " + ToString(std::this_thread::get_id()) + "): " + ((mObject != nullptr) ? ((mName + ": Addr=") + ToString(mObject) + ", ") : "") + - fullMessage + "\n"; + fullMessage + ((errorString.empty()) ? "" : (" [ " + errorString + " ]")) + + "\n"; } OutputDebugStringA(outputString.c_str()); @@ -185,28 +191,28 @@ namespace gpgmm { bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kDebug, messageId, isExternal, name, object}; + return {MessageSeverity::kDebug, messageId, ErrorCode::kNone, isExternal, name, object}; } LogMessage InfoLog(MessageId messageId, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kInfo, messageId, isExternal, name, object}; + return {MessageSeverity::kInfo, messageId, ErrorCode::kNone, isExternal, name, object}; } LogMessage WarnLog(MessageId messageId, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kWarning, messageId, isExternal, name, object}; + return {MessageSeverity::kWarning, messageId, ErrorCode::kNone, isExternal, name, object}; } - LogMessage ErrorLog(MessageId messageId, + LogMessage ErrorLog(ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) { - return {MessageSeverity::kError, messageId, isExternal, name, object}; + return {MessageSeverity::kError, MessageId::kUnknown, errorCode, isExternal, name, object}; } LogMessage DebugLog(const char* file, const char* function, int line) { @@ -230,13 +236,14 @@ namespace gpgmm { (object != nullptr) ? object->GetTypename() : "", object); } - LogMessage ErrorLog(MessageId messageId, const ObjectBase* object) { - return ErrorLog(messageId, /*isExternal*/ false, + LogMessage ErrorLog(ErrorCode errorCode, const ObjectBase* object) { + return ErrorLog(errorCode, /*isExternal*/ false, (object != nullptr) ? object->GetTypename() : "", object); } LogMessage Log(MessageSeverity severity, MessageId messageId, + ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) { @@ -248,10 +255,10 @@ namespace gpgmm { case MessageSeverity::kWarning: return WarnLog(messageId, isExternal, name, object); case MessageSeverity::kError: - return ErrorLog(messageId, isExternal, name, object); + return ErrorLog(errorCode, isExternal, name, object); default: UNREACHABLE(); - return {severity, messageId, isExternal, name, object}; + return {severity, messageId, errorCode, isExternal, name, object}; } } diff --git a/src/gpgmm/utils/Log.h b/src/gpgmm/utils/Log.h index f7fd98cb..e5ad85aa 100644 --- a/src/gpgmm/utils/Log.h +++ b/src/gpgmm/utils/Log.h @@ -44,6 +44,7 @@ // // Get more information // GPGMM_DEBUG() << texture.GetFormat(); +#include "gpgmm/common/Error.h" #include "gpgmm/common/Message.h" #include "gpgmm/common/Object.h" @@ -60,6 +61,7 @@ namespace gpgmm { public: LogMessage(MessageSeverity severity, MessageId messageId, + ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object) noexcept; @@ -84,6 +86,7 @@ namespace gpgmm { std::string mName; const ObjectBase* mObject = nullptr; std::ostringstream mStream; + ErrorCode mErrorCode = ErrorCode::kNone; }; LogMessage DebugLog(MessageId messageId, @@ -98,7 +101,7 @@ namespace gpgmm { bool isExternal, const std::string& name, const ObjectBase* object); - LogMessage ErrorLog(MessageId messageId, + LogMessage ErrorLog(ErrorCode errorCode, bool isExternal, const std::string& name, const ObjectBase* object); @@ -110,12 +113,13 @@ namespace gpgmm { const ObjectBase* object = nullptr); LogMessage WarnLog(MessageId messageId = MessageId::kUnknown, const ObjectBase* object = nullptr); - LogMessage ErrorLog(MessageId messageId = MessageId::kUnknown, + LogMessage ErrorLog(ErrorCode errorCode = ErrorCode::kUnknown, const ObjectBase* object = nullptr); // Create a LogMessage based on severity. LogMessage Log(MessageSeverity severity, MessageId messageId = MessageId::kUnknown, + ErrorCode errorCode = ErrorCode::kNone, bool isExternal = false, const std::string& name = "", const ObjectBase* object = nullptr); diff --git a/src/gpgmm/vk/DeviceMemoryAllocatorVk.cpp b/src/gpgmm/vk/DeviceMemoryAllocatorVk.cpp index da6b9fcc..a17bc9c2 100644 --- a/src/gpgmm/vk/DeviceMemoryAllocatorVk.cpp +++ b/src/gpgmm/vk/DeviceMemoryAllocatorVk.cpp @@ -40,7 +40,7 @@ namespace gpgmm::vk { const uint64_t maxDeviceMemoryAllocationCount = mResourceAllocator->GetCaps()->GetMaxDeviceAllocationCount(); if (mStats.UsedMemoryCount + 1 >= maxDeviceMemoryAllocationCount) { - DebugEvent(MessageId::kAllocatorFailed, true) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Device exceeded max number of device memory allocations (" + std::to_string(mStats.UsedMemoryCount) + " vs " + std::to_string(maxDeviceMemoryAllocationCount) + ")."; diff --git a/src/gpgmm/vk/ResourceAllocatorVk.cpp b/src/gpgmm/vk/ResourceAllocatorVk.cpp index 884c9a05..45084c13 100644 --- a/src/gpgmm/vk/ResourceAllocatorVk.cpp +++ b/src/gpgmm/vk/ResourceAllocatorVk.cpp @@ -353,7 +353,7 @@ namespace gpgmm::vk { } if (!result.IsSuccess()) { - ErrorEvent(MessageId::kAllocatorFailed, true) + ErrorLog(ErrorCode::kAllocatorFailed, this) << "Unable to allocate memory for resource."; return VK_ERROR_UNKNOWN; } diff --git a/src/gpgmm/vk/ResourceAllocatorVk.h b/src/gpgmm/vk/ResourceAllocatorVk.h index 4ed54368..4fbaae7a 100644 --- a/src/gpgmm/vk/ResourceAllocatorVk.h +++ b/src/gpgmm/vk/ResourceAllocatorVk.h @@ -30,7 +30,7 @@ namespace gpgmm::vk { class Caps; - struct GpResourceAllocator_T { + struct GpResourceAllocator_T final : public ObjectBase { public: static VkResult CreateResourceAllocator(const GpAllocatorCreateInfo& info, GpResourceAllocator* allocatorOut); @@ -67,6 +67,9 @@ namespace gpgmm::vk { uint64_t memoryTypeIndex, uint64_t memoryAlignment); + // ObjectBase interface + DEFINE_OBJECT_BASE_OVERRIDES(GpResourceAllocator_T) + VkDevice mDevice; VulkanFunctions mVulkanFunctions; std::unique_ptr mCaps;