From c2171fe3fc478aa0aa6e46908863ab458d2ceee6 Mon Sep 17 00:00:00 2001 From: psiberx Date: Wed, 22 Jan 2025 23:18:12 +0300 Subject: [PATCH 1/4] Fix typo --- include/RED4ext/ISerializable.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/RED4ext/ISerializable.hpp b/include/RED4ext/ISerializable.hpp index 245cafe42..f6797e1ea 100644 --- a/include/RED4ext/ISerializable.hpp +++ b/include/RED4ext/ISerializable.hpp @@ -58,7 +58,7 @@ struct ISerializable operator const WeakHandle&() const noexcept; operator Handle() noexcept; - WeakHandle ref; // 00 - Initialized in Handle ctor + WeakHandle ref; // 08 - Initialized in Handle ctor WeakHandle unk18; // 18 uint64_t unk28; // 28 - Global incremental ID, used in serialization }; From 67f966bd840387827246fcc5c306183543e64a5e Mon Sep 17 00:00:00 2001 From: psiberx Date: Wed, 22 Jan 2025 23:18:26 +0300 Subject: [PATCH 2/4] Add UniquePtr --- include/RED4ext/Memory/UniquePtr.hpp | 111 +++++++++++++++++++++++++++ include/RED4ext/RED4ext.hpp | 1 + 2 files changed, 112 insertions(+) create mode 100644 include/RED4ext/Memory/UniquePtr.hpp diff --git a/include/RED4ext/Memory/UniquePtr.hpp b/include/RED4ext/Memory/UniquePtr.hpp new file mode 100644 index 000000000..deae2af13 --- /dev/null +++ b/include/RED4ext/Memory/UniquePtr.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include + +#include +#include + +namespace RED4ext +{ +template +class UniquePtr +{ +public: + UniquePtr(T* aPtr = nullptr) + : instance(aPtr) + { + } + + UniquePtr(const UniquePtr&) = delete; + + UniquePtr(UniquePtr&& aOther) noexcept + { + instance = aOther.Release(); + } + + ~UniquePtr() + { + static_assert(Memory::IsDeleteCompatible, + "UniquePtr only supports types that define the allocator type and are destructible " + "(a polymorphic type requires a virtual destructor)"); + + if (instance) + { + Memory::Delete(instance); + } + } + + UniquePtr& operator=(const UniquePtr&) = delete; + + UniquePtr& operator=(UniquePtr&& aRhs) noexcept + { + UniquePtr(std::move(aRhs)).Swap(*this); + return *this; + } + + template>> + [[nodiscard]] inline U& operator*() const + { + return *GetPtr(); + } + + [[nodiscard]] inline T* operator->() const + { + return GetPtr(); + } + + [[nodiscard]] inline operator T*() const + { + return GetPtr(); + } + + explicit operator bool() const noexcept + { + return GetPtr() != nullptr; + } + + [[nodiscard]] T* GetPtr() const noexcept + { + return reinterpret_cast(instance); + } + + template + [[nodiscard]] U* GetPtr() const noexcept + { + return reinterpret_cast(instance); + } + + T* Release() noexcept + { + T* released = instance; + instance = nullptr; + return released; + } + + void Reset() noexcept + { + UniquePtr().Swap(*this); + } + + void Reset(T* aPtr) noexcept + { + UniquePtr(aPtr).Swap(*this); + } + + void Swap(UniquePtr& aOther) noexcept + { + std::swap(instance, aOther.instance); + } + + T* instance; + +}; +RED4EXT_ASSERT_SIZE(UniquePtr, 0x8); +RED4EXT_ASSERT_OFFSET(UniquePtr, instance, 0x0); + +template +inline UniquePtr MakeUnique(Args&&... args) +{ + return Memory::New(std::forward(args)...); +} +} // namespace RED4ext diff --git a/include/RED4ext/RED4ext.hpp b/include/RED4ext/RED4ext.hpp index 431c5647e..b973c15c2 100644 --- a/include/RED4ext/RED4ext.hpp +++ b/include/RED4ext/RED4ext.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include From 7aa8ab579360c7f5366f27242ccf4584586af5c4 Mon Sep 17 00:00:00 2001 From: psiberx Date: Wed, 22 Jan 2025 23:19:14 +0300 Subject: [PATCH 3/4] Use UniquePtr for CommandListContext --- include/RED4ext/Detail/AddressHashes.hpp | 1 + .../RED4ext/GpuApi/CommandListContext-inl.hpp | 22 +++++++++++++------ include/RED4ext/GpuApi/CommandListContext.hpp | 10 ++++++--- include/RED4ext/GpuApi/DeviceData.hpp | 18 +++++++-------- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/include/RED4ext/Detail/AddressHashes.hpp b/include/RED4ext/Detail/AddressHashes.hpp index b4dc9de3e..1e96c8e43 100644 --- a/include/RED4ext/Detail/AddressHashes.hpp +++ b/include/RED4ext/Detail/AddressHashes.hpp @@ -79,6 +79,7 @@ constexpr std::uint32_t CNamePool_Get = 0x68DF07DC; #pragma region CommandListContext constexpr std::uint32_t GetFreeCommandList = 1926836641UL; +constexpr std::uint32_t CommandListContext_dtor = 4228123904UL; constexpr std::uint32_t CommandListContext_AddPendingBarrier = 2814122829UL; constexpr std::uint32_t CommandListContext_Close = 1163138096UL; constexpr std::uint32_t CommandListContext_FlushPendingBarriers = 2786924000UL; diff --git a/include/RED4ext/GpuApi/CommandListContext-inl.hpp b/include/RED4ext/GpuApi/CommandListContext-inl.hpp index 86789c185..cf2e08644 100644 --- a/include/RED4ext/GpuApi/CommandListContext-inl.hpp +++ b/include/RED4ext/GpuApi/CommandListContext-inl.hpp @@ -8,6 +8,13 @@ namespace RED4ext::GpuApi { +RED4EXT_INLINE CommandListContext::~CommandListContext() +{ + using func_t = void (*)(CommandListContext*); + static const UniversalRelocFunc func(Detail::AddressHashes::CommandListContext_dtor); + func(this); +} + RED4EXT_INLINE void CommandListContext::AddPendingBarrier(const D3D12_RESOURCE_BARRIER& aBarrier) { using func_t = void (*)(CommandListContext*, const D3D12_RESOURCE_BARRIER&); @@ -29,16 +36,17 @@ RED4EXT_INLINE void CommandListContext::FlushPendingBarriers() func(this); } -RED4EXT_INLINE CommandListContext* AcquireFreeCommandList(CommandListType aType, const StringView& aDebugName, - uint64_t aHash) +RED4EXT_INLINE UniquePtr AcquireFreeCommandList(CommandListType aType, const StringView& aDebugName, + uint64_t aHash) { // NOTE: This function has parameters for debug name and hash which seem to be optional. - // Expects unique ptr as an out param and returns it by reference. - using func_t = CommandListContext*& (*)(CommandListContext*&, CommandListType, const StringView&, uint64_t); + using func_t = UniquePtr* (*)(UniquePtr&, CommandListType, + const StringView&, uint64_t); static const UniversalRelocFunc func(Detail::AddressHashes::GetFreeCommandList); - // TODO: This should be unique_ptr which function fills in and returns. - CommandListContext* outContext = nullptr; - return func(outContext, aType, aDebugName, aHash); + UniquePtr outContext; + func(outContext, aType, aDebugName, aHash); + + return std::move(outContext); } } // namespace RED4ext::GpuApi diff --git a/include/RED4ext/GpuApi/CommandListContext.hpp b/include/RED4ext/GpuApi/CommandListContext.hpp index f32abaf96..018622041 100644 --- a/include/RED4ext/GpuApi/CommandListContext.hpp +++ b/include/RED4ext/GpuApi/CommandListContext.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,10 @@ enum class CommandListType struct CommandListContext { + using AllocatorType = Memory::CommandListsAllocator; + + ~CommandListContext(); + void AddPendingBarrier(const D3D12_RESOURCE_BARRIER& aBarrier); void Close(); void FlushPendingBarriers(); @@ -46,9 +51,8 @@ RED4EXT_ASSERT_OFFSET(CommandListContext, commandList, 0x030); RED4EXT_ASSERT_OFFSET(CommandListContext, type, 0x068); RED4EXT_ASSERT_OFFSET(CommandListContext, pendingBarriers, 0x528); -// TODO: Change to return unique ptr. -CommandListContext* AcquireFreeCommandList(CommandListType aType, const StringView& aDebugName = "", - uint64_t aHash = 0); +UniquePtr AcquireFreeCommandList(CommandListType aType, const StringView& aDebugName = "", + uint64_t aHash = 0); } // namespace GpuApi } // namespace RED4ext diff --git a/include/RED4ext/GpuApi/DeviceData.hpp b/include/RED4ext/GpuApi/DeviceData.hpp index 5259eb07d..d1fa07a75 100644 --- a/include/RED4ext/GpuApi/DeviceData.hpp +++ b/include/RED4ext/GpuApi/DeviceData.hpp @@ -62,15 +62,15 @@ struct ResourceContainer struct SDeviceDataBase { - uint8_t unk00[0x02f180]; // 000000 - SpinLock resourcesSpinLock; // 02F180 - uint8_t unk2f180[0x5c0ae0 - 0x02f181]; // 02F181 - ResourceContainer buffers; // 5C0AE0 - uint8_t unkb40af8[0xc97f20 - 0xb50af0]; // B50AF0 - ResourceContainer swapChains; // C97F20 - uint8_t unkc99678[0xd1ad80 - 0xc99570]; // C98028 - ResourceContainer commandLists; // D1AD80 - TODO: Uses unique ptr wrapper. - uint8_t unkd1b598[0x13bc240 - 0xd1b690]; // D1B690 + uint8_t unk00[0x02f180]; // 000000 + SpinLock resourcesSpinLock; // 02F180 + uint8_t unk2f180[0x5c0ae0 - 0x02f181]; // 02F181 + ResourceContainer buffers; // 5C0AE0 + uint8_t unkb40af8[0xc97f20 - 0xb50af0]; // B50AF0 + ResourceContainer swapChains; // C97F20 + uint8_t unkc99678[0xd1ad80 - 0xc99570]; // C98028 + ResourceContainer, 128> commandLists; // D1AD80 + uint8_t unkd1b598[0x13bc240 - 0xd1b690]; // D1B690 }; RED4EXT_ASSERT_SIZE(SDeviceDataBase, 0x13bc240); RED4EXT_ASSERT_OFFSET(SDeviceDataBase, buffers, 0x5c0ae0); From 836766536f8a72bd55c696cfecb62bdb7de536bf Mon Sep 17 00:00:00 2001 From: psiberx Date: Wed, 22 Jan 2025 23:24:37 +0300 Subject: [PATCH 4/4] Fix typo --- include/RED4ext/Memory/UniquePtr.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/RED4ext/Memory/UniquePtr.hpp b/include/RED4ext/Memory/UniquePtr.hpp index deae2af13..b851582d2 100644 --- a/include/RED4ext/Memory/UniquePtr.hpp +++ b/include/RED4ext/Memory/UniquePtr.hpp @@ -98,7 +98,6 @@ class UniquePtr } T* instance; - }; RED4EXT_ASSERT_SIZE(UniquePtr, 0x8); RED4EXT_ASSERT_OFFSET(UniquePtr, instance, 0x0);