Some directx cleaning.
This commit is contained in:
parent
850bd6906f
commit
55ed0e9299
19 changed files with 900 additions and 487 deletions
|
@ -21,7 +21,6 @@
|
|||
#include "File.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <directx/d3dx12.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -62,7 +61,7 @@ void DirectXPainter::paint()
|
|||
{
|
||||
}
|
||||
|
||||
void DirectXPainter::paintBackground(const CD3DX12_CPU_DESCRIPTOR_HANDLE& rtvHandle, ID3D12GraphicsCommandList* commandList)
|
||||
void DirectXPainter::paintBackground(const D3D12_CPU_DESCRIPTOR_HANDLE& rtvHandle, ID3D12GraphicsCommandList* commandList)
|
||||
{
|
||||
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
|
||||
commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||
|
|
|
@ -13,8 +13,6 @@ class DrawingContext;
|
|||
class DirectXMeshPainter;
|
||||
class DirectXTextPainter;
|
||||
|
||||
struct CD3DX12_CPU_DESCRIPTOR_HANDLE;
|
||||
|
||||
class DirectXPainter : public AbstractPainter
|
||||
{
|
||||
public:
|
||||
|
@ -28,7 +26,7 @@ public:
|
|||
|
||||
void initializeText(ID2D1DeviceContext2* d2dContext, IDWriteFactory* directWriteFactory);
|
||||
|
||||
void paintBackground(const CD3DX12_CPU_DESCRIPTOR_HANDLE& rtvHandle, ID3D12GraphicsCommandList* commandList);
|
||||
void paintBackground(const D3D12_CPU_DESCRIPTOR_HANDLE& rtvHandle, ID3D12GraphicsCommandList* commandList);
|
||||
|
||||
void paintMesh(ID3D12GraphicsCommandList* commandList);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void DirectXTextPainter::updateTextFormat(IDWriteFactory* directWriteFactory, un
|
|||
void DirectXTextPainter::paint(SceneText* text, DrawingContext* context, ID2D1DeviceContext2* d2dContext, IDWriteFactory* directWriteFactory)
|
||||
{
|
||||
const auto location = text->getTransform().getLocation();
|
||||
D2D1_RECT_F textRect = D2D1::RectF(location.getX(), location.getY(), location.getX() + 100, location.getY() + 100);
|
||||
D2D1_RECT_F textRect = D2D1::RectF(location.getX(), location.getY(), location.getX() + 200, location.getY() + 100);
|
||||
|
||||
updateTextFormat(directWriteFactory, text->getTextData().mFont.getSize());
|
||||
|
||||
|
|
|
@ -58,10 +58,18 @@ else()
|
|||
ui_interfaces/win32/Win32WindowInterface.cpp
|
||||
ui_interfaces/win32/Win32Window.h
|
||||
ui_interfaces/win32/Win32Window.cpp
|
||||
ui_interfaces/win32/Win32DxInterface.h
|
||||
ui_interfaces/win32/Win32DxInterface.cpp
|
||||
ui_interfaces/win32/Win32DxWindowInterface.h
|
||||
ui_interfaces/win32/Win32DxWindowInterface.cpp
|
||||
ui_interfaces/win32/directx/Win32DxInterface.h
|
||||
ui_interfaces/win32/directx/Win32DxInterface.cpp
|
||||
ui_interfaces/win32/directx/Win32DxWindowInterface.h
|
||||
ui_interfaces/win32/directx/Win32DxWindowInterface.cpp
|
||||
ui_interfaces/win32/directx/DirectXDescriptors.h
|
||||
ui_interfaces/win32/directx/DirectXDescriptors.cpp
|
||||
ui_interfaces/win32/directx/DirectX2dIntegration.h
|
||||
ui_interfaces/win32/directx/DirectX2dIntegration.cpp
|
||||
ui_interfaces/win32/directx/DirectXBuffers.h
|
||||
ui_interfaces/win32/directx/DirectXBuffers.cpp
|
||||
ui_interfaces/win32/directx/DirectXCommandList.h
|
||||
ui_interfaces/win32/directx/DirectXCommandList.cpp
|
||||
)
|
||||
|
||||
list(APPEND platform_LIBS D3D12.lib D3DCompiler.lib DXGI.lib Dwrite.lib D2d1.lib D3D11.lib)
|
||||
|
@ -81,12 +89,13 @@ list(APPEND windows_LIB_INCLUDES
|
|||
add_library(windows SHARED ${windows_LIB_INCLUDES} ${platform_INCLUDES})
|
||||
|
||||
target_include_directories(windows PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/managers"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/managers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32/directx
|
||||
${WAYLAND_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIRS}
|
||||
)
|
||||
|
|
|
@ -1,320 +0,0 @@
|
|||
#include "Win32DxWindowInterface.h"
|
||||
|
||||
#include "Win32DxInterface.h"
|
||||
#include "Win32Window.h"
|
||||
#include "Window.h"
|
||||
#include "Widget.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include "DrawingContext.h"
|
||||
#include "DirectXPainter.h"
|
||||
#include "DirectXMeshPainter.h"
|
||||
#include "DirectXTextPainter.h"
|
||||
#include "DirectXShaderProgram.h"
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <d3d12sdklayers.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d3d11on12.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <d2d1_1.h>
|
||||
#include <D3Dcommon.h>
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
Win32DxWindowInterface::Win32DxWindowInterface(mt::Window* window, Win32DxInterface* dxInterface)
|
||||
: mWindow(window),
|
||||
mDxInterface(dxInterface)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Win32DxWindowInterface::~Win32DxWindowInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::destroyWindow()
|
||||
{
|
||||
waitForPreviousFrame();
|
||||
|
||||
::CloseHandle(mFenceEvent);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::onRender()
|
||||
{
|
||||
if (!mIsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Record all the commands we need to render the scene into the command list.
|
||||
populateCommandList();
|
||||
|
||||
// Execute the command list.
|
||||
ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() };
|
||||
mDxInterface->getCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
||||
|
||||
renderD2d();
|
||||
|
||||
// Present the frame.
|
||||
mSwapChain->Present(1, 0);
|
||||
|
||||
waitForPreviousFrame();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::populateCommandList()
|
||||
{
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
|
||||
// Command list allocators can only be reset when the associated
|
||||
// command lists have finished execution on the GPU; apps should use
|
||||
// fences to determine GPU execution progress.
|
||||
mCommandAllocator->Reset();
|
||||
|
||||
// However, when ExecuteCommandList() is called on a particular command
|
||||
// list, that command list can then be reset at any time and must be before
|
||||
// re-recording.
|
||||
mCommandList->Reset(mCommandAllocator.Get(), painter->getMeshPainter()->getPipelineState());
|
||||
|
||||
// Set necessary state.
|
||||
mCommandList->SetGraphicsRootSignature(painter->getMeshPainter()->getRootSignature());
|
||||
mCommandList->RSSetViewports(1, &mViewport);
|
||||
mCommandList->RSSetScissorRects(1, &mScissorRect);
|
||||
|
||||
// Indicate that the back buffer will be used as a render target.
|
||||
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
mCommandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart(), static_cast<INT>(mFrameIndex), mRtvDescriptorSize);
|
||||
mCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
||||
|
||||
painter->paintBackground(rtvHandle, mCommandList.Get());
|
||||
painter->paintMesh(mCommandList.Get());
|
||||
|
||||
// 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);
|
||||
|
||||
mCommandList->Close();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::renderD2d()
|
||||
{
|
||||
// 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());
|
||||
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
painter->paintText(mDxInterface->getD2dContext(), mDxInterface->getDirectWriteFactory());
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::initialize()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
mInitialized = true;
|
||||
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
mViewport = CD3DX12_VIEWPORT(0.0f, 0.0f, static_cast<float>(width), static_cast<float>(height));
|
||||
mScissorRect = CD3DX12_RECT(0, 0, width, height);
|
||||
|
||||
if (!loadPipeline())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!loadAssets())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mIsValid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::loadPipeline()
|
||||
{
|
||||
if (!setupSwapChain())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
setupDescriptorHeaps();
|
||||
|
||||
setupFrameResources();
|
||||
|
||||
mDxInterface->getDevice()->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocator));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::setupSwapChain()
|
||||
{
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
const auto hwnd = dynamic_cast<Win32Window*>(mWindow->getPlatformWindow())->getHandle();
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = FrameCount;
|
||||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
auto command_queue = mDxInterface->getCommandQueue();
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
|
||||
const auto hr = mDxInterface->getFactory()->CreateSwapChainForHwnd(command_queue, hwnd, &swapChainDesc, nullptr, nullptr, &swapChain);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
MLOG_ERROR("Failed to create swap chain for hwnd: " << hwnd);
|
||||
return false;
|
||||
}
|
||||
swapChain.As(&mSwapChain);
|
||||
|
||||
// Prevent fullscreen toggle
|
||||
mDxInterface->getFactory()->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
|
||||
// Update index for backbuffer
|
||||
mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::setupDescriptorHeaps()
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
|
||||
rtvHeapDesc.NumDescriptors = FrameCount;
|
||||
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
mDxInterface->getDevice()->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&mRtvHeap));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
|
||||
srvHeapDesc.NumDescriptors = 1;
|
||||
srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
mDxInterface->getDevice()->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvHeap));
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {};
|
||||
cbvHeapDesc.NumDescriptors = 1;
|
||||
cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
mDxInterface->getDevice()->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&mCbvHeap));
|
||||
|
||||
mRtvDescriptorSize = mDxInterface->getDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::setupFrameResources()
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
for (UINT n = 0; n < FrameCount; n++)
|
||||
{
|
||||
setupFrameResource(n, rtvHandle, bitmapProperties);
|
||||
}
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::setupFrameResource(UINT idx, CD3DX12_CPU_DESCRIPTOR_HANDLE& descriptorHandle, const D2D1_BITMAP_PROPERTIES1& bitmapProps)
|
||||
{
|
||||
mSwapChain->GetBuffer(idx, IID_PPV_ARGS(&mRenderTargets[idx]));
|
||||
mDxInterface->getDevice()->CreateRenderTargetView(mRenderTargets[idx].Get(), nullptr, descriptorHandle);
|
||||
|
||||
setupFrameD2DResource(idx, bitmapProps);
|
||||
|
||||
descriptorHandle.Offset(1, mRtvDescriptorSize);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::setupFrameD2DResource(UINT idx, const D2D1_BITMAP_PROPERTIES1& bitmapProps)
|
||||
{
|
||||
D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
|
||||
mDxInterface->get11On12Device()->CreateWrappedResource(mRenderTargets[idx].Get(),&d3d11Flags,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&mWrappedBackBuffers[idx]));
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISurface> surface;
|
||||
mWrappedBackBuffers[idx].As(&surface);
|
||||
mDxInterface->getD2dContext()->CreateBitmapFromDxgiSurface(surface.Get(), &bitmapProps, &mD2dRenderTargets[idx]);
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::loadAssets()
|
||||
{
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
|
||||
painter->initializeMesh(mDxInterface->getDevice());
|
||||
|
||||
// Create the command list.
|
||||
mDxInterface->getDevice()->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(),
|
||||
painter->getMeshPainter()->getPipelineState(), IID_PPV_ARGS(&mCommandList));
|
||||
|
||||
// Create D2D/DWrite objects for rendering text.
|
||||
painter->initializeText(mDxInterface->getD2dContext(), mDxInterface->getDirectWriteFactory());
|
||||
|
||||
// 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();
|
||||
|
||||
painter->updateMesh(mDxInterface->getDevice());
|
||||
|
||||
createSyncObjects();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::createSyncObjects()
|
||||
{
|
||||
mDxInterface->getDevice()->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence));
|
||||
mFenceValue = 1;
|
||||
|
||||
// Create an event handle to use for frame synchronization.
|
||||
mFenceEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (mFenceEvent == nullptr)
|
||||
{
|
||||
//ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
// Wait for the command list to execute; we are reusing the same command
|
||||
// list in our main loop but for now, we just want to wait for setup to
|
||||
// complete before continuing.
|
||||
waitForPreviousFrame();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::waitForPreviousFrame()
|
||||
{
|
||||
// Signal and increment the fence value.
|
||||
const UINT64 fence = mFenceValue;
|
||||
mDxInterface->getCommandQueue()->Signal(mFence.Get(), fence);
|
||||
mFenceValue++;
|
||||
|
||||
// Wait until the previous frame is finished.
|
||||
if (mFence->GetCompletedValue() < fence)
|
||||
{
|
||||
mFence->SetEventOnCompletion(fence, mFenceEvent);
|
||||
::WaitForSingleObject(mFenceEvent, INFINITE);
|
||||
}
|
||||
mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
#include <directx/d3dx12.h>
|
||||
|
||||
class Win32DxInterface;
|
||||
namespace mt
|
||||
{
|
||||
class Window;
|
||||
}
|
||||
|
||||
struct ID3D12CommandQueue;
|
||||
struct ID3D12CommandAllocator;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct IDXGISwapChain4;
|
||||
struct ID3D12DescriptorHeap;
|
||||
struct ID3D12Resource;
|
||||
struct ID3D12Fence;
|
||||
struct ID3D12RootSignature;
|
||||
struct ID3D12PipelineState;
|
||||
|
||||
struct ID3D11Resource;
|
||||
struct ID2D1Bitmap1;
|
||||
struct D2D1_BITMAP_PROPERTIES1;
|
||||
struct CD3DX12_CPU_DESCRIPTOR_HANDLE;
|
||||
|
||||
class Win32DxWindowInterface
|
||||
{
|
||||
public:
|
||||
Win32DxWindowInterface(mt::Window* window, Win32DxInterface* dxInterface);
|
||||
|
||||
~Win32DxWindowInterface();
|
||||
|
||||
bool initialize();
|
||||
|
||||
void onRender();
|
||||
|
||||
private:
|
||||
bool loadPipeline();
|
||||
bool loadAssets();
|
||||
|
||||
void populateCommandList();
|
||||
void waitForPreviousFrame();
|
||||
void destroyWindow();
|
||||
|
||||
void renderD2d();
|
||||
|
||||
bool setupSwapChain();
|
||||
void setupDescriptorHeaps();
|
||||
|
||||
void setupFrameResources();
|
||||
void setupFrameResource(UINT idx, CD3DX12_CPU_DESCRIPTOR_HANDLE& descriptorHandle, const D2D1_BITMAP_PROPERTIES1& bitmapProps);
|
||||
void setupFrameD2DResource(UINT idx, const D2D1_BITMAP_PROPERTIES1& bitmapProps);
|
||||
|
||||
void createSyncObjects();
|
||||
|
||||
static const UINT FrameCount = 2;
|
||||
Win32DxInterface* mDxInterface{ nullptr };
|
||||
bool mInitialized{ false };
|
||||
bool mIsValid{ false };
|
||||
|
||||
mt::Window* mWindow{ nullptr };
|
||||
CD3DX12_VIEWPORT mViewport;
|
||||
CD3DX12_RECT mScissorRect;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mCommandAllocator;
|
||||
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain4> mSwapChain;
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mSrvHeap;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mCbvHeap;
|
||||
UINT mRtvDescriptorSize{ 0 };
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12Resource> mRenderTargets[FrameCount];
|
||||
Microsoft::WRL::ComPtr<ID3D11Resource> mWrappedBackBuffers[FrameCount];
|
||||
Microsoft::WRL::ComPtr<ID2D1Bitmap1> mD2dRenderTargets[FrameCount];
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12Fence> mFence;
|
||||
uint64_t mFenceValue = 0;
|
||||
uint64_t mFrameFenceValues[FrameCount] = {};
|
||||
HANDLE mFenceEvent{};
|
||||
|
||||
uint64_t mFrameIndex{ 0 };
|
||||
};
|
||||
|
||||
using XcbGlWindowInterfacePtr = std::unique_ptr<Win32DxWindowInterface>;
|
|
@ -39,6 +39,11 @@ void Win32UIInterface::loop()
|
|||
MSG msg = { };
|
||||
while (::GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
#include "DirectX2dIntegration.h"
|
||||
|
||||
#include "Window.h"
|
||||
#include "Widget.h"
|
||||
#include "DirectXPainter.h"
|
||||
#include "DrawingContext.h"
|
||||
|
||||
#include "Win32DxInterface.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d3d11on12.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <d2d1_1.h>
|
||||
|
||||
DirectX2dIntegration::DirectX2dIntegration(mt::Window* window, Win32DxInterface* dxInterface, UINT frameCount)
|
||||
: mDxInterface(dxInterface),
|
||||
mWindow(window),
|
||||
mFrameCount(frameCount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ID3D11Resource* const* DirectX2dIntegration::getD11on12WrappedBackBuffer() const
|
||||
{
|
||||
return mWrappedBackBuffers[mFrameIndex].GetAddressOf();
|
||||
}
|
||||
|
||||
ID2D1Bitmap1* DirectX2dIntegration::getD2dRenderTarget() const
|
||||
{
|
||||
return mD2dRenderTargets[mFrameIndex].Get();
|
||||
}
|
||||
|
||||
void DirectX2dIntegration::render()
|
||||
{
|
||||
// Acquire our wrapped render target resource for the current back buffer.
|
||||
mDxInterface->get11On12Device()->AcquireWrappedResources(getD11on12WrappedBackBuffer(), 1);
|
||||
|
||||
// Render text directly to the back buffer.
|
||||
mDxInterface->getD2dContext()->SetTarget(getD2dRenderTarget());
|
||||
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
painter->paintText(mDxInterface->getD2dContext(), mDxInterface->getDirectWriteFactory());
|
||||
|
||||
// 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(getD11on12WrappedBackBuffer(), 1);
|
||||
|
||||
// Flush to submit the 11 command list to the shared command queue.
|
||||
mDxInterface->getD3d11DeviceContext()->Flush();
|
||||
}
|
||||
|
||||
void DirectX2dIntegration::clearBuffers()
|
||||
{
|
||||
for (auto& buffer : mWrappedBackBuffers)
|
||||
{
|
||||
buffer.Reset();
|
||||
}
|
||||
mWrappedBackBuffers.clear();
|
||||
|
||||
for (auto& buffer : mD2dRenderTargets)
|
||||
{
|
||||
buffer.Reset();
|
||||
}
|
||||
mD2dRenderTargets.clear();
|
||||
}
|
||||
|
||||
void DirectX2dIntegration::wrapBuffer(ID3D12Resource* renderTarget)
|
||||
{
|
||||
mWrappedBackBuffers.push_back(Microsoft::WRL::ComPtr<ID3D11Resource>());
|
||||
|
||||
D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET };
|
||||
mDxInterface->get11On12Device()->CreateWrappedResource(renderTarget, &d3d11Flags,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&mWrappedBackBuffers[mWrappedBackBuffers.size()-1]));
|
||||
|
||||
float dpiX{ 0.0 };
|
||||
float dpiY{ 0.0 };
|
||||
mDxInterface->getD2dFactory()->GetDesktopDpi(&dpiX, &dpiY);
|
||||
const auto pixel_format = D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED);
|
||||
const auto bitmap_props = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, pixel_format, dpiX, dpiY);
|
||||
|
||||
mD2dRenderTargets.push_back(Microsoft::WRL::ComPtr<ID2D1Bitmap1>());
|
||||
Microsoft::WRL::ComPtr<IDXGISurface> surface;
|
||||
mWrappedBackBuffers[mWrappedBackBuffers.size() - 1].As(&surface);
|
||||
mDxInterface->getD2dContext()->CreateBitmapFromDxgiSurface(surface.Get(), &bitmap_props, &mD2dRenderTargets[mD2dRenderTargets.size()-1]);
|
||||
}
|
||||
|
||||
void DirectX2dIntegration::updateBackbufferIndex(UINT idx)
|
||||
{
|
||||
mFrameIndex = idx;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <wrl.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
class Win32DxInterface;
|
||||
namespace mt
|
||||
{
|
||||
class Window;
|
||||
}
|
||||
struct ID3D12Resource;
|
||||
struct ID3D11Resource;
|
||||
struct ID2D1Bitmap1;
|
||||
|
||||
class DirectX2dIntegration
|
||||
{
|
||||
public:
|
||||
DirectX2dIntegration(mt::Window* window, Win32DxInterface* dxInterface, UINT frameCount);
|
||||
|
||||
void clearBuffers();
|
||||
|
||||
void render();
|
||||
|
||||
void updateBackbufferIndex(UINT idx);
|
||||
|
||||
void wrapBuffer(ID3D12Resource* referenceBuffer);
|
||||
|
||||
private:
|
||||
ID3D11Resource* const* getD11on12WrappedBackBuffer() const;
|
||||
ID2D1Bitmap1* getD2dRenderTarget() const;
|
||||
|
||||
Win32DxInterface* mDxInterface{ nullptr };
|
||||
mt::Window* mWindow{ nullptr };
|
||||
|
||||
UINT mFrameCount{ 2 };
|
||||
UINT mFrameIndex{ 0 };
|
||||
std::vector<Microsoft::WRL::ComPtr<ID3D11Resource> > mWrappedBackBuffers;
|
||||
std::vector<Microsoft::WRL::ComPtr<ID2D1Bitmap1> > mD2dRenderTargets;
|
||||
};
|
97
src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp
Normal file
97
src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include "DirectXBuffers.h"
|
||||
|
||||
#include "DirectXDescriptors.h"
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d12.h>
|
||||
#include <directx/d3dx12.h>
|
||||
|
||||
DirectXBuffers::DirectXBuffers(UINT frameCount)
|
||||
: mFrameCount(frameCount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DirectXBuffers::clear()
|
||||
{
|
||||
for (auto& buffer : mBackBuffers)
|
||||
{
|
||||
buffer.Reset();
|
||||
}
|
||||
mBackBuffers.clear();
|
||||
mDepthStencilBuffer.Reset();
|
||||
}
|
||||
|
||||
UINT DirectXBuffers::getCurrentBackBufferIndex() const
|
||||
{
|
||||
return mBackBufferIndex;
|
||||
}
|
||||
|
||||
ID3D12Resource* DirectXBuffers::getCurrentBackBuffer() const
|
||||
{
|
||||
return mBackBuffers[mBackBufferIndex].Get();
|
||||
}
|
||||
|
||||
ID3D12Resource* DirectXBuffers::getBackBuffer(UINT index) const
|
||||
{
|
||||
return mBackBuffers[index].Get();
|
||||
}
|
||||
|
||||
ID3D12Resource* DirectXBuffers::getDepthStencilBuffer() const
|
||||
{
|
||||
return mDepthStencilBuffer.Get();
|
||||
}
|
||||
|
||||
void DirectXBuffers::updateBackbufferIndex(UINT index)
|
||||
{
|
||||
mBackBufferIndex = index;
|
||||
}
|
||||
|
||||
void DirectXBuffers::setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swapChain, DirectXDescriptors* descriptors)
|
||||
{
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_heap_handle(descriptors->getRtvHandle());
|
||||
for (UINT i = 0; i < mFrameCount; i++)
|
||||
{
|
||||
mBackBuffers.push_back(Microsoft::WRL::ComPtr<ID3D12Resource>());
|
||||
|
||||
swapChain->GetBuffer(i, IID_PPV_ARGS(&mBackBuffers[mBackBuffers.size()-1]));
|
||||
device->CreateRenderTargetView(mBackBuffers[mBackBuffers.size() - 1].Get(), nullptr, rtv_heap_handle);
|
||||
rtv_heap_handle.Offset(1, descriptors->getRtvDescriptorSize());
|
||||
}
|
||||
}
|
||||
|
||||
void DirectXBuffers::setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height)
|
||||
{
|
||||
D3D12_RESOURCE_DESC depthStencilDesc;
|
||||
depthStencilDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
depthStencilDesc.Alignment = 0;
|
||||
depthStencilDesc.Width = width;
|
||||
depthStencilDesc.Height = height;
|
||||
depthStencilDesc.DepthOrArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
depthStencilDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
depthStencilDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
|
||||
D3D12_CLEAR_VALUE optClear;
|
||||
optClear.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
optClear.DepthStencil.Depth = 1.0f;
|
||||
optClear.DepthStencil.Stencil = 0;
|
||||
|
||||
auto props = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
|
||||
device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE,
|
||||
&depthStencilDesc, D3D12_RESOURCE_STATE_COMMON, &optClear, IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
void DirectXBuffers::setupDepthStencilView(ID3D12Device* device, DirectXDescriptors* descriptors)
|
||||
{
|
||||
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
|
||||
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
|
||||
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
dsvDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
dsvDesc.Texture2D.MipSlice = 0;
|
||||
device->CreateDepthStencilView(mDepthStencilBuffer.Get(), &dsvDesc, descriptors->getDsvHandle());
|
||||
}
|
39
src/windows/ui_interfaces/win32/directx/DirectXBuffers.h
Normal file
39
src/windows/ui_interfaces/win32/directx/DirectXBuffers.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include <wrl.h>
|
||||
#include <vector>
|
||||
|
||||
class DirectXDescriptors;
|
||||
struct ID3D12Resource;
|
||||
struct ID3D12Device;
|
||||
struct IDXGISwapChain4;
|
||||
|
||||
class DirectXBuffers
|
||||
{
|
||||
public:
|
||||
DirectXBuffers(UINT frameCount);
|
||||
|
||||
void clear();
|
||||
|
||||
UINT getCurrentBackBufferIndex() const;
|
||||
|
||||
ID3D12Resource* getCurrentBackBuffer() const;
|
||||
|
||||
ID3D12Resource* getBackBuffer(UINT index) const;
|
||||
|
||||
ID3D12Resource* getDepthStencilBuffer() const;
|
||||
|
||||
void setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swapChain, DirectXDescriptors* descriptors);
|
||||
|
||||
void setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height);
|
||||
|
||||
void setupDepthStencilView(ID3D12Device* device, DirectXDescriptors* descriptors);
|
||||
|
||||
void updateBackbufferIndex(UINT index);
|
||||
|
||||
private:
|
||||
UINT mFrameCount{ 2 };
|
||||
UINT mBackBufferIndex{ 0 };
|
||||
std::vector<Microsoft::WRL::ComPtr<ID3D12Resource> > mBackBuffers;
|
||||
Microsoft::WRL::ComPtr<ID3D12Resource> mDepthStencilBuffer;
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
#include "DirectXCommandList.h"
|
||||
|
||||
#include <d3d12.h>
|
||||
|
||||
void DirectXCommandList::close()
|
||||
{
|
||||
mCommandList->Close();
|
||||
}
|
||||
|
||||
void DirectXCommandList::create(ID3D12Device* device, ID3D12PipelineState* pso)
|
||||
{
|
||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocator));
|
||||
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), pso, IID_PPV_ARGS(&mCommandList));
|
||||
mCommandList->Close();
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* DirectXCommandList::get() const
|
||||
{
|
||||
return mCommandList.Get();
|
||||
}
|
||||
|
||||
void DirectXCommandList::execute(ID3D12CommandQueue* queue)
|
||||
{
|
||||
ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() };
|
||||
queue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
||||
}
|
||||
|
||||
void DirectXCommandList::reset(ID3D12PipelineState* pso)
|
||||
{
|
||||
mCommandList->Reset(mCommandAllocator.Get(), pso);
|
||||
}
|
||||
|
||||
void DirectXCommandList::resetAllocator()
|
||||
{
|
||||
mCommandAllocator.Reset();
|
||||
}
|
||||
|
29
src/windows/ui_interfaces/win32/directx/DirectXCommandList.h
Normal file
29
src/windows/ui_interfaces/win32/directx/DirectXCommandList.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <wrl.h>
|
||||
|
||||
struct ID3D12CommandAllocator;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct ID3D12PipelineState;
|
||||
struct ID3D12CommandQueue;
|
||||
struct ID3D12Device;
|
||||
|
||||
class DirectXCommandList
|
||||
{
|
||||
public:
|
||||
void close();
|
||||
|
||||
void create(ID3D12Device* device, ID3D12PipelineState* pso);
|
||||
|
||||
ID3D12GraphicsCommandList* get() const;
|
||||
|
||||
void execute(ID3D12CommandQueue* queue);
|
||||
|
||||
void resetAllocator();
|
||||
|
||||
void reset(ID3D12PipelineState* pso);
|
||||
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mCommandAllocator;
|
||||
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;
|
||||
};
|
|
@ -0,0 +1,76 @@
|
|||
#include "DirectXDescriptors.h"
|
||||
|
||||
#include <directx/d3dx12.h>
|
||||
|
||||
UINT DirectXDescriptors::getRtvDescriptorSize() const
|
||||
{
|
||||
return mRtvDescriptorSize;
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DirectXDescriptors::getRtvHandle(int index) const
|
||||
{
|
||||
if (index == -1)
|
||||
{
|
||||
return CD3DX12_CPU_DESCRIPTOR_HANDLE(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
|
||||
}
|
||||
else
|
||||
{
|
||||
return CD3DX12_CPU_DESCRIPTOR_HANDLE(mRtvHeap->GetCPUDescriptorHandleForHeapStart(), index, mRtvDescriptorSize);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DirectXDescriptors::getDsvHandle() const
|
||||
{
|
||||
return mDsvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
}
|
||||
|
||||
void DirectXDescriptors::updateDescriptorSizes(ID3D12Device* device)
|
||||
{
|
||||
mRtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
mDsvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
||||
mCbvSrvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
}
|
||||
|
||||
void DirectXDescriptors::setupDefaultDescriptorHeaps(ID3D12Device* device, unsigned numFrames)
|
||||
{
|
||||
updateDescriptorSizes(device);
|
||||
setupRtvDescriptorHeap(device, numFrames);
|
||||
setupDsvDescriptorHeap(device);
|
||||
}
|
||||
|
||||
void DirectXDescriptors::setupRtvDescriptorHeap(ID3D12Device* device, unsigned numFrames)
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
|
||||
rtvHeapDesc.NumDescriptors = numFrames;
|
||||
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&mRtvHeap));
|
||||
}
|
||||
|
||||
void DirectXDescriptors::setupDsvDescriptorHeap(ID3D12Device* device)
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
|
||||
dsvHeapDesc.NumDescriptors = 1;
|
||||
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
||||
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
dsvHeapDesc.NodeMask = 0;
|
||||
device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&mDsvHeap));
|
||||
}
|
||||
|
||||
void DirectXDescriptors::setupSrvDescriptorHeap(ID3D12Device* device)
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
|
||||
srvHeapDesc.NumDescriptors = 1;
|
||||
srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvHeap));
|
||||
}
|
||||
|
||||
void DirectXDescriptors::setupCbvDescriptorHeap(ID3D12Device* device)
|
||||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {};
|
||||
cbvHeapDesc.NumDescriptors = 1;
|
||||
cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&mCbvHeap));
|
||||
}
|
29
src/windows/ui_interfaces/win32/directx/DirectXDescriptors.h
Normal file
29
src/windows/ui_interfaces/win32/directx/DirectXDescriptors.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
class DirectXDescriptors
|
||||
{
|
||||
public:
|
||||
UINT getRtvDescriptorSize() const;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE getRtvHandle(int index = -1) const;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE getDsvHandle() const;
|
||||
|
||||
void setupDefaultDescriptorHeaps(ID3D12Device* device, unsigned numFrames = 2);
|
||||
private:
|
||||
void updateDescriptorSizes(ID3D12Device* device);
|
||||
void setupRtvDescriptorHeap(ID3D12Device* device, unsigned numFrames);
|
||||
void setupDsvDescriptorHeap(ID3D12Device* device);
|
||||
void setupSrvDescriptorHeap(ID3D12Device* device);
|
||||
void setupCbvDescriptorHeap(ID3D12Device* device);
|
||||
|
||||
UINT mRtvDescriptorSize{ 0 };
|
||||
UINT mDsvDescriptorSize{ 0 };
|
||||
UINT mCbvSrvDescriptorSize{ 0 };
|
||||
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mDsvHeap;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mSrvHeap;
|
||||
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mCbvHeap;
|
||||
};
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include <DirectXMath.h>
|
||||
#include <DirectXPackedVector.h>
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d11.h>
|
||||
|
@ -17,25 +14,17 @@
|
|||
|
||||
#include <dwrite.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <windows.h>
|
||||
#include <wrl.h>
|
||||
|
||||
void Win32DxInterface::getHardwareAdapter(IDXGIAdapter1** ppAdapter)
|
||||
{
|
||||
*ppAdapter = nullptr;
|
||||
for (UINT adapterIndex = 0; ; ++adapterIndex)
|
||||
{
|
||||
IDXGIAdapter1* pAdapter = nullptr;
|
||||
if (DXGI_ERROR_NOT_FOUND == mFactory->EnumAdapters1(adapterIndex, &pAdapter))
|
||||
if (mDxgiFactory->EnumAdapters1(adapterIndex, &pAdapter) == DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||
if (SUCCEEDED(::D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||
{
|
||||
*ppAdapter = pAdapter;
|
||||
return;
|
||||
|
@ -49,9 +38,9 @@ bool Win32DxInterface::isValid() const
|
|||
return mIsValid;
|
||||
}
|
||||
|
||||
ID3D12Device* Win32DxInterface::getDevice() const
|
||||
ID3D12Device* Win32DxInterface::getD3dDevice() const
|
||||
{
|
||||
return mDevice.Get();
|
||||
return mD3dDevice.Get();
|
||||
}
|
||||
|
||||
ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
||||
|
@ -59,9 +48,9 @@ ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
|||
return mD3d11On12Device.Get();
|
||||
}
|
||||
|
||||
IDXGIFactory7* Win32DxInterface::getFactory() const
|
||||
IDXGIFactory7* Win32DxInterface::getDxgiFactory() const
|
||||
{
|
||||
return mFactory.Get();
|
||||
return mDxgiFactory.Get();
|
||||
}
|
||||
|
||||
ID2D1Factory3* Win32DxInterface::getD2dFactory() const
|
||||
|
@ -91,7 +80,20 @@ ID3D11DeviceContext* Win32DxInterface::getD3d11DeviceContext() const
|
|||
|
||||
void Win32DxInterface::initialize()
|
||||
{
|
||||
MLOG_INFO("Initialize DX");
|
||||
MLOG_INFO("Initialize DirectX");
|
||||
createD3dFactory();
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter1> pAdapter;
|
||||
getHardwareAdapter(&pAdapter);
|
||||
createD3dDevice(pAdapter.Get());
|
||||
|
||||
createCommandQueue();
|
||||
|
||||
mIsValid = initializeD2d();
|
||||
}
|
||||
|
||||
bool Win32DxInterface::createD3dFactory()
|
||||
{
|
||||
UINT dxgiFactoryFlags = 0;
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
{
|
||||
|
@ -103,36 +105,52 @@ void Win32DxInterface::initialize()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (FAILED(::CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&mDxgiFactory))))
|
||||
{
|
||||
MLOG_ERROR("Failed to create DXGI Factory");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT hr = ::CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&mFactory));
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter1> pAdapter;
|
||||
getHardwareAdapter(&pAdapter);
|
||||
bool Win32DxInterface::createD3dDevice(IDXGIAdapter1* pAdapter)
|
||||
{
|
||||
if (pAdapter)
|
||||
{
|
||||
if (!SUCCEEDED(D3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&mDevice))))
|
||||
if (FAILED(::D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&mD3dDevice))))
|
||||
{
|
||||
MLOG_ERROR("Failed to create D3D12 device.");
|
||||
return;
|
||||
MLOG_ERROR("Failed to create D3D12 device, will try WARP.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter> pWarpAdapter;
|
||||
mDxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&pWarpAdapter));
|
||||
if (FAILED(::D3D12CreateDevice(pWarpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&mD3dDevice))))
|
||||
{
|
||||
MLOG_ERROR("Failed to create WARP device.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MLOG_ERROR("Failed to get DX hardware adapter.");
|
||||
return;
|
||||
MLOG_ERROR("Failed to get DirectX adapter.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32DxInterface::createCommandQueue()
|
||||
{
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
if (!SUCCEEDED(mDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue))))
|
||||
if (FAILED(mD3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue))))
|
||||
{
|
||||
MLOG_ERROR("Failed to create command queue.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto init_2d_ok = initializeD2d();
|
||||
mIsValid = init_2d_ok;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32DxInterface::initializeD2d()
|
||||
|
@ -159,24 +177,17 @@ bool Win32DxInterface::initializeD11on12()
|
|||
{
|
||||
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
|
||||
);
|
||||
auto pCommandQueue = reinterpret_cast<IUnknown**>(mCommandQueue.GetAddressOf());
|
||||
if (FAILED(D3D11On12CreateDevice(mD3dDevice.Get(), d3d11DeviceFlags, nullptr, 0, pCommandQueue, 1, 0, &d3d11Device, &mD3d11DeviceContext, nullptr)))
|
||||
{
|
||||
MLOG_ERROR("Failed to create D3D11 on 12 Device");
|
||||
return false;
|
||||
}
|
||||
d3d11Device.As(&mD3d11On12Device);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32DxInterface::initializeDirectWrite()
|
||||
{
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory);
|
||||
return true;
|
||||
return SUCCEEDED(::DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory));
|
||||
}
|
|
@ -21,24 +21,24 @@ struct ID2D1DeviceContext2;
|
|||
class Win32DxInterface
|
||||
{
|
||||
public:
|
||||
ID3D12Device* getDevice() const;
|
||||
ID3D11On12Device* get11On12Device() const;
|
||||
ID3D11DeviceContext* getD3d11DeviceContext() const;
|
||||
|
||||
IDXGIFactory7* getFactory() const;
|
||||
|
||||
ID2D1Factory3* getD2dFactory() const;
|
||||
ID2D1DeviceContext2* getD2dContext() const;
|
||||
|
||||
IDXGIFactory7* getDxgiFactory() const;
|
||||
ID3D12Device* getD3dDevice() const;
|
||||
ID3D12CommandQueue* getCommandQueue() const;
|
||||
|
||||
ID3D11On12Device* get11On12Device() const;
|
||||
ID3D11DeviceContext* getD3d11DeviceContext() const;
|
||||
ID2D1Factory3* getD2dFactory() const;
|
||||
ID2D1DeviceContext2* getD2dContext() const;
|
||||
IDWriteFactory* getDirectWriteFactory() const;
|
||||
|
||||
void initialize();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
bool createD3dFactory();
|
||||
bool createD3dDevice(IDXGIAdapter1* ppAdapter);
|
||||
bool createCommandQueue();
|
||||
|
||||
void getHardwareAdapter(IDXGIAdapter1** ppAdapter);
|
||||
|
||||
bool initializeD2d();
|
||||
|
@ -47,16 +47,15 @@ private:
|
|||
|
||||
bool mIsValid{ false };
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory7> mFactory;
|
||||
Microsoft::WRL::ComPtr<ID3D12Device> mDevice;
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory7> mDxgiFactory;
|
||||
Microsoft::WRL::ComPtr<ID3D12Device> mD3dDevice;
|
||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||
|
||||
// 2D Rendering - e.g. text
|
||||
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;
|
||||
};
|
|
@ -0,0 +1,283 @@
|
|||
#include "Win32DxWindowInterface.h"
|
||||
|
||||
#include "Win32DxInterface.h"
|
||||
#include "Win32Window.h"
|
||||
#include "Window.h"
|
||||
#include "Widget.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include "DirectXDescriptors.h"
|
||||
#include "DirectX2dIntegration.h"
|
||||
#include "DirectXBuffers.h"
|
||||
#include "DirectXCommandList.h"
|
||||
|
||||
#include "DrawingContext.h"
|
||||
#include "DirectXPainter.h"
|
||||
#include "DirectXMeshPainter.h"
|
||||
#include "DirectXTextPainter.h"
|
||||
#include "DirectXShaderProgram.h"
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d3d12sdklayers.h>
|
||||
#include <D3Dcommon.h>
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
Win32DxWindowInterface::Win32DxWindowInterface(mt::Window* window, Win32DxInterface* dxInterface)
|
||||
: mWindow(window),
|
||||
mDxInterface(dxInterface)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Win32DxWindowInterface::~Win32DxWindowInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::destroyWindow()
|
||||
{
|
||||
flushCommandQueue();
|
||||
::CloseHandle(mFenceEvent);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::onRender()
|
||||
{
|
||||
if (!mIsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateCommandList();
|
||||
|
||||
mCommandList->execute(mDxInterface->getCommandQueue());
|
||||
|
||||
mD2dIntegration->render();
|
||||
|
||||
mSwapChain->Present(1, 0);
|
||||
|
||||
flushCommandQueue();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::updateCommandList()
|
||||
{
|
||||
// Command list allocators can only be reset when the associated
|
||||
// command lists have finished execution on the GPU; apps should use
|
||||
// fences to determine GPU execution progress.
|
||||
mCommandList->resetAllocator();
|
||||
|
||||
// However, when ExecuteCommandList() is called on a particular command
|
||||
// list, that command list can then be reset at any time and must be before
|
||||
// re-recording.
|
||||
mCommandList->reset(getPipelineState());
|
||||
|
||||
// Set necessary state.
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
mCommandList->get()->SetGraphicsRootSignature(painter->getMeshPainter()->getRootSignature());
|
||||
mCommandList->get()->RSSetViewports(1, &mViewport);
|
||||
mCommandList->get()->RSSetScissorRects(1, &mScissorRect);
|
||||
|
||||
// Indicate that the back buffer will be used as a render target.
|
||||
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getCurrentBackBuffer(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
mCommandList->get()->ResourceBarrier(1, &barrier);
|
||||
|
||||
auto rtv_handle = mDescriptors->getRtvHandle(static_cast<int>(mBuffers->getCurrentBackBufferIndex()));
|
||||
mCommandList->get()->OMSetRenderTargets(1, &rtv_handle, FALSE, nullptr);
|
||||
|
||||
painter->paintBackground(rtv_handle, mCommandList->get());
|
||||
painter->paintMesh(mCommandList->get());
|
||||
|
||||
// Indicate that the back buffer will now be used to present. (Exclude as handled by D2D integration later)
|
||||
//barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
|
||||
//mCommandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
mCommandList->close();
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::initialize()
|
||||
{
|
||||
if (mInitialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
mInitialized = true;
|
||||
|
||||
if (!createSwapChain())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mCommandList = std::make_unique<DirectXCommandList>();
|
||||
mCommandList->create(mDxInterface->getD3dDevice(), getPipelineState());
|
||||
|
||||
createSyncObjects();
|
||||
|
||||
mDescriptors = std::make_unique<DirectXDescriptors>();
|
||||
mDescriptors->setupDefaultDescriptorHeaps(mDxInterface->getD3dDevice());
|
||||
mD2dIntegration = std::make_unique<DirectX2dIntegration>(mWindow, mDxInterface, FrameCount);
|
||||
mBuffers = std::make_unique<DirectXBuffers>(FrameCount);
|
||||
|
||||
onResize();
|
||||
|
||||
if (!loadAssets())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
flushCommandQueue();
|
||||
|
||||
mIsValid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::onResize()
|
||||
{
|
||||
flushCommandQueue();
|
||||
|
||||
mCommandList->reset(getPipelineState());
|
||||
|
||||
clearBuffers();
|
||||
|
||||
resizeSwapChain();
|
||||
|
||||
populateBuffers();
|
||||
|
||||
mCommandList->close();
|
||||
|
||||
mCommandList->execute(mDxInterface->getCommandQueue());
|
||||
|
||||
flushCommandQueue();
|
||||
|
||||
updateViewport();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::resizeSwapChain()
|
||||
{
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
mSwapChain->ResizeBuffers(FrameCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
|
||||
updateBackbufferIndex(0);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::updateViewport()
|
||||
{
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
mViewport = CD3DX12_VIEWPORT(0.0f, 0.0f, static_cast<float>(width), static_cast<float>(height));
|
||||
mScissorRect = CD3DX12_RECT(0, 0, width, height);
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::clearBuffers()
|
||||
{
|
||||
mBuffers->clear();
|
||||
mD2dIntegration->clearBuffers();
|
||||
}
|
||||
|
||||
ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const
|
||||
{
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
return painter->getMeshPainter()->getPipelineState();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::populateBuffers()
|
||||
{
|
||||
auto d3d_device = mDxInterface->getD3dDevice();
|
||||
mBuffers->setupBackBuffers(d3d_device, mSwapChain.Get(), mDescriptors.get());
|
||||
for (UINT idx = 0; idx < FrameCount; idx++)
|
||||
{
|
||||
mD2dIntegration->wrapBuffer(mBuffers->getBackBuffer(idx));
|
||||
}
|
||||
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
mBuffers->setupDepthStencilHeap(mDxInterface->getD3dDevice(), width, height);
|
||||
mBuffers->setupDepthStencilView(mDxInterface->getD3dDevice(), mDescriptors.get());
|
||||
|
||||
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getDepthStencilBuffer(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE);
|
||||
mCommandList->get()->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::createSwapChain()
|
||||
{
|
||||
mSwapChain.Reset();
|
||||
|
||||
const auto width = mWindow->getWidth();
|
||||
const auto height = mWindow->getHeight();
|
||||
const auto hwnd = dynamic_cast<Win32Window*>(mWindow->getPlatformWindow())->getHandle();
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = FrameCount;
|
||||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
|
||||
if (FAILED(mDxInterface->getDxgiFactory()->CreateSwapChainForHwnd(mDxInterface->getCommandQueue(), hwnd, &swapChainDesc, nullptr, nullptr, &swapChain)))
|
||||
{
|
||||
MLOG_ERROR("Failed to create swap chain for hwnd: " << hwnd);
|
||||
return false;
|
||||
}
|
||||
swapChain.As(&mSwapChain);
|
||||
|
||||
// Prevent fullscreen toggle
|
||||
mDxInterface->getDxgiFactory()->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
|
||||
|
||||
// Update index for backbuffer
|
||||
updateBackbufferIndex(mSwapChain->GetCurrentBackBufferIndex());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::updateBackbufferIndex(UINT index)
|
||||
{
|
||||
mBuffers->updateBackbufferIndex(index);
|
||||
mD2dIntegration->updateBackbufferIndex(index);
|
||||
}
|
||||
|
||||
bool Win32DxWindowInterface::loadAssets()
|
||||
{
|
||||
auto painter = dynamic_cast<DirectXPainter*>(mWindow->getDrawingContent()->getPainter());
|
||||
painter->initializeMesh(mDxInterface->getD3dDevice());
|
||||
painter->initializeText(mDxInterface->getD2dContext(), mDxInterface->getDirectWriteFactory());
|
||||
|
||||
painter->updateMesh(mDxInterface->getD3dDevice());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::createSyncObjects()
|
||||
{
|
||||
mDxInterface->getD3dDevice()->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&mFence));
|
||||
mFenceValue = 1;
|
||||
|
||||
// Create an event handle to use for frame synchronization.
|
||||
mFenceEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (mFenceEvent == nullptr)
|
||||
{
|
||||
//ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
// Wait for the command list to execute; we are reusing the same command
|
||||
// list in our main loop but for now, we just want to wait for setup to
|
||||
// complete before continuing.
|
||||
flushCommandQueue();
|
||||
}
|
||||
|
||||
void Win32DxWindowInterface::flushCommandQueue()
|
||||
{
|
||||
// Signal and increment the fence value.
|
||||
const UINT64 fence = mFenceValue;
|
||||
mDxInterface->getCommandQueue()->Signal(mFence.Get(), fence);
|
||||
mFenceValue++;
|
||||
|
||||
// Wait until the previous frame is finished.
|
||||
if (mFence->GetCompletedValue() < fence)
|
||||
{
|
||||
mFence->SetEventOnCompletion(fence, mFenceEvent);
|
||||
::WaitForSingleObject(mFenceEvent, INFINITE);
|
||||
}
|
||||
|
||||
updateBackbufferIndex(mSwapChain->GetCurrentBackBufferIndex());
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
#include <directx/d3dx12.h>
|
||||
|
||||
class Win32DxInterface;
|
||||
class DirectXDescriptors;
|
||||
class DirectX2dIntegration;
|
||||
class DirectXBuffers;
|
||||
class DirectXCommandList;
|
||||
namespace mt
|
||||
{
|
||||
class Window;
|
||||
}
|
||||
|
||||
struct ID3D12CommandAllocator;
|
||||
struct ID3D12GraphicsCommandList;
|
||||
struct IDXGISwapChain4;
|
||||
struct ID3D12Resource;
|
||||
struct ID3D12Fence;
|
||||
struct ID3D12PipelineState;
|
||||
|
||||
class Win32DxWindowInterface
|
||||
{
|
||||
public:
|
||||
Win32DxWindowInterface(mt::Window* window, Win32DxInterface* dxInterface);
|
||||
|
||||
~Win32DxWindowInterface();
|
||||
|
||||
bool initialize();
|
||||
|
||||
void onResize();
|
||||
|
||||
void onRender();
|
||||
|
||||
private:
|
||||
bool loadAssets();
|
||||
|
||||
void updateCommandList();
|
||||
|
||||
void destroyWindow();
|
||||
|
||||
bool createSwapChain();
|
||||
void resizeSwapChain();
|
||||
|
||||
void clearBuffers();
|
||||
void populateBuffers();
|
||||
void updateBackbufferIndex(UINT index);
|
||||
|
||||
void createSyncObjects();
|
||||
void flushCommandQueue();
|
||||
|
||||
void updateViewport();
|
||||
|
||||
ID3D12PipelineState* getPipelineState() const;
|
||||
|
||||
Win32DxInterface* mDxInterface{ nullptr };
|
||||
bool mInitialized{ false };
|
||||
bool mIsValid{ false };
|
||||
|
||||
mt::Window* mWindow{ nullptr };
|
||||
CD3DX12_VIEWPORT mViewport;
|
||||
CD3DX12_RECT mScissorRect;
|
||||
|
||||
std::unique_ptr<DirectXDescriptors> mDescriptors;
|
||||
std::unique_ptr<DirectX2dIntegration> mD2dIntegration;
|
||||
std::unique_ptr<DirectXBuffers> mBuffers;
|
||||
std::unique_ptr<DirectXCommandList> mCommandList;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain4> mSwapChain;
|
||||
|
||||
static const UINT FrameCount = 2;
|
||||
Microsoft::WRL::ComPtr<ID3D12Fence> mFence;
|
||||
uint64_t mFenceValue = 0;
|
||||
uint64_t mFrameFenceValues[FrameCount] = {};
|
||||
HANDLE mFenceEvent{};
|
||||
};
|
||||
|
||||
using XcbGlWindowInterfacePtr = std::unique_ptr<Win32DxWindowInterface>;
|
Loading…
Reference in a new issue