DX12
环境搭建
我们可以向UE一样,把需要的头文件封印在 ThirdParty 中:


诸如 dxgi1_6.h dxgiformat.h 这样的头文件,我们可以在这里找到:https://github.com/microsoft/win32metadata/tree/main/generation/WinSDK/RecompiledIdlHeaders/shared
其实本地装了Windows sdk,这些文件就会在这里:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared
而 d3dx12.h,我们则可以在这里找到:https://github.com/microsoft/DirectXTK12/tree/main/Src
关于 UE 的做法
ue可以看到把相关的一些文件都放在 third party 了,

这样子就不需要依赖Windows SDK。而我们目前是依赖Windows SDK,需要在cmake中链接:
target_link_libraries(HEngineRuntime PUBLIC d3d11.lib d3d12.lib dxgi.lib dxguid.lib D3DCompiler.lib d2d1.lib dwrite.lib winmm.lib)初始化
我们想用 EnumAdapterByGpuPreference 去按照性能来排序枚举系统中的适配器,这需要用到IDXGIFactory6,参考:
https://blog.csdn.net/u014038143/article/details/102493360
参考官方文档:https://learn.microsoft.com/en-us/windows/win32/api/_direct3ddxgi/
每一代dxgi都会升级一些新的接口,同时保持旧的接口兼容,这些也是包含在 Windows sdk 里的,应该也就和驱动相关了。
Device
https://directx11.tech/#/part1/01
https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-d3d12createdevice
参考上面链接,D3D12CreateDevice 函数其实是统一创建一个 ID3D11Device,我们可以需要哪个更高型号再转型查看可不可用。例如ue的做法:


同样根据之前说的,我们想用 IDXGIFactory6 版本的 EnumAdapterByGpuPreference 方法,ue 是这样做的:

不过事实上除了 RootDevice->QueryInterface,如果是 ComPtr 的话(UE没用微软的 ComPtr,而是自己包出了 TRefCountPtr ),可以直接用 ComPtr::As,例如:

相当于调用 IUnknown::QueryInterface,失败了也只不过是返回一个nullptr指针(对应上图即 dxgiFactory2 为 nullptr)
D3D_FEATURE_LEVEL
参考:https://directx11.tech/#/part1/01
我们可以轮询特性数组 D3D_FEATURE_LEVEL featureLevels 来检测所支持的特性等级,它的定义可以在 d3dcommon 里找到,具体安装位置在安装的 Windows sdk 的 C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um 里面。而 10.0.19041.0 是没有 D3D_FEATURE_LEVEL_12_2 的,这就没法使用 Shader model 6.5,具体特性等级的差异可以看:https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro
这一特性等级需要在 10.0.20348.0 及以上的版本才能开启。
描述符管理
http://diligentgraphics.com/diligent-engine/architecture/d3d12/ https://zhuanlan.zhihu.com/p/129257338 https://github.com/DiligentGraphics/DiligentCore/blob/master/Graphics/GraphicsAccessories/interface/VariableSizeAllocationsManager.hpp
内存分配
当和 Descriptor 关联的 Resource View 释放时,Descriptor 在逻辑上就成为可重用的状态,而这一切都需要 API 使用者自己来保证,所以可以一些常用的内存分配算法如 Buddy 来管理 Descriptor 的分配和释放,以此达到 Descriptor 重用的目的。
微软官方给的例子就是 Buddy Allocator:https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/MiniEngine/Core/BuddyAllocator.h
我们也能参考前面的链接:http://diligentgraphics.com/diligent-engine/architecture/d3d12/
104使用的vulkan,用到了第三方库VulkanMemoryAllocator:https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/include/vk_mem_alloc.h
我发现这个库也有d3d12版本(官方说明的上面这个vulkan版本的等效库):https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator
对应的文档:https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/
RenderGraph
参考:https://github.com/mateeeeeee/Adria-DX12/tree/master/Adria
封装
参考:
https://github.com/SuikaSibyl/SibylEngine2021
https://github.com/J-Mat/ZeroEngine/tree/main/ZeroEngine/Engine/Source/Runtime/Render/RHI
https://www.zhihu.com/column/c_1414208206361587713
https://www.zhihu.com/column/c_1434895110592552960
主要参考:
https://github.com/jpvanoosten/LearningDirectX12/tree/main
https://www.3dgep.com/learning-directx-12-2/
D3D12MA:
https://github.dev/mateeeeeee/Adria-DX12/tree/master/Adria/Graphics
发现它主要是在 Buffer 和 Texture 使用 D3D12MA 管理。
更多资料
https://developer.nvidia.com/dx12-dos-and-donts
http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/
https://gpuopen.com/learn/get-the-most-out-of-smart-access-memory/
https://stackoverflow.com/questions/37277332/directx-12-descriptor-heaps
Last updated