Add directwrite to example.

This commit is contained in:
jmsgrogan 2023-01-04 11:28:29 +00:00
parent 92d1f24613
commit d1ec8b4f68
5 changed files with 235 additions and 21 deletions

View file

@ -10,6 +10,13 @@
#include <d3dcompiler.h>
#include <d3d12sdklayers.h>
#include <d3d11.h>
#include <d3d11on12.h>
#include <d2d1_3.h>
#include <d2d1_1.h>
#include <dwrite.h>
Win32DxWindowInterface::Win32DxWindowInterface(Win32DxInterface* dxInterface)
: mDxInterface(dxInterface)
{
@ -35,7 +42,9 @@ void Win32DxWindowInterface::onRender()
// Execute the command list.
ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() };
mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
mDxInterface->getCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
renderD2d();
// Present the frame.
mSwapChain->Present(1, 0);
@ -75,8 +84,8 @@ void Win32DxWindowInterface::populateCommandList()
mCommandList->DrawInstanced(3, 1, 0, 0);
// Indicate that the back buffer will now be used to present.
barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
mCommandList->ResourceBarrier(1, &barrier);
//barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
//mCommandList->ResourceBarrier(1, &barrier);
mCommandList->Close();
}
@ -102,12 +111,6 @@ bool Win32DxWindowInterface::initialize(mt::Window* window)
void Win32DxWindowInterface::loadPipeline(mt::Window* window)
{
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
mDxInterface->getDevice()->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.BufferCount = FrameCount;
@ -125,7 +128,7 @@ void Win32DxWindowInterface::loadPipeline(mt::Window* window)
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
mDxInterface->getFactory()->CreateSwapChainForHwnd(
mCommandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it.
mDxInterface->getCommandQueue(),
hwnd,
&swapChainDesc,
nullptr,
@ -136,6 +139,19 @@ void Win32DxWindowInterface::loadPipeline(mt::Window* window)
swapChain.As(&mSwapChain);
auto mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
// Query the desktop's dpi settings, which will be used to create
// D2D's render targets.
float dpiX{ 0.0 };
float dpiY{ 0.0 };
mDxInterface->getD2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX,
dpiY
);
// Create descriptor heaps.
{
// Describe and create a render target view (RTV) descriptor heap.
@ -157,6 +173,25 @@ void Win32DxWindowInterface::loadPipeline(mt::Window* window)
{
mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargets[n]));
mDxInterface->getDevice()->CreateRenderTargetView(mRenderTargets[n].Get(), nullptr, rtvHandle);
D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
mDxInterface->get11On12Device()->CreateWrappedResource(
mRenderTargets[n].Get(),
&d3d11Flags,
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT,
IID_PPV_ARGS(&mWrappedBackBuffers[n])
);
// Create a render target for D2D to draw directly to this back buffer.
Microsoft::WRL::ComPtr<IDXGISurface> surface;
mWrappedBackBuffers[n].As(&surface);
mDxInterface->getD2dContext()->CreateBitmapFromDxgiSurface(
surface.Get(),
&bitmapProperties,
&mD2dRenderTargets[n]
);
rtvHandle.Offset(1, mRtvDescriptorSize);
}
}
@ -223,6 +258,24 @@ void Win32DxWindowInterface::loadAssets()
// Create the command list.
mDxInterface->getDevice()->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), mPipelineState.Get(), IID_PPV_ARGS(&mCommandList));
// Create D2D/DWrite objects for rendering text.
{
mDxInterface->getD2dContext()->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &mTextBrush);
mDxInterface->getDirectWriteFactory()->CreateTextFormat(
L"Verdana",
NULL,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
50,
L"en-us",
&mTextFormat
);
mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
}
// Command lists are created in the recording state, but there is nothing
// to record yet. The main loop expects it to be closed, so close it now.
mCommandList->Close();
@ -286,11 +339,42 @@ void Win32DxWindowInterface::loadAssets()
}
}
void Win32DxWindowInterface::renderD2d()
{
D2D1_SIZE_F rtSize = mD2dRenderTargets[mFrameIndex]->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.
mDxInterface->get11On12Device()->AcquireWrappedResources(mWrappedBackBuffers[mFrameIndex].GetAddressOf(), 1);
// Render text directly to the back buffer.
mDxInterface->getD2dContext()->SetTarget(mD2dRenderTargets[mFrameIndex].Get());
mDxInterface->getD2dContext()->BeginDraw();
mDxInterface->getD2dContext()->SetTransform(D2D1::Matrix3x2F::Identity());
mDxInterface->getD2dContext()->DrawText(
text,
_countof(text) - 1,
mTextFormat.Get(),
&textRect,
mTextBrush.Get()
);
mDxInterface->getD2dContext()->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.
mDxInterface->get11On12Device()->ReleaseWrappedResources(mWrappedBackBuffers[mFrameIndex].GetAddressOf(), 1);
// Flush to submit the 11 command list to the shared command queue.
mDxInterface->getD3d11DeviceContext()->Flush();
}
void Win32DxWindowInterface::waitForPreviousFrame()
{
// Signal and increment the fence value.
const UINT64 fence = mFenceValue;
mCommandQueue->Signal(mFence.Get(), fence);
mDxInterface->getCommandQueue()->Signal(mFence.Get(), fence);
mFenceValue++;
// Wait until the previous frame is finished.