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 "File.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <directx/d3dx12.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
#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 };
|
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
|
||||||
commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||||
|
|
|
@ -13,8 +13,6 @@ class DrawingContext;
|
||||||
class DirectXMeshPainter;
|
class DirectXMeshPainter;
|
||||||
class DirectXTextPainter;
|
class DirectXTextPainter;
|
||||||
|
|
||||||
struct CD3DX12_CPU_DESCRIPTOR_HANDLE;
|
|
||||||
|
|
||||||
class DirectXPainter : public AbstractPainter
|
class DirectXPainter : public AbstractPainter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -28,7 +26,7 @@ public:
|
||||||
|
|
||||||
void initializeText(ID2D1DeviceContext2* d2dContext, IDWriteFactory* directWriteFactory);
|
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);
|
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)
|
void DirectXTextPainter::paint(SceneText* text, DrawingContext* context, ID2D1DeviceContext2* d2dContext, IDWriteFactory* directWriteFactory)
|
||||||
{
|
{
|
||||||
const auto location = text->getTransform().getLocation();
|
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());
|
updateTextFormat(directWriteFactory, text->getTextData().mFont.getSize());
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,18 @@ else()
|
||||||
ui_interfaces/win32/Win32WindowInterface.cpp
|
ui_interfaces/win32/Win32WindowInterface.cpp
|
||||||
ui_interfaces/win32/Win32Window.h
|
ui_interfaces/win32/Win32Window.h
|
||||||
ui_interfaces/win32/Win32Window.cpp
|
ui_interfaces/win32/Win32Window.cpp
|
||||||
ui_interfaces/win32/Win32DxInterface.h
|
ui_interfaces/win32/directx/Win32DxInterface.h
|
||||||
ui_interfaces/win32/Win32DxInterface.cpp
|
ui_interfaces/win32/directx/Win32DxInterface.cpp
|
||||||
ui_interfaces/win32/Win32DxWindowInterface.h
|
ui_interfaces/win32/directx/Win32DxWindowInterface.h
|
||||||
ui_interfaces/win32/Win32DxWindowInterface.cpp
|
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)
|
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})
|
add_library(windows SHARED ${windows_LIB_INCLUDES} ${platform_INCLUDES})
|
||||||
|
|
||||||
target_include_directories(windows PUBLIC
|
target_include_directories(windows PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/managers"
|
${CMAKE_CURRENT_SOURCE_DIR}/managers
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces"
|
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11"
|
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland"
|
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32"
|
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32/directx
|
||||||
${WAYLAND_INCLUDE_DIRS}
|
${WAYLAND_INCLUDE_DIRS}
|
||||||
${X11_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 = { };
|
MSG msg = { };
|
||||||
while (::GetMessage(&msg, NULL, 0, 0))
|
while (::GetMessage(&msg, NULL, 0, 0))
|
||||||
{
|
{
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
::TranslateMessage(&msg);
|
::TranslateMessage(&msg);
|
||||||
::DispatchMessage(&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 "FileLogger.h"
|
||||||
|
|
||||||
#include <DirectXMath.h>
|
|
||||||
#include <DirectXPackedVector.h>
|
|
||||||
|
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include <dxgi1_6.h>
|
#include <dxgi1_6.h>
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
@ -17,25 +14,17 @@
|
||||||
|
|
||||||
#include <dwrite.h>
|
#include <dwrite.h>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wrl.h>
|
|
||||||
|
|
||||||
void Win32DxInterface::getHardwareAdapter(IDXGIAdapter1** ppAdapter)
|
void Win32DxInterface::getHardwareAdapter(IDXGIAdapter1** ppAdapter)
|
||||||
{
|
{
|
||||||
*ppAdapter = nullptr;
|
*ppAdapter = nullptr;
|
||||||
for (UINT adapterIndex = 0; ; ++adapterIndex)
|
for (UINT adapterIndex = 0; ; ++adapterIndex)
|
||||||
{
|
{
|
||||||
IDXGIAdapter1* pAdapter = nullptr;
|
IDXGIAdapter1* pAdapter = nullptr;
|
||||||
if (DXGI_ERROR_NOT_FOUND == mFactory->EnumAdapters1(adapterIndex, &pAdapter))
|
if (mDxgiFactory->EnumAdapters1(adapterIndex, &pAdapter) == DXGI_ERROR_NOT_FOUND)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (SUCCEEDED(::D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||||
// 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)))
|
|
||||||
{
|
{
|
||||||
*ppAdapter = pAdapter;
|
*ppAdapter = pAdapter;
|
||||||
return;
|
return;
|
||||||
|
@ -49,9 +38,9 @@ bool Win32DxInterface::isValid() const
|
||||||
return mIsValid;
|
return mIsValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Device* Win32DxInterface::getDevice() const
|
ID3D12Device* Win32DxInterface::getD3dDevice() const
|
||||||
{
|
{
|
||||||
return mDevice.Get();
|
return mD3dDevice.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
||||||
|
@ -59,9 +48,9 @@ ID3D11On12Device* Win32DxInterface::get11On12Device() const
|
||||||
return mD3d11On12Device.Get();
|
return mD3d11On12Device.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
IDXGIFactory7* Win32DxInterface::getFactory() const
|
IDXGIFactory7* Win32DxInterface::getDxgiFactory() const
|
||||||
{
|
{
|
||||||
return mFactory.Get();
|
return mDxgiFactory.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID2D1Factory3* Win32DxInterface::getD2dFactory() const
|
ID2D1Factory3* Win32DxInterface::getD2dFactory() const
|
||||||
|
@ -91,7 +80,20 @@ ID3D11DeviceContext* Win32DxInterface::getD3d11DeviceContext() const
|
||||||
|
|
||||||
void Win32DxInterface::initialize()
|
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;
|
UINT dxgiFactoryFlags = 0;
|
||||||
#if defined(DEBUG) || defined(_DEBUG)
|
#if defined(DEBUG) || defined(_DEBUG)
|
||||||
{
|
{
|
||||||
|
@ -103,36 +105,52 @@ void Win32DxInterface::initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#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));
|
bool Win32DxInterface::createD3dDevice(IDXGIAdapter1* pAdapter)
|
||||||
|
{
|
||||||
Microsoft::WRL::ComPtr<IDXGIAdapter1> pAdapter;
|
|
||||||
getHardwareAdapter(&pAdapter);
|
|
||||||
if (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.");
|
MLOG_ERROR("Failed to create D3D12 device, will try WARP.");
|
||||||
return;
|
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
|
else
|
||||||
{
|
{
|
||||||
MLOG_ERROR("Failed to get DX hardware adapter.");
|
MLOG_ERROR("Failed to get DirectX adapter.");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Win32DxInterface::createCommandQueue()
|
||||||
|
{
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
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.");
|
MLOG_ERROR("Failed to create command queue.");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
const auto init_2d_ok = initializeD2d();
|
|
||||||
mIsValid = init_2d_ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32DxInterface::initializeD2d()
|
bool Win32DxInterface::initializeD2d()
|
||||||
|
@ -159,24 +177,17 @@ bool Win32DxInterface::initializeD11on12()
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<ID3D11Device> d3d11Device;
|
Microsoft::WRL::ComPtr<ID3D11Device> d3d11Device;
|
||||||
UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||||
D3D11On12CreateDevice(
|
auto pCommandQueue = reinterpret_cast<IUnknown**>(mCommandQueue.GetAddressOf());
|
||||||
mDevice.Get(),
|
if (FAILED(D3D11On12CreateDevice(mD3dDevice.Get(), d3d11DeviceFlags, nullptr, 0, pCommandQueue, 1, 0, &d3d11Device, &mD3d11DeviceContext, nullptr)))
|
||||||
d3d11DeviceFlags,
|
{
|
||||||
nullptr,
|
MLOG_ERROR("Failed to create D3D11 on 12 Device");
|
||||||
0,
|
return false;
|
||||||
reinterpret_cast<IUnknown**>(mCommandQueue.GetAddressOf()),
|
}
|
||||||
1,
|
|
||||||
0,
|
|
||||||
&d3d11Device,
|
|
||||||
&mD3d11DeviceContext,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
d3d11Device.As(&mD3d11On12Device);
|
d3d11Device.As(&mD3d11On12Device);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32DxInterface::initializeDirectWrite()
|
bool Win32DxInterface::initializeDirectWrite()
|
||||||
{
|
{
|
||||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory);
|
return SUCCEEDED(::DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &mDWriteFactory));
|
||||||
return true;
|
|
||||||
}
|
}
|
|
@ -21,24 +21,24 @@ struct ID2D1DeviceContext2;
|
||||||
class Win32DxInterface
|
class Win32DxInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ID3D12Device* getDevice() const;
|
IDXGIFactory7* getDxgiFactory() const;
|
||||||
ID3D11On12Device* get11On12Device() const;
|
ID3D12Device* getD3dDevice() const;
|
||||||
ID3D11DeviceContext* getD3d11DeviceContext() const;
|
|
||||||
|
|
||||||
IDXGIFactory7* getFactory() const;
|
|
||||||
|
|
||||||
ID2D1Factory3* getD2dFactory() const;
|
|
||||||
ID2D1DeviceContext2* getD2dContext() const;
|
|
||||||
|
|
||||||
ID3D12CommandQueue* getCommandQueue() const;
|
ID3D12CommandQueue* getCommandQueue() const;
|
||||||
|
|
||||||
|
ID3D11On12Device* get11On12Device() const;
|
||||||
|
ID3D11DeviceContext* getD3d11DeviceContext() const;
|
||||||
|
ID2D1Factory3* getD2dFactory() const;
|
||||||
|
ID2D1DeviceContext2* getD2dContext() const;
|
||||||
IDWriteFactory* getDirectWriteFactory() const;
|
IDWriteFactory* getDirectWriteFactory() const;
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool createD3dFactory();
|
||||||
|
bool createD3dDevice(IDXGIAdapter1* ppAdapter);
|
||||||
|
bool createCommandQueue();
|
||||||
|
|
||||||
void getHardwareAdapter(IDXGIAdapter1** ppAdapter);
|
void getHardwareAdapter(IDXGIAdapter1** ppAdapter);
|
||||||
|
|
||||||
bool initializeD2d();
|
bool initializeD2d();
|
||||||
|
@ -47,16 +47,15 @@ private:
|
||||||
|
|
||||||
bool mIsValid{ false };
|
bool mIsValid{ false };
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IDXGIFactory7> mFactory;
|
Microsoft::WRL::ComPtr<IDXGIFactory7> mDxgiFactory;
|
||||||
Microsoft::WRL::ComPtr<ID3D12Device> mDevice;
|
Microsoft::WRL::ComPtr<ID3D12Device> mD3dDevice;
|
||||||
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
|
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
|
||||||
|
|
||||||
|
// 2D Rendering - e.g. text
|
||||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3d11DeviceContext;
|
Microsoft::WRL::ComPtr<ID3D11DeviceContext> mD3d11DeviceContext;
|
||||||
Microsoft::WRL::ComPtr<ID3D11On12Device> mD3d11On12Device;
|
Microsoft::WRL::ComPtr<ID3D11On12Device> mD3d11On12Device;
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ID2D1Factory3> mD2dFactory;
|
Microsoft::WRL::ComPtr<ID2D1Factory3> mD2dFactory;
|
||||||
Microsoft::WRL::ComPtr<ID2D1Device2> mD2dDevice;
|
Microsoft::WRL::ComPtr<ID2D1Device2> mD2dDevice;
|
||||||
Microsoft::WRL::ComPtr<ID2D1DeviceContext2> mD2dDeviceContext;
|
Microsoft::WRL::ComPtr<ID2D1DeviceContext2> mD2dDeviceContext;
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IDWriteFactory> mDWriteFactory;
|
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