Delen via


D2D met D3D11on12

Het D3D1211on12 voorbeeld laat zien hoe u D2D-inhoud over D3D12-inhoud kunt weergeven door resources te delen tussen een apparaat op basis van 11 en een apparaat met 12.

Een ID3D11On12Device maken

De eerste stap is het maken van een ID3D11On12Device- nadat de ID3D12Device- is gemaakt, waarbij een ID3D11Device- wordt gemaakt die is verpakt rond de ID3D12Device- via de API D3D11On12CreateDevice. Deze API neemt onder andere de parameter ID3D12CommandQueue- op, zodat het 11On12-apparaat zijn opdrachten kan verzenden. Nadat de ID3D11Device- is gemaakt, kunt u een query uitvoeren op de ID3D11On12Device interface. Dit is het primaire apparaatobject dat wordt gebruikt voor het instellen van D2D.

In de methode LoadPipeline moet u de apparaten instellen.

 // Create an 11 device wrapped around the 12 device and share
    // 12's command queue.
    ComPtr<ID3D11Device> d3d11Device;
    ThrowIfFailed(D3D11On12CreateDevice(
        m_d3d12Device.Get(),
        d3d11DeviceFlags,
        nullptr,
        0,
        reinterpret_cast<IUnknown**>(m_commandQueue.GetAddressOf()),
        1,
        0,
        &d3d11Device,
        &m_d3d11DeviceContext,
        nullptr
        ));

    // Query the 11On12 device from the 11 device.
    ThrowIfFailed(d3d11Device.As(&m_d3d11On12Device));
Oproepstroom Parameters
ID3D11Device
D3D11On12CreateDevice

 

Een D2D-factory maken

Nu we een 11On12-apparaat hebben, gebruiken we het om een D2D-fabriek en -apparaat te maken, net zoals het normaal zou worden gedaan met D3D11.

Voeg toe aan de methode LoadAssets.

 // Create D2D/DWrite components.
    {
        D2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;
        ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &m_d2dFactory));
        ComPtr<IDXGIDevice> dxgiDevice;
        ThrowIfFailed(m_d3d11On12Device.As(&dxgiDevice));
        ThrowIfFailed(m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice));
        ThrowIfFailed(m_d2dDevice->CreateDeviceContext(deviceOptions, &m_d2dDeviceContext));
        ThrowIfFailed(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &m_dWriteFactory));
    }
Oproepstroom Parameters
D2D1_DEVICE_CONTEXT_OPTIONS
D2D1CreateFactory D2D1_FACTORY_TYPE
IDXGIDevice
ID2D1Factory3::CreateDevice
ID2D1Device::CreateDeviceContext
DWriteCreateFactory DWRITE_FACTORY_TYPE

 

Een renderdoel maken voor D2D

D3D12 is eigenaar van de swap chain, dus als we naar de backbuffer willen renderen met ons 11On12-apparaat (D2D-inhoud), moeten we ingepakte resources van het type ID3D11Resource maken vanuit de backbuffers van het type ID3D12Resource. Hiermee wordt de ID3D12Resource- gekoppeld aan een D3D11-gebaseerde interface, zodat deze kan worden gebruikt met het 11On12-apparaat. Nadat we een verpakte resource hebben, kunnen we vervolgens een renderdoeloppervlak voor D2D maken om te renderen, ook in de methode LoadAssets.

// Initialize *hwnd* with the handle of the window displaying the rendered content.
HWND hwnd;

// Query the window's dpi settings, which will be used to create
// D2D's render targets.
float dpi = GetDpiForWindow(hwnd);
D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(
    D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
    D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
    dpi,
    dpi);  

// Create frame resources.
{
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());

    // Create a RTV, D2D render target, and a command allocator for each frame.
    for (UINT n = 0; n < FrameCount; n++)
    {
        ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])));
        m_d3d12Device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle);

        // Create a wrapped 11On12 resource of this back buffer. Since we are 
        // rendering all D3D12 content first and then all D2D content, we specify 
        // the In resource state as RENDER_TARGET - because D3D12 will have last 
        // used it in this state - and the Out resource state as PRESENT. When 
        // ReleaseWrappedResources() is called on the 11On12 device, the resource 
        // will be transitioned to the PRESENT state.
        D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
        ThrowIfFailed(m_d3d11On12Device->CreateWrappedResource(
            m_renderTargets[n].Get(),
            &d3d11Flags,
            D3D12_RESOURCE_STATE_RENDER_TARGET,
            D3D12_RESOURCE_STATE_PRESENT,
            IID_PPV_ARGS(&m_wrappedBackBuffers[n])
            ));

        // Create a render target for D2D to draw directly to this back buffer.
        ComPtr<IDXGISurface> surface;
        ThrowIfFailed(m_wrappedBackBuffers[n].As(&surface));
        ThrowIfFailed(m_d2dDeviceContext->CreateBitmapFromDxgiSurface(
            surface.Get(),
            &bitmapProperties,
            &m_d2dRenderTargets[n]
            ));

        rtvHandle.Offset(1, m_rtvDescriptorSize);

        ThrowIfFailed(m_d3d12Device->CreateCommandAllocator(
            D3D12_COMMAND_LIST_TYPE_DIRECT,
            IID_PPV_ARGS(&m_commandAllocators[n])));
    }
}
Oproepstroom Parameters
GetDpiForWindow Een venstergreep
D2D1_BITMAP_PROPERTIES1
BitmapProperties1
[D2D1_BITMAP_OPTIONS](/windows/desktop/api/d2d1_1/ne-d2d1_1-d2d1_bitmap_options)
[PixelFormat](/windows/desktop/api/d2d1helper/nf-d2d1helper-pixelformat)
[DXGI_FORMAT](/windows/desktop/api/dxgiformat/ne-dxgiformat-dxgi_format)
[D2D1_ALPHA_MODE](/windows/desktop/api/dcommon/ne-dcommon-d2d1_alpha_mode)
CD3DX12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandleForHeapStart
IDXGISwapChain::GetBuffer
CreateRenderTargetView-
D3D11_RESOURCE_FLAGS D3D11_BIND_FLAG
CreateWrappedResource D3D12_RESOURCE_STATES
IDXGISurface
ID2D1DeviceContext::CreateBitmapFromDxgiSurface
CreateCommandAllocator- D3D12_COMMAND_LIST_TYPE

 

Eenvoudige D2D-tekstobjecten maken

We hebben nu een ID3D12Device- om 3D-inhoud weer te geven, een ID2D1Device- die wordt gedeeld met onze ID3D12Device via een ID3D11On12Device- - die we kunnen gebruiken om 2D-inhoud weer te geven - en ze zijn beide geconfigureerd om te renderen naar dezelfde swap chain. In dit voorbeeld wordt eenvoudig het D2D-apparaat gebruikt om tekst weer te geven over de 3D-scène, vergelijkbaar met hoe games hun gebruikersinterface weergeven. Hiervoor moeten we enkele eenvoudige D2D-objecten maken, nog steeds in de methode LoadAssets.

 // Create D2D/DWrite objects for rendering text.
    {
        ThrowIfFailed(m_d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_textBrush));
        ThrowIfFailed(m_dWriteFactory->CreateTextFormat(
            L"Verdana",
            NULL,
            DWRITE_FONT_WEIGHT_NORMAL,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            50,
            L"en-us",
            &m_textFormat
            ));
        ThrowIfFailed(m_textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
        ThrowIfFailed(m_textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));
    }
Oproepstroom Parameters
ID2D1RenderTarget::CreateSolidColorBrush ColorF
IDWriteFactory::CreateTextFormat DWRITE_FONT_WEIGHT
IDWriteTextFormat::SetTextAlignment DWRITE_TEXT_ALIGNMENT
IDWriteTextFormat::SetParagraphAlignment DWRITE_PARAGRAPH_ALIGNMENT

 

De hoofdweergavelus bijwerken

Nu de initialisatie van het voorbeeld is voltooid, kunnen we verdergaan met de hoofdweergavelus.

// Render the scene.
void D3D1211on12::OnRender()
{
    // Record all the commands we need to render the scene into the command list.
    PopulateCommandList();

    // Execute the command list.
    ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
    m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);

    RenderUI();

    // Present the frame.
    ThrowIfFailed(m_swapChain->Present(0, 0));

    MoveToNextFrame();
}
Oproepstroom Parameters
ID3D12CommandList
ExecuteCommandLists
IDXGISwapChain1::Present1

 

Het enige wat nieuw is in onze renderlus is de RenderUI--aanroep, die D2D gebruikt om onze gebruikersinterface weer te geven. U ziet dat we al onze D3D12-opdrachtlijsten eerst uitvoeren om onze 3D-scène weer te geven en vervolgens onze gebruikersinterface weer te geven. Voordat we ingaan op RenderUI, moeten we kijken naar een wijziging in PopulateCommandLists. In andere voorbeelden plaatsen we vaak een resource-barrière in de opdrachtlijst voordat we deze sluiten om de backbuffer van de rendertarget-status over te zetten naar de presentatiestatus. In dit voorbeeld verwijderen we echter die resourcebarrière, omdat we nog steeds met D2D naar de achterbuffers moeten renderen. Houd er rekening mee dat toen we onze verpakte resources van de backbuffer creëerden, we de doeltoestand voor weergave als de status 'IN' en de presentatiestatus als de status 'OUT' hadden gespecificeerd.

RenderUI- is redelijk eenvoudig in termen van D2D-gebruik. We stellen ons renderdoel in en geven onze tekst weer. Echter, voordat we verpakte bronnen op een 11On12-apparaat gebruiken, zoals onze backbuffer-renderdoelen, moeten we de AcquireWrappedResources API aanroepen op het 11On12-apparaat. Na het renderen roepen we de --ReleaseWrappedResources---API aan op het 11On12-apparaat. Door ReleaseWrappedResources aan te roepen zorgt ervoor dat er achter de schermen een resourcebarrière optreedt waarmee de opgegeven resource wordt overgezet naar de status "OUT" die tijdens het maken is opgegeven. In ons geval is dit de huidige status. Ten slotte moeten we Flush aanroepen op de ID3D11DeviceContextom al onze opdrachten die op het 11On12-apparaat worden uitgevoerd in te dienen bij de gedeelde ID3D12CommandQueue.

// Render text over D3D12 using D2D via the 11On12 device.
void D3D1211on12::RenderUI()
{
    D2D1_SIZE_F rtSize = m_d2dRenderTargets[m_frameIndex]->GetSize();
    D2D1_RECT_F textRect = D2D1::RectF(0, 0, rtSize.width, rtSize.height);
    static const WCHAR text[] = L"11On12";

    // Acquire our wrapped render target resource for the current back buffer.
    m_d3d11On12Device->AcquireWrappedResources(m_wrappedBackBuffers[m_frameIndex].GetAddressOf(), 1);

    // Render text directly to the back buffer.
    m_d2dDeviceContext->SetTarget(m_d2dRenderTargets[m_frameIndex].Get());
    m_d2dDeviceContext->BeginDraw();
    m_d2dDeviceContext->SetTransform(D2D1::Matrix3x2F::Identity());
    m_d2dDeviceContext->DrawTextW(
        text,
        _countof(text) - 1,
        m_textFormat.Get(),
        &textRect,
        m_textBrush.Get()
        );
    ThrowIfFailed(m_d2dDeviceContext->EndDraw());

    // Release our wrapped render target resource. Releasing 
    // transitions the back buffer resource to the state specified
    // as the OutState when the wrapped resource was created.
    m_d3d11On12Device->ReleaseWrappedResources(m_wrappedBackBuffers[m_frameIndex].GetAddressOf(), 1);

    // Flush to submit the 11 command list to the shared command queue.
    m_d3d11DeviceContext->Flush();
}
Oproepstroom Parameters
D2D1_SIZE_F
D2D1_RECT_F RectF
VerkrijgIngepakteMiddelen
ID2D1DeviceContext::SetTarget
ID2D1RenderTarget::BeginDraw
ID2D1RenderTarget::SetTransform Matrix3x2F
nl-NL: ID2D1RenderTarget::DrawTextW-
ID2D1RenderTarget::EndDraw
ReleaseWrappedResources
ID3D11DeviceContext::Flush

 

Het voorbeeld uitvoeren

de uiteindelijke uitvoer van de 11 op 12

D3D12-code-overzichten

Direct3D 11 op 12

Direct3D 12 Interop

11on12 Referentie