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
- Bir D2D fabrika nesnesi oluşturun
- D2D için işleme hedefi oluşturma
- Temel D2D metin nesneleri oluşturma
- ana işleme döngüsünü güncelleştirme
- Örneği çalıştır
- İlgili konular
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));
}
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 |
[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));
}
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();
}
Örneği çalıştırma
11 üzerinde 12 numuneden son çıkış
İlgili konular