Add directwrite to example.
This commit is contained in:
parent
92d1f24613
commit
d1ec8b4f68
5 changed files with 235 additions and 21 deletions
|
@ -64,7 +64,7 @@ else()
|
|||
ui_interfaces/win32/Win32DxWindowInterface.cpp
|
||||
)
|
||||
|
||||
list(APPEND platform_LIBS D3D12.lib D3DCompiler.lib DXGI.lib)
|
||||
list(APPEND platform_LIBS D3D12.lib D3DCompiler.lib DXGI.lib Dwrite.lib D2d1.lib D3D11.lib)
|
||||
|
||||
find_package(DirectX-Headers REQUIRED)
|
||||
list(APPEND platform_LIBS Microsoft::DirectX-Headers)
|
||||
|
|
|
@ -7,9 +7,16 @@
|
|||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3d11on12.h>
|
||||
#include <d3d12.h>
|
||||
#include <d3d12sdklayers.h>
|
||||
|
||||
#include <d2d1_3.h>
|
||||
#include <d2d1_1.h>
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
@ -38,16 +45,51 @@ void Win32DxInterface::getHardwareAdapter(IDXGIAdapter1** ppAdapter)
|
|||
}
|
||||
}
|
||||
|
||||
bool Win32DxInterface::isValid() const
|
||||
{
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
ID3D12Device* Win32DxInterface::getDevice() const
|
||||
{
|
||||
return mDevice.Get();
|
||||
}
|
||||
|
||||
ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
||||
{
|
||||
return mD3d11On12Device.Get();
|
||||
}
|
||||
|
||||
IDXGIFactory7* Win32DxInterface::getFactory() const
|
||||
{
|
||||
return mFactory.Get();
|
||||
}
|
||||
|
||||
ID2D1Factory3* Win32DxInterface::getD2dFactory() const
|
||||
{
|
||||
return mD2dFactory.Get();
|
||||
}
|
||||
|
||||
IDWriteFactory* Win32DxInterface::getDirectWriteFactory() const
|
||||
{
|
||||
return mDWriteFactory.Get();
|
||||
}
|
||||
|
||||
ID2D1DeviceContext2* Win32DxInterface::getD2dContext() const
|
||||
{
|
||||
return mD2dDeviceContext.Get();
|
||||
}
|
||||
|
||||
ID3D12CommandQueue* Win32DxInterface::getCommandQueue() const
|
||||
{
|
||||
return mCommandQueue.Get();
|
||||
}
|
||||
|
||||
ID3D11DeviceContext* Win32DxInterface::getD3d11DeviceContext() const
|
||||
{
|
||||
return mD3d11DeviceContext.Get();
|
||||
}
|
||||
|
||||
void Win32DxInterface::initialize()
|
||||
{
|
||||
if (!DirectX::XMVerifyCPUSupport())
|
||||
|
@ -66,10 +108,6 @@ void Win32DxInterface::initialize()
|
|||
#endif
|
||||
|
||||
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory7), (void**)(&mFactory));
|
||||
if (hr == S_OK)
|
||||
{
|
||||
MLOG_INFO("FACTORY IS OK");
|
||||
}
|
||||
|
||||
IDXGIAdapter1* pAdapter{ nullptr };
|
||||
getHardwareAdapter(&pAdapter);
|
||||
|
@ -87,5 +125,50 @@ void Win32DxInterface::initialize()
|
|||
MLOG_INFO("No adapter found");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
|
||||
mDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
|
||||
|
||||
mIsValid = initializeD2d();
|
||||
}
|
||||
|
||||
bool Win32DxInterface::initializeD2d()
|
||||
{
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> d3d11Device;
|
||||
UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
D3D11On12CreateDevice(
|
||||
mDevice.Get(),
|
||||
d3d11DeviceFlags,
|
||||
nullptr,
|
||||
0,
|
||||
reinterpret_cast<IUnknown**>(mCommandQueue.GetAddressOf()),
|
||||
1,
|
||||
0,
|
||||
&d3d11Device,
|
||||
&mD3d11DeviceContext,
|
||||
nullptr
|
||||
);
|
||||
|
||||
d3d11Device.As(&mD3d11On12Device);
|
||||
|
||||
// Create D2D/DWrite components.
|
||||
{
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE;
|
||||
D2D1_FACTORY_OPTIONS d2dFactoryOptions = {};
|
||||
|
||||
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &mD2dFactory);
|
||||
Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
|
||||
mD3d11On12Device.As(&dxgiDevice);
|
||||
|
||||
mD2dFactory->CreateDevice(dxgiDevice.Get(), &mD2dDevice);
|
||||
|
||||
mD2dDevice->CreateDeviceContext(deviceOptions, &mD2dDeviceContext);
|
||||
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,24 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <wrl.h>
|
||||
#include <dwrite.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <d3d11on12.h>
|
||||
|
||||
struct ID3D12Device;
|
||||
struct IDXGIFactory7;
|
||||
struct IDXGIAdapter1;
|
||||
struct ID3D12CommandQueue;
|
||||
|
||||
struct ID3D11DeviceContext;
|
||||
struct ID3D11On12Device;
|
||||
|
||||
struct IDWriteFactory;
|
||||
struct ID2D1Factory3;
|
||||
struct ID2D1Device2;
|
||||
struct ID2D1DeviceContext2;
|
||||
|
||||
class Win32DxInterface
|
||||
{
|
||||
public:
|
||||
ID3D12Device* getDevice() const;
|
||||
ID3D11On12Device* get11On12Device() const;
|
||||
ID3D11DeviceContext* getD3d11DeviceContext() const;
|
||||
|
||||
IDXGIFactory7* getFactory() const;
|
||||
|
||||
ID2D1Factory3* getD2dFactory() const;
|
||||
ID2D1DeviceContext2* getD2dContext() const;
|
||||
|
||||
ID3D12CommandQueue* getCommandQueue() const;
|
||||
|
||||
IDWriteFactory* getDirectWriteFactory() const;
|
||||
|
||||
void initialize();
|
||||
|
||||
ID3D12Device* getDevice() const;
|
||||
|
||||
IDXGIFactory7* getFactory() const;
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
void getHardwareAdapter(IDXGIAdapter1** ppAdapter);
|
||||
|
||||
bool initializeD2d();
|
||||
|
||||
bool mIsValid{ false };
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory7> mFactory;
|
||||
Microsoft::WRL::ComPtr<ID3D12Device> mDevice;
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3d11DeviceContext;
|
||||
Microsoft::WRL::ComPtr<ID3D11On12Device> mD3d11On12Device;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID2D1Factory3> mD2dFactory;
|
||||
Microsoft::WRL::ComPtr<ID2D1Device2> mD2dDevice;
|
||||
Microsoft::WRL::ComPtr<ID2D1DeviceContext2> mD2dDeviceContext;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory> mDWriteFactory;
|
||||
};
|
|
@ -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.
|
||||
|
|
|
@ -23,6 +23,11 @@ struct ID3D12Fence;
|
|||
struct ID3D12RootSignature;
|
||||
struct ID3D12PipelineState;
|
||||
|
||||
struct ID3D11Resource;
|
||||
struct ID2D1Bitmap1;
|
||||
struct ID2D1SolidColorBrush;
|
||||
struct IDWriteTextFormat;
|
||||
|
||||
class Win32DxWindowInterface
|
||||
{
|
||||
public:
|
||||
|
@ -46,6 +51,8 @@ private:
|
|||
void waitForPreviousFrame();
|
||||
void destroyWindow();
|
||||
|
||||
void renderD2d();
|
||||
|
||||
static const UINT FrameCount = 2;
|
||||
Win32DxInterface* mDxInterface{ nullptr };
|
||||
bool mInitialized{ false };
|
||||
|
@ -59,7 +66,6 @@ private:
|
|||
CD3DX12_VIEWPORT mViewport;
|
||||
CD3DX12_RECT mScissorRect;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mCommandAllocator;
|
||||
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;
|
||||
|
||||
|
@ -72,6 +78,11 @@ private:
|
|||
UINT mRtvDescriptorSize{ 0 };
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12Resource> mRenderTargets[FrameCount];
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> mWrappedBackBuffers[FrameCount];
|
||||
Microsoft::WRL::ComPtr<ID2D1Bitmap1> mD2dRenderTargets[FrameCount];
|
||||
|
||||
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mTextBrush;
|
||||
Microsoft::WRL::ComPtr<IDWriteTextFormat> mTextFormat;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12Resource> mVertexBuffer;
|
||||
D3D12_VERTEX_BUFFER_VIEW mVertexBufferView{};
|
||||
|
|
Loading…
Reference in a new issue