Aracılığıyla paylaş


D3D11on12 kullanılarak D2D

D3D1211on12 örneği, 11 tabanlı bir cihaz ile 12 tabanlı bir cihaz arasında kaynakları paylaşarak D3D12 içeriği üzerine D2D içeriğinin nasıl işleneceğini gösterir.

ID3D11On12Device oluşturma

İlk adım, ID3D12Deviceoluşturulduktan sonra id3D11On12Deviceoluşturmaktır. D3D11On12CreateDeviceAPIaracılığıyla ID3D12Device çevresinde sarmalanmış bir ID3D11Device oluşturmayı içerir. Bu API ayrıca diğer parametrelerin yanı sıra, 11On12 cihazının komutlarını gönderebilmesi için ID3D12CommandQueue alır. ID3D11Device oluşturulduktan sonra, ID3D11On12Device arabirimini ondan sorgulayabilirsiniz. Bu, D2D'yi ayarlamak için kullanılacak birincil cihaz nesnesidir.

LoadPipeline yönteminde cihazları ayarlayın.

 // 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));
Çağrı akışı Parametreler
ID3D11Device
D3D11On12CreateDevice

 

D2D fabrikası oluşturma

Artık bir 11On12 cihazımız olduğuna göre, normalde D3D11 ile yapıldığı gibi bir D2D fabrikası ve cihazı oluşturmak için bu cihazı kullanıyoruz.

LoadAssets yöntemine ekleyin.

 // 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));
    }
Çağrı akışı Parametreler
D2D1_DEVICE_CONTEXT_OPTIONS
D2D1CreateFactory D2D1_FACTORY_TYPE
IDXGIDevice
ID2D1Factory3::CreateDevice
ID2D1Device::CreateDeviceContext
DWriteCreateFactory DWRITE_FACTORY_TYPE

 

D2D için bir işleme hedefi oluştur

D3D12, değiştirme zincirinin sahibidir, bu nedenle 11On12 cihazımızı (D2D içeriği) kullanarak arka arabellekte işleme yapmak istiyorsak, ID3D12Resourcetüründeki arka arabelleklerden ID3D11Resource türünde sarmalanmış kaynaklar oluşturmamız gerekir. Bu, ID3D12Resource D3D11 tabanlı bir arabirimle ilişkilendirir ve böylece 11On12 cihazıyla kullanılabilir. Sarmalanmış bir kaynağımız olduktan sonra, LoadAssets yönteminde D2D'nin üzerine işlem yapacağı bir hedef yüzey de oluşturabiliriz.

// 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])));
    }
}
Çağrı akışı Parametreler
GetDpiForWindow Pencere tutamacı
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
Komut Ayırıcı Oluştur D3D12_COMMAND_LIST_TYPE

 

Temel D2D metin nesneleri oluşturma

Artık 3B içeriği render etmek için bir ID3D12Device'imiz ve 12 cihazımızla bir ID3D11On12Device aracılığıyla paylaşılan bir ID2D1Device'imiz (bu cihazı 2B içeriği render etmek için kullanabiliriz) var ve her ikisi de aynı takas zincirine render etmek üzere yapılandırılmıştır. Bu örnek, oyunların kullanıcı arabirimini işleme şekline benzer şekilde 3B sahne üzerinde metin işlemek için D2D cihazını kullanır. Bunun için, hala LoadAssets yönteminde bazı temel D2D nesneleri oluşturmamız gerekir.

 // 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));
    }
Çağrı akışı Parametreler
ID2D1RenderTarget::CreateSolidColorBrush ColorF
IDWriteFactory::CreateTextFormat DWRITE_FONT_WEIGHT
IDWriteTextFormat::SetTextAlignment DWRITE_TEXT_ALIGNMENT
IDWriteTextFormat::SetParagraphAlignment DWRITE_PARAGRAPH_ALIGNMENT

 

Ana işleme döngüsünü güncelleştirme

Örneği başlatma işlemi tamamlandıktan sonra ana işleme döngüsüne geçebiliriz.

// 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();
}
Çağrı akışı Parametreler
ID3D12CommandList
ExecuteCommandLists
IDXGISwapChain1::Present1

 

İşleme döngümüzde yeni olan tek şey, kullanıcı arabirimimizi işlemek için D2D kullanacak olan RenderUI çağrısıdır. 3B sahnemizi işlemek için önce tüm D3D12 komut listelerimizi yürüttüğümüze ve ardından kullanıcı arabirimimizi bunun üzerine işlediğimize dikkat edin. RenderUIgeçmeden önce, PopulateCommandListsbir değişikliğe bakmamız gerekiyor. Diğer örneklerde, komut listesini kapatmadan önce, arka tamponu işlem hedefi durumundan sunum durumuna geçirmek için genellikle bir kaynak engeli koyarız. Ancak, bu örnekte bu kaynak engelini kaldırıyoruz, çünkü yine de D2D kullanarak arka arabelleklere işlememiz gerekiyor. Geri arabelleğinde sarmalanan kaynaklarımızı oluşturduğumuzda, işleme hedef durumunu "IN" durumu ve mevcut durumu "OUT" durumu olarak belirttiğimizi unutmayın.

RenderUI, D2D kullanımı açısından oldukça kolay anlaşılır bir özelliktir. İşleme hedefimizi ayarlar ve metnimizi işleriz. Ancak, arka arabellek işleme hedeflerimiz gibi sarmalanmış kaynakları kullanmadan önce, öncelikle AcquireWrappedResources API'sini 11On12 cihazında çağırmamız gerekir. İşlemeden sonra 11On12 cihazında ReleaseWrappedResources API'sini çağırırız. ReleaseWrappedResources çağrısı yaparak perde arkasında, belirtilmiş kaynağı oluşturma anında belirtilen "OUT" durumuna geçirecek bir engel oluştururuz. Bizim durumumuzda, bu mevcut durumdur. Son olarak, 11On12 cihazında gerçekleştirilen tüm komutlarımızı paylaşılan ID3D12CommandQueuegöndermek için ID3D11DeviceContextüzerinde Flush çalıştırmalıyız.

// 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();
}
Çağrı akışı Parametreler
D2D1_SIZE_F
D2D1_RECT_F RectF
AcquireWrappedResources
ID2D1DeviceContext::SetTarget
ID2D1RenderTarget::BeginDraw
ID2D1RenderTarget::SetTransform Matrix3x2F
ID2D1RenderTarget::DrawTextW
ID2D1RenderTarget::EndDraw
ReleaseWrappedResources
ID3D11DeviceContext::Flush

 

Örneği çalıştırma

11 üzerinde 12 numuneden son çıkış

D3D12 Kod kılavuzu

12 üzerinde Direct3D 11'i

Direct3D 12 Birlikte Çalışma

11on12 Başvuru