Skip to content

Commit

Permalink
Add SSwapChainData and fix mistakes in former PR
Browse files Browse the repository at this point in the history
  • Loading branch information
WSSDude committed Jan 12, 2025
1 parent 929c8e0 commit 1f6f3cc
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 43 deletions.
6 changes: 4 additions & 2 deletions include/RED4ext/GpuApi/Buffer.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <RED4ext/Common.hpp>

#include <REd4ext/Common.hpp>
#include <d3d12.h>
#include <wrl/client.h>

Expand All @@ -16,6 +18,6 @@ struct SBufferData
uint8_t unk20[0xa8 - 0x20]; // 20
};
RED4EXT_ASSERT_SIZE(SBufferData, 0xa8);
RED4EXT_ASSERT_OFFSET(SBufferData, bufferResource, 0xa8);
RED4EXT_ASSERT_OFFSET(SBufferData, bufferResource, 0x10);
} // namespace GpuApi
} // namespace RED4ext
13 changes: 13 additions & 0 deletions include/RED4ext/GpuApi/CommandListContext-inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,16 @@ RED4EXT_INLINE void RED4ext::GpuApi::CommandListContext::FlushPendingBarriers()
static UniversalRelocFunc<func_t> func(Detail::AddressHashes::CommandListContext_FlushPendingBarriers);
func(this);
}

RED4EXT_INLINE RED4ext::GpuApi::CommandListContext* GetFreeCommandList(RED4ext::GpuApi::CommandListType aType)
{
// NOTE: this function has parameters for hash and name but they appear unused.
using func_t =
RED4ext::GpuApi::CommandListContext** (*)(RED4ext::GpuApi::CommandListContext**,
RED4ext::GpuApi::CommandListType, RED4ext::CString*, uint64_t);
static RED4ext::UniversalRelocFunc<func_t> func(RED4ext::Detail::AddressHashes::GetFreeCommandList);

RED4ext::GpuApi::CommandListContext* outContext = nullptr;
func(&outContext, aType, nullptr, 0);
return outContext;
}
38 changes: 16 additions & 22 deletions include/RED4ext/GpuApi/CommandListContext.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include <RED4ext/CString.hpp>
#include <RED4ext/Common.hpp>
#include <RED4ext/DynArray.hpp>
#include <REd4ext/CString.hpp>
#include <REd4ext/Common.hpp>

#include <d3d12.h>
#include <wrl/client.h>

Expand All @@ -26,32 +27,25 @@ struct CommandListContext
void Close();
void FlushPendingBarriers();

CString debugName; // 00
uint64_t hash; // 20
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocator; // 28
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList; // 30
uint8_t unk38[0x68 - 0x38]; // 48
CommandListType type; // 68
uint8_t unk6c[0x528 - 0x6c]; // 6C
CString debugName; // 000
uint64_t hash; // 020
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocator; // 028
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList; // 030
uint8_t unk38[0x068 - 0x038]; // 048
CommandListType type; // 068
uint8_t unk6c[0x528 - 0x06c]; // 06C
DynArray<D3D12_RESOURCE_BARRIER> pendingBarriers; // 528
uint8_t unk538[0x650 - 0x538]; // 538
};
RED4EXT_ASSERT_SIZE(CommandListContext, 0x650);
RED4EXT_ASSERT_OFFSET(CommandListContext, commandAllocator, 0x28);
RED4EXT_ASSERT_OFFSET(CommandListContext, commandList, 0x30);
RED4EXT_ASSERT_OFFSET(CommandListContext, type, 0x68);
RED4EXT_ASSERT_OFFSET(CommandListContext, debugName, 0x000);
RED4EXT_ASSERT_OFFSET(CommandListContext, hash, 0x020);
RED4EXT_ASSERT_OFFSET(CommandListContext, commandAllocator, 0x028);
RED4EXT_ASSERT_OFFSET(CommandListContext, commandList, 0x030);
RED4EXT_ASSERT_OFFSET(CommandListContext, type, 0x068);
RED4EXT_ASSERT_OFFSET(CommandListContext, pendingBarriers, 0x528);

RED4EXT_INLINE CommandListContext* GetFreeCommandList(CommandListType aType)
{
// NOTE: this function has parameters for hash and name but they appear unused.
using func_t = CommandListContext** (*)(CommandListContext**, CommandListType, const char*, uint64_t);
static UniversalRelocFunc<func_t> func(Detail::AddressHashes::GetFreeCommandList);

CommandListContext* outContext;
func(&outContext, aType, "", 0);
return outContext;
}
CommandListContext* GetFreeCommandList(CommandListType aType);

} // namespace GpuApi
} // namespace RED4ext
Expand Down
4 changes: 3 additions & 1 deletion include/RED4ext/GpuApi/D3D12MemAlloc.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <D3D12MemAlloc.h>

#ifdef RED4EXT_HEADER_ONLY
#include <RED4ext/GpuApi/D3D12MemAlloc-inl.hpp>
#endif
#endif
57 changes: 57 additions & 0 deletions include/RED4ext/GpuApi/DeviceData-inl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#ifdef RED4EXT_STATIC_LIB
#include <RED4ext/GpuApi/DeviceData.hpp>
#endif

template<typename T, size_t MAX_SIZE>
bool RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::Resource::IsUsed() const
{
return refCount >= 0;
}

template<typename T, size_t MAX_SIZE>
bool RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::IsUsedID(const uint32_t id) const
{
return IsValidID(id) && resources[IDToIndex(id)].IsUsed();
}

template<typename T, size_t MAX_SIZE>
bool RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::IsUnusedID(const uint32_t id) const
{
return IsValidID(id) && !resources[IDToIndex(id)].IsUsed();
}

template<typename T, size_t MAX_SIZE>
bool RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::IsEmpty() const
{
assert(numUnused <= MAX_SIZE);
return numUnused == MAX_SIZE;
}

template<typename T, size_t MAX_SIZE>
bool RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::IsFull() const
{
assert(numUnused <= MAX_SIZE);
return numUnused == 0;
}

template<typename T, size_t MAX_SIZE>
T& RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::GetData(uint32_t id)
{
assert(IsUsedID(id));
return resources[IDToIndex(id)].instance;
}

template<typename T, size_t MAX_SIZE>
const T& RED4ext::GpuApi::ResourceContainer<T, MAX_SIZE>::GetData(uint32_t id) const
{
assert(IsUsedID(id));
return resources[IDToIndex(id)].instance;
}

RED4EXT_INLINE RED4ext::GpuApi::SDeviceData& RED4ext::GpuApi::GetDeviceData()
{
static UniversalRelocPtr<SDeviceData*> dd(Detail::AddressHashes::g_DeviceData);
return *dd;
}
75 changes: 57 additions & 18 deletions include/RED4ext/GpuApi/DeviceData.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#pragma once

#include <RED4ext/Common.hpp>
#include <RED4ext/GpuApi/Buffer.hpp>
#include <RED4ext/GpuApi/CommandListContext.hpp>
#include <RED4ext/GpuApi/D3D12MemAlloc.hpp>
#include <REd4ext/Common.hpp>
#include <RED4ext/GpuApi/SwapChain.hpp>
#include <RED4ext/SpinLock.hpp>

namespace RED4ext
{
Expand All @@ -14,32 +16,69 @@ struct ResourceContainer
{
struct Resource
{
int32_t refCount;
bool IsUsed() const;

std::atomic_int32_t refCount;
T instance;
};

void* mutex; // 00 - spin lock?
int32_t defaultNumUnused; // 08 - defaults to MaxSize
static constexpr uint32_t IDToIndex(const uint32_t id)
{
return id - 1;
}

static constexpr uint32_t IndexToID(const uint32_t index)
{
return index + 1;
}

static constexpr bool IsValidIndex(const uint32_t index)
{
return index < MAX_SIZE;
}

static constexpr bool IsValidID(const uint32_t id)
{
return IsValidIndex(IDToIndex(id));
}

bool IsUsedID(uint32_t id) const;

bool IsUnusedID(uint32_t id) const;

bool IsEmpty() const;

bool IsFull() const;

T& GetData(uint32_t id);

const T& GetData(uint32_t id) const;

SpinLock* spinLockRef; // 00
std::atomic_int32_t numUnused; // 08 - defaults to MaxSize
Resource resources[MAX_SIZE];
uint16_t unusedIndices[MAX_SIZE];
uint16_t unusedIndices[MAX_SIZE]; // These are indices, not IDs!
};

struct SDeviceDataBase
{
uint8_t unk00[0x5c0ae0 - 0x00]; // 00
uint8_t unk00[0x5c0ae0 - 0x000000]; // 000000
ResourceContainer<SBufferData, 32768> buffers; // 5C0AE0
uint8_t unkb40af8[0xd1ad80 - 0xb50af0]; // B50AF0
uint8_t unkb40af8[0xc97f20 - 0xb50af0]; // B50AF0
ResourceContainer<SSwapChainData, 32> swapChains; // C97F20
uint8_t unkc99678[0xd1ad80 - 0xc99570]; // C98028
ResourceContainer<CommandListContext*, 128> commandLists; // D1AD80 - Uses unknown ptr wrapper
uint8_t unkd1b598[0x13bc240 - 0xd1b690]; // D1B690
};
RED4EXT_ASSERT_SIZE(SDeviceDataBase, 0x13bc240);
RED4EXT_ASSRT_OFFSET(SDeviceDataBase, buffers, 0x5C0AE0);
RED4EXT_ASSRT_OFFSET(SDeviceDataBase, commandLists, 0xD1AD80);
RED4EXT_ASSERT_OFFSET(SDeviceDataBase, buffers, 0x5c0ae0);
RED4EXT_ASSERT_OFFSET(SDeviceDataBase, swapChains, 0xc97f20);
RED4EXT_ASSERT_OFFSET(SDeviceDataBase, commandLists, 0xd1ad80);

struct SDeviceData : SDeviceDataBase
{
uint8_t unk13bc240[0x13bc4a8 - 0x13bc240]; // 13BC240
Microsoft::WRL::ComPtr<ID3D12Device> device; // 13BC4A8
Microsoft::WRL::ComPtr<ID3D12Device14> device; // 13BC4A8
uint8_t unk13bc4b0[0x13bc4d0 - 0x13bc4b0]; // 13BC4B0
Microsoft::WRL::ComPtr<ID3D12CommandQueue> directCommandQueue; // 13BC4D0
Microsoft::WRL::ComPtr<ID3D12CommandQueue> computeCommandQueue; // 13BC4D8
Expand All @@ -48,14 +87,14 @@ struct SDeviceData : SDeviceDataBase
uint8_t unk13bc4b8[0x1a8f880 - 0x13bc548]; // 13BC548
};
RED4EXT_ASSERT_SIZE(SDeviceData, 0x1a8f880);
RED4EXT_ASSRT_OFFSET(SDeviceData, device, 0x13BC4A8);
RED4EXT_ASSRT_OFFSET(SDeviceData, directCommandQueue, 0x13BC4D0);
RED4EXT_ASSRT_OFFSET(SDeviceData, memoryAllocator, 0x13BC540);
RED4EXT_ASSERT_OFFSET(SDeviceData, device, 0x13bc4a8);
RED4EXT_ASSERT_OFFSET(SDeviceData, directCommandQueue, 0x13bc4d0);
RED4EXT_ASSERT_OFFSET(SDeviceData, memoryAllocator, 0x13bc540);

RED4EXT_INLINE SDeviceData& GetDeviceData()
{
static UniversalRelocPtr<SDeviceData*> dd(Detail::AddressHashes::g_DeviceData);
return *dd;
}
SDeviceData& GetDeviceData();
} // namespace GpuApi
} // namespace RED4ext

#ifdef RED4EXT_HEADER_ONLY
#include <RED4ext/GpuApi/DeviceData-inl.hpp>
#endif
46 changes: 46 additions & 0 deletions include/RED4ext/GpuApi/SwapChain.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include <d3d12.h>
#include <dxgi1_6.h>
#include <wrl/client.h>
#include <wrl/wrappers/corewrappers.h>

namespace RED4ext
{
namespace GpuApi
{
struct SSwapChainData
{
static constexpr uint32_t MaxBackBuffers = 3u;

Microsoft::WRL::ComPtr<IDXGISwapChain4> swapChain; // 00
uint8_t unk8[0x28 - 0x08]; // 08 - Always seems to be filled with zeros.
uint32_t backBufferTextureId; // 28 - Reference to back buffer texture data.
uint32_t backBufferIndex; // 2C
uint8_t unk30; // 30 - Always seems to be zero.
bool fullScreen; // 31 - True when in fullscreen.
HWND windowHandle; // 38
Microsoft::WRL::ComPtr<ID3D12Fence1> presentFence; // 40
uint64_t presentFenceCompletionFrames[MaxBackBuffers]; // 48 - Compared against completion value in presentFence
// before swapping back buffer.
uint64_t presentFenceNextCompletionFrame; // 60 - Gets assigned to presentFenceCompletionFrames[backBufferIndex]
// each GpuApi::DoPresent call after the presentFence is Signaled with the
// same value, auto-incremented on each call.
D3D12_CPU_DESCRIPTOR_HANDLE backBufferRtvs[MaxBackBuffers]; // 68
D3D12_CPU_DESCRIPTOR_HANDLE backBufferUavs[MaxBackBuffers]; // 80
Microsoft::WRL::Wrappers::Event presentFenceEvent; // 98 - Event signaled on presentFence completion.
};
RED4EXT_ASSERT_SIZE(SSwapChainData, 0xa8);
RED4EXT_ASSERT_OFFSET(SSwapChainData, swapChain, 0x00);
RED4EXT_ASSERT_OFFSET(SSwapChainData, backBufferTextureId, 0x28);
RED4EXT_ASSERT_OFFSET(SSwapChainData, backBufferIndex, 0x2c);
RED4EXT_ASSERT_OFFSET(SSwapChainData, fullScreen, 0x31);
RED4EXT_ASSERT_OFFSET(SSwapChainData, windowHandle, 0x38);
RED4EXT_ASSERT_OFFSET(SSwapChainData, presentFence, 0x40);
RED4EXT_ASSERT_OFFSET(SSwapChainData, presentFenceCompletionFrames, 0x48);
RED4EXT_ASSERT_OFFSET(SSwapChainData, presentFenceNextCompletionFrame, 0x60);
RED4EXT_ASSERT_OFFSET(SSwapChainData, backBufferRtvs, 0x68);
RED4EXT_ASSERT_OFFSET(SSwapChainData, backBufferUavs, 0x80);
RED4EXT_ASSERT_OFFSET(SSwapChainData, presentFenceEvent, 0x98);
} // namespace GpuApi
} // namespace RED4ext
5 changes: 5 additions & 0 deletions src/GpuApi/DeviceData.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#ifndef RED4EXT_STATIC_LIB
#error Please define 'RED4EXT_STATIC_LIB' to compile this file.
#endif

#include <RED4ext/GpuApi/DeviceData-inl.hpp>

0 comments on commit 1f6f3cc

Please sign in to comment.