Skip to content

Commit

Permalink
Merge pull request #175 from psiberx/master
Browse files Browse the repository at this point in the history
Added UniquePtr implementation
  • Loading branch information
psiberx authored Jan 23, 2025
2 parents 1e757de + 8367665 commit 7719488
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 20 deletions.
1 change: 1 addition & 0 deletions include/RED4ext/Detail/AddressHashes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
22 changes: 15 additions & 7 deletions include/RED4ext/GpuApi/CommandListContext-inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

namespace RED4ext::GpuApi
{
RED4EXT_INLINE CommandListContext::~CommandListContext()
{
using func_t = void (*)(CommandListContext*);
static const UniversalRelocFunc<func_t> 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&);
Expand All @@ -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<CommandListContext> 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<CommandListContext>* (*)(UniquePtr<CommandListContext>&, CommandListType,
const StringView&, uint64_t);
static const UniversalRelocFunc<func_t> 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<CommandListContext> outContext;
func(outContext, aType, aDebugName, aHash);

return std::move(outContext);
}
} // namespace RED4ext::GpuApi
10 changes: 7 additions & 3 deletions include/RED4ext/GpuApi/CommandListContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <RED4ext/CString.hpp>
#include <RED4ext/Common.hpp>
#include <RED4ext/DynArray.hpp>
#include <RED4ext/Memory/UniquePtr.hpp>
#include <RED4ext/StringView.hpp>

#include <d3d12.h>
Expand All @@ -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();
Expand All @@ -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<CommandListContext> AcquireFreeCommandList(CommandListType aType, const StringView& aDebugName = "",
uint64_t aHash = 0);

} // namespace GpuApi
} // namespace RED4ext
Expand Down
18 changes: 9 additions & 9 deletions include/RED4ext/GpuApi/DeviceData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ struct ResourceContainer

struct SDeviceDataBase
{
uint8_t unk00[0x02f180]; // 000000
SpinLock resourcesSpinLock; // 02F180
uint8_t unk2f180[0x5c0ae0 - 0x02f181]; // 02F181
ResourceContainer<SBufferData, 32768> buffers; // 5C0AE0
uint8_t unkb40af8[0xc97f20 - 0xb50af0]; // B50AF0
ResourceContainer<SSwapChainData, 32> swapChains; // C97F20
uint8_t unkc99678[0xd1ad80 - 0xc99570]; // C98028
ResourceContainer<CommandListContext*, 128> 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<SBufferData, 32768> buffers; // 5C0AE0
uint8_t unkb40af8[0xc97f20 - 0xb50af0]; // B50AF0
ResourceContainer<SSwapChainData, 32> swapChains; // C97F20
uint8_t unkc99678[0xd1ad80 - 0xc99570]; // C98028
ResourceContainer<UniquePtr<CommandListContext>, 128> commandLists; // D1AD80
uint8_t unkd1b598[0x13bc240 - 0xd1b690]; // D1B690
};
RED4EXT_ASSERT_SIZE(SDeviceDataBase, 0x13bc240);
RED4EXT_ASSERT_OFFSET(SDeviceDataBase, buffers, 0x5c0ae0);
Expand Down
2 changes: 1 addition & 1 deletion include/RED4ext/ISerializable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct ISerializable
operator const WeakHandle<ISerializable>&() const noexcept;
operator Handle<ISerializable>() noexcept;

WeakHandle<ISerializable> ref; // 00 - Initialized in Handle ctor
WeakHandle<ISerializable> ref; // 08 - Initialized in Handle ctor
WeakHandle<ISerializable> unk18; // 18
uint64_t unk28; // 28 - Global incremental ID, used in serialization
};
Expand Down
110 changes: 110 additions & 0 deletions include/RED4ext/Memory/UniquePtr.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#pragma once

#include <memory>

#include <RED4ext/Common.hpp>
#include <RED4ext/Memory/Utils.hpp>

namespace RED4ext
{
template<typename T>
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<T>,
"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<typename U = T, typename = std::enable_if_t<!std::is_void_v<U>>>
[[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<T*>(instance);
}

template<typename U>
[[nodiscard]] U* GetPtr() const noexcept
{
return reinterpret_cast<U*>(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<void>, 0x8);
RED4EXT_ASSERT_OFFSET(UniquePtr<void>, instance, 0x0);

template<typename T, typename... Args>
inline UniquePtr<T> MakeUnique(Args&&... args)
{
return Memory::New<T>(std::forward<Args>(args)...);
}
} // namespace RED4ext
1 change: 1 addition & 0 deletions include/RED4ext/RED4ext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <RED4ext/Hashing/Murmur3.hpp>
#include <RED4ext/Memory/Allocators.hpp>
#include <RED4ext/Memory/SharedPtr.hpp>
#include <RED4ext/Memory/UniquePtr.hpp>

#include <RED4ext/IO/BaseStream.hpp>

Expand Down

0 comments on commit 7719488

Please sign in to comment.