How Does Direct2D Work Alongside Direct3D?
Direct2D and Direct3D operate as complementary graphics APIs within Microsoft's DirectX ecosystem, sharing underlying hardware resources rather than running as isolated pipelines. Built directly on top of Direct3D, Direct2D translates 2D vector geometries, text, and bitmaps into hardware-accelerated Direct3D primitives, drawing calls, and shaders. By utilizing the DirectX Graphics Infrastructure (DXGI) as a common interchange format, developers can seamlessly combine 2D user interfaces or overlays with complex 3D scenes on the same rendering targets without incurring expensive system-memory readbacks.
The Architecture of Direct2D on Direct3D
Historically, Windows separated 2D rendering (via GDI and GDI+) from 3D hardware pipelines. Starting with Windows 7, Microsoft designed Direct2D to eliminate this divide by utilizing Direct3D as its underlying hardware abstraction layer.
Direct2D does not talk directly to the graphics driver. Instead, it
generates Direct3D vertex buffers, index buffers, and draw calls
internally. When an application calls DrawGeometry or
FillRectangle, Direct2D tessellates the 2D shapes into
triangles, uploads vertex data, binds specialized pixel shaders, and
issues draw calls to the Direct3D device. This ensures that text
rendering via DirectWrite and vector shapes receive the same GPU
execution speed, texture filtering, and anti-aliasing hardware benefits
as native 3D geometry.
Shared Surfaces Through DXGI
The core bridge between Direct2D and Direct3D is the DirectX Graphics Infrastructure (DXGI). DXGI manages the fundamental low-level tasks common across graphics APIs, such as adapter enumeration, swap chain management, and surface memory allocation.
Direct2D interoperates with Direct3D by targeting a shared
IDXGISurface:
- Device Creation: The application initializes a Direct3D device context (such as Direct3D 11).
- DXGI Surface Acquisition: A texture or back buffer
is created in Direct3D with compatibility flags enabling it to be
referenced as an
IDXGISurface. - Render Target Binding: Direct2D creates a render
target (such as
ID2D1RenderTargetorID2D1DeviceContext) directly wrapping that underlying DXGI surface.
Because both runtimes reference the exact same video memory addresses, zero data copying is required across the PCIe bus. Drawing commands issued via Direct2D render straight into the Direct3D surface buffer.
Mixed-Mode Rendering Pipelines
Developers typically combine Direct2D and Direct3D using two architectural workflows:
1. Direct2D Overlays on 3D Scenes
In games, data visualization software, and CAD tools, the 3D scene is
rendered first using standard Direct3D shaders and depth buffers. Once
3D rendering finishes, the application calls BeginDraw() on
the Direct2D context attached to the same back buffer. Direct2D draws
HUD elements, text, and 2D vector UI widgets on top of the existing
image before presenting the swap chain.
2. Texture-Level Interoperability
Alternatively, Direct2D can render into off-screen Direct3D textures. These textures can then be bound as shader resource views inside a 3D pipeline. This technique allows developers to draw interactive interfaces, dynamic gauges, or rendered text directly onto 3D surfaces and in-game computer terminals within a virtual world.
Resource Management and State Synchronization
While Direct2D abstracts Direct3D operations, sharing a context requires explicit state management. Direct2D alters pipeline states—such as blend states, viewport boundaries, rasterizer options, and shader bindings—during its draw routines.
To maintain correct operation:
- Applications must ensure Direct3D finishes relevant tasks before
Direct2D begins, invoking
Flush()or matching appropriate synchronization fences. - When using modern APIs like Direct3D 12, interop typically relies on
the Direct3D 11 On 12 mapping layer (
ID3D11On12Device), which translates Direct2D’s underlying Direct3D 11 instructions into Direct3D 12 command lists and resource transitions. - Developers must restore necessary Direct3D state blocks after
Direct2D issues
EndDraw(), preventing 2D pipeline side effects from altering subsequent 3D render passes.