ninepoints.just regular fiat Profile picture
Graphics and game engines. Ex Amazon, WB, Cryptic, Riot. Now at: @ninepoints@mastodon.gamedev.place 🐘

Nov 10, 2020, 14 tweets

For people interested making an engine that supports both Vulkan and D3D12, here's a quick summary of differences you should plan for. I can't comment about any other proprietary APIs (console), but setting yourself up for Vulkan/D3D12 is a decent start for all of them (1/n)

1. Descriptors in Vulkan are strongly typed and are untyped in D3D12. Descriptors in VK refer to buffers, images, samplers and must be provisioned for in a descriptor pool. Descriptors in D3D12 are simply virtual addresses, without type information

2. D3D12 has no concept of "descriptor sets." Instead, you can bind descriptors to particular "register spaces" and you have to manage this grouping yourself.

3. The binding model for D3D12 is more explicit in how you manage the "root signature" (pipeline layout in VK parlance). You assign data to explicit slots instead of letting the API/driver manage that for you

4. Render passes in D3D12 don't have a notion of subpass dependencies, instead you rely on resource transitions to ensure your render targets are in the proper state

5. "Secondary command buffers" in VK are "command list bundles" in D3D12. In VK, they don't inherit state unless executing within a render pass (in which case they inherit subpass and query state). In D12, they more or less inherit all state.

6. VK secondary CBs can operate on the compute/dma queue, but D12 bundles can't (in practice not often important, VK CBs can't inherit state, so why would you want this)

7. VK supports the "timeline semaphore" via extension which mirrors the D3D12 "fence." There is also VkEvent which is a bit harder to use but doesn't require the extension. In general, VK has more of a "zoo" of synchronization primitives. The semaphore is still needed for present

8. Speaking of extensions, VK requires you to chain extension required data using struct chaining and occasionally to query function pointers. D3D12 has you query for the available interface COM-style, and uses inheritance so you don't have to do the chaining yourself

9. Required alignment is somewhat more "hardcoded" in D3D12, with constants provided to specify alignment restrictions for placement/allocation/etc. In VK, you're expected to query this at runtime. Note that this has implications for compile-time code.

10. D3D12 has a concept of "reserved memory" wherein you allocate a virtual address range and page data in and out of VRAM. It also lets you respond to low-memory warning messages this way. VK doesn't have this so you have to do this in other means

11. From an API standpoint, D3D12 resources are modeled via inheritance. Everything is a "resource" and resources have handles, resource usage, etc. VK resources are typed separately.

Probably forgetting a ton of things. Wrote this in ~10 minutes in sort of a blur. Feel free to comment to fill in the (inevitable gaps). Also, note that I tried not to comment on which API I "preferred." Honestly, strengths and weaknesses in both APIs imo.

Note that there are a lot of differences that are just naming things, so not as disruptive when it comes to implementation. It can be hard to know what to look for sometimes though. For example, ROVs (rasterizer order views) in D3D12 is VK_EXT_fragment_shader_interlock in VK

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling