Initial directx example.

This commit is contained in:
jmsgrogan 2023-01-03 20:33:18 +00:00
parent 1dfbcc61c4
commit 92d1f24613
28 changed files with 683 additions and 212 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
.cproject
.project
.pydevproject
.vscode
.settings/
/Debug/
/build/

View file

@ -1,11 +1,6 @@
add_subdirectory(notes_tk)
add_subdirectory(website-generator)
# Experimental Below
if(WIN32)
add_subdirectory(directx-practice)
endif()
# Sample Console
add_executable(notes_tk_console main.cpp)
target_link_libraries(notes_tk_console PUBLIC console core network database geometry audio web)

View file

@ -1,16 +0,0 @@
list(APPEND directx_practice_LIB_INCLUDES
)
add_executable(directx-practice WIN32 directx-practice.cpp ${directx_practice_LIB_INCLUDES})
target_include_directories(directx-practice PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
)
target_link_libraries(directx-practice PUBLIC core D3D12.lib DXGI.lib)
set_property(TARGET directx-practice PROPERTY FOLDER apps/directx-practice)

View file

@ -1,111 +0,0 @@
#include "loggers/FileLogger.h"
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <iostream>
#include <vector>
#include <windows.h>
#include <wrl.h>
#include <dxgi.h>
#include <dxgi1_6.h>
#include <d3d12.h>
#include <d3d12sdklayers.h>
void GetHardwareAdapter(IDXGIFactory7* pFactory, IDXGIAdapter1** ppAdapter)
{
*ppAdapter = nullptr;
for (UINT adapterIndex = 0; ; ++adapterIndex)
{
IDXGIAdapter1* pAdapter = nullptr;
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
{
// No more adapters to enumerate.
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)))
{
*ppAdapter = pAdapter;
return;
}
pAdapter->Release();
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
FileLogger::GetInstance().Open();
MLOG_INFO("Test");
if (!DirectX::XMVerifyCPUSupport())
{
MLOG_ERROR("Directx math not supported");
return 0;
}
auto n = DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
//auto u = DirectX::XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
//auto v = DirectX::XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);
//auto w = DirectX::XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);
auto p = DirectX::XMVectorZero();
auto q = DirectX::XMVectorSplatOne();
auto u = DirectX::XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
auto v = DirectX::XMVectorReplicate(-2.0f);
auto w = DirectX::XMVectorSplatZ(u);
DirectX::XMMATRIX A(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 4.0f, 0.0f,
1.0f, 2.0f, 3.0f, 1.0f);
DirectX::XMMATRIX B = DirectX::XMMatrixIdentity();
IDXGIAdapter* adapter = nullptr;
std::vector<IDXGIAdapter*> adapterList;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
#if defined(DEBUG) || defined(_DEBUG)
// Enable the D3D12 debug layer.
{
ID3D12Debug* debugController;
D3D12GetDebugInterface(IID_PPV_ARGS(&debugController));
debugController->EnableDebugLayer();
}
#endif
IDXGIFactory7* pFactory{ nullptr };
HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory7), (void**)(&pFactory));
if (hr == S_OK)
{
MLOG_INFO("FACTORY IS OK");
}
IDXGIAdapter1* pAdapter{ nullptr };
GetHardwareAdapter(pFactory, &pAdapter);
ID3D12Device* pDevice{ nullptr };
if (pAdapter)
{
MLOG_INFO("Found adapter");
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&pDevice))))
{
MLOG_INFO("Got device");
}
}
else
{
MLOG_INFO("No adapter found");
return 0;
}
return 0;
}

View file

@ -16,8 +16,8 @@
#include "DesktopManager.h"
#include "MainApplication.h"
NotesTk::NotesTk(std::unique_ptr<CommandLineArgs> args)
: GuiApplication(std::move(args))
NotesTk::NotesTk(std::unique_ptr<CommandLineArgs> args, std::unique_ptr<MainApplication> mainApp)
: GuiApplication(std::move(args), std::move(mainApp))
{
}

View file

@ -5,7 +5,7 @@
class NotesTk : public GuiApplication
{
public:
NotesTk(std::unique_ptr<CommandLineArgs> args);
NotesTk(std::unique_ptr<CommandLineArgs> args = nullptr, std::unique_ptr<MainApplication> mainApp = nullptr);
protected:
void initializeViews() override;

View file

@ -3,11 +3,12 @@
#endif
#include "MainApplication.h"
#include "GuiApplication.h"
#include "NotesTk.h"
#include "CommandLineArgs.h"
#include "Win32WindowInterface.h"
#include "FileLogger.h"
#include "StringUtils.h"
#include "Widget.h"
#include "windows.h"
@ -55,13 +56,11 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
MLOG_INFO("Creating GUI Application");
// Start the gui application
auto gui_app = GuiApplication();
//gui_app.setMainApplication(main_app);
auto gui_app = NotesTk(nullptr, std::move(main_app));
MLOG_INFO("Running GUI Application");
gui_app.run();
main_app->shutDown();
return 0;
}

View file

@ -111,7 +111,7 @@ void WasapiInterface::play(AudioDevice* device, AudioSample* sample, unsigned du
// hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &deviceName);
hr = pPropertyStore->GetValue(PKEY_DeviceInterface_FriendlyName, &deviceName);
//PKEY_Device_FriendlyName
std::cout << "Device name: " << deviceName.pwszVal << std::endl;
//std::cout << "Device name: " << deviceName.pwszVal << std::endl;
pPropertyStore->Release();

View file

@ -11,13 +11,20 @@
#include "FileLogger.h"
GuiApplication::GuiApplication(std::unique_ptr<CommandLineArgs> args)
GuiApplication::GuiApplication(std::unique_ptr<CommandLineArgs> args, std::unique_ptr<MainApplication> mainApp)
: AbstractDesktopApp(),
mMainApplication(MainApplication::Create()),
mDesktopManager(DesktopManager::Create(this))
{
if (mainApp)
{
mMainApplication = std::move(mainApp);
}
else
{
mMainApplication = MainApplication::Create();
mMainApplication->initialize(args ? std::move(args) : CommandLineArgs::Create());
}
}
GuiApplication::~GuiApplication()
{

View file

@ -13,7 +13,7 @@ class AbstractUiInterface;
class GuiApplication : public AbstractDesktopApp
{
public:
GuiApplication(std::unique_ptr<CommandLineArgs> args = nullptr);
GuiApplication(std::unique_ptr<CommandLineArgs> args = nullptr, std::unique_ptr<MainApplication> mainApp = nullptr);
~GuiApplication();

View file

@ -20,7 +20,8 @@ std::unique_ptr<SqliteInterface> SqliteInterface::Create()
void SqliteInterface::open(Database* db)
{
int rc = sqlite3_open(db->getPath().c_str(), &mSqliteDb);
const auto path = db->getPath().string();
int rc = sqlite3_open(path.c_str(), &mSqliteDb);
if( rc )
{
MLOG_ERROR("Can't open database: %s\n" << sqlite3_errmsg(mSqliteDb));

View file

@ -42,6 +42,11 @@ if (OpenGL_FOUND)
else()
message(STATUS "OpenGL not found - skipping support")
endif()
else()
list(APPEND graphics_LIB_INCLUDES
directx/DirectXPainter.cpp)
list(APPEND graphics_HEADERS
directx/DirectXPainter.h)
endif()
add_library(${MODULE_NAME} SHARED

View file

View file

View file

@ -34,7 +34,6 @@ public:
virtual void clear() = 0;
virtual void onResize(unsigned width, unsigned height) = 0;
protected:
mt::Window* mWindow{nullptr};
};

View file

@ -58,10 +58,20 @@ 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
)
list(APPEND platform_LIBS D3D12.lib D3DCompiler.lib DXGI.lib)
find_package(DirectX-Headers REQUIRED)
list(APPEND platform_LIBS Microsoft::DirectX-Headers)
endif()
list(APPEND windows_LIB_INCLUDES
ui_interfaces/AbstractUiInterface.h
ui_interfaces/UiInterfaceFactory.cpp
managers/WindowManager.cpp
managers/DesktopManager.cpp

View file

@ -45,6 +45,6 @@ std::unique_ptr<AbstractUIInterface> UiInterfaceFactory::create(DesktopManager*
#endif
}
#else
return std::make_unique<Win32UIInterface>(desktopManager, std::move(fonts_manager));
return std::make_unique<Win32UIInterface>(desktopManager, std::move(fonts_manager), true);
#endif
}

View file

@ -0,0 +1,91 @@
#include "Win32DxInterface.h"
#include "FileLogger.h"
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <dxgi.h>
#include <dxgi1_6.h>
#include <d3d12.h>
#include <d3d12sdklayers.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))
{
// No more adapters to enumerate.
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)))
{
*ppAdapter = pAdapter;
return;
}
pAdapter->Release();
}
}
ID3D12Device* Win32DxInterface::getDevice() const
{
return mDevice.Get();
}
IDXGIFactory7* Win32DxInterface::getFactory() const
{
return mFactory.Get();
}
void Win32DxInterface::initialize()
{
if (!DirectX::XMVerifyCPUSupport())
{
MLOG_ERROR("Directx math not supported");
return;
}
#if defined(DEBUG) || defined(_DEBUG)
// Enable the D3D12 debug layer.
{
ID3D12Debug* debugController;
D3D12GetDebugInterface(IID_PPV_ARGS(&debugController));
debugController->EnableDebugLayer();
}
#endif
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory7), (void**)(&mFactory));
if (hr == S_OK)
{
MLOG_INFO("FACTORY IS OK");
}
IDXGIAdapter1* pAdapter{ nullptr };
getHardwareAdapter(&pAdapter);
if (pAdapter)
{
MLOG_INFO("Found adapter");
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&mDevice))))
{
MLOG_INFO("Got device");
}
}
else
{
MLOG_INFO("No adapter found");
return;
}
return;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <wrl.h>
struct ID3D12Device;
struct IDXGIFactory7;
struct IDXGIAdapter1;
class Win32DxInterface
{
public:
void initialize();
ID3D12Device* getDevice() const;
IDXGIFactory7* getFactory() const;
private:
void getHardwareAdapter(IDXGIAdapter1** ppAdapter);
Microsoft::WRL::ComPtr<IDXGIFactory7> mFactory;
Microsoft::WRL::ComPtr<ID3D12Device> mDevice;
};

View file

@ -0,0 +1,304 @@
#include "Win32DxWindowInterface.h"
#include "Win32DxInterface.h"
#include "Win32Window.h"
#include "Window.h"
#include "Widget.h"
#include <dxgi.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h>
#include <d3d12sdklayers.h>
Win32DxWindowInterface::Win32DxWindowInterface(Win32DxInterface* dxInterface)
: mDxInterface(dxInterface)
{
}
Win32DxWindowInterface::~Win32DxWindowInterface()
{
}
void Win32DxWindowInterface::destroyWindow()
{
waitForPreviousFrame();
::CloseHandle(mFenceEvent);
}
void Win32DxWindowInterface::onRender()
{
// Record all the commands we need to render the scene into the command list.
populateCommandList();
// Execute the command list.
ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() };
mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// Present the frame.
mSwapChain->Present(1, 0);
waitForPreviousFrame();
}
void Win32DxWindowInterface::populateCommandList()
{
// 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(), mPipelineState.Get());
// Set necessary state.
mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
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);
// Record commands.
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
mCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
mCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
mCommandList->IASetVertexBuffers(0, 1, &mVertexBufferView);
mCommandList->DrawInstanced(3, 1, 0, 0);
// Indicate that the back buffer will now be used to present.
barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
mCommandList->ResourceBarrier(1, &barrier);
mCommandList->Close();
}
bool Win32DxWindowInterface::initialize(mt::Window* window)
{
if (mInitialized)
{
return true;
}
const auto width = window->getWidth();
const auto height = window->getHeight();
mViewport = CD3DX12_VIEWPORT(0.0f, 0.0f, width, height);
mScissorRect = CD3DX12_RECT(0, 0, width, height);
loadPipeline(window);
loadAssets();
return true;
}
void Win32DxWindowInterface::loadPipeline(mt::Window* window)
{
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
mDxInterface->getDevice()->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.BufferCount = FrameCount;
const auto width = window->getWidth();
const auto height = window->getHeight();
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;
const auto hwnd = dynamic_cast<Win32Window*>(window->getPlatformWindow())->getHandle();
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
mDxInterface->getFactory()->CreateSwapChainForHwnd(
mCommandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it.
hwnd,
&swapChainDesc,
nullptr,
nullptr,
&swapChain
);
mDxInterface->getFactory()->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
swapChain.As(&mSwapChain);
auto mFrameIndex = mSwapChain->GetCurrentBackBufferIndex();
// Create descriptor heaps.
{
// Describe and create a render target view (RTV) descriptor heap.
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));
mRtvDescriptorSize = mDxInterface->getDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
// Create frame resources.
{
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
// Create a RTV for each frame.
for (UINT n = 0; n < FrameCount; n++)
{
mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargets[n]));
mDxInterface->getDevice()->CreateRenderTargetView(mRenderTargets[n].Get(), nullptr, rtvHandle);
rtvHandle.Offset(1, mRtvDescriptorSize);
}
}
mDxInterface->getDevice()->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandAllocator));
}
void Win32DxWindowInterface::loadAssets()
{
// Create an empty root signature.
{
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
Microsoft::WRL::ComPtr<ID3DBlob> signature;
Microsoft::WRL::ComPtr<ID3DBlob> error;
D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
mDxInterface->getDevice()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&mRootSignature));
}
// Create the pipeline state, which includes compiling and loading shaders.
{
Microsoft::WRL::ComPtr<ID3DBlob> vertexShader;
Microsoft::WRL::ComPtr<ID3DBlob> pixelShader;
#if defined(_DEBUG)
// Enable better shader debugging with the graphics debugging tools.
// UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
UINT compileFlags = 0;
#else
UINT compileFlags = 0;
#endif
auto shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders.hlsl";
D3DCompileFromFile(shader_path.c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr);
D3DCompileFromFile(shader_path.c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr);
// Define the vertex input layout.
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
// Describe and create the graphics pipeline state object (PSO).
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
psoDesc.pRootSignature = mRootSignature.Get();
psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState.DepthEnable = FALSE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.SampleMask = UINT_MAX;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
psoDesc.SampleDesc.Count = 1;
mDxInterface->getDevice()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&mPipelineState));
}
// Create the command list.
mDxInterface->getDevice()->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), mPipelineState.Get(), IID_PPV_ARGS(&mCommandList));
// 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();
// Create the vertex buffer.
{
// Define the geometry for a triangle.
const float aspectRatio = 1.0;
Vertex triangleVertices[] =
{
{ { 0.0f, 0.25f * aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
{ { 0.25f, -0.25f * aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { -0.25f, -0.25f * aspectRatio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
};
const UINT vertexBufferSize = sizeof(triangleVertices);
// Note: using upload heaps to transfer static data like vert buffers is not
// recommended. Every time the GPU needs it, the upload heap will be marshalled
// over. Please read up on Default Heap usage. An upload heap is used here for
// code simplicity and because there are very few verts to actually transfer.
CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD);
auto desc = CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize);
mDxInterface->getDevice()->CreateCommittedResource(
&heapProps,
D3D12_HEAP_FLAG_NONE,
&desc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&mVertexBuffer));
// Copy the triangle data to the vertex buffer.
UINT8* pVertexDataBegin;
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
mVertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin));
memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
mVertexBuffer->Unmap(0, nullptr);
// Initialize the vertex buffer view.
mVertexBufferView.BufferLocation = mVertexBuffer->GetGPUVirtualAddress();
mVertexBufferView.StrideInBytes = sizeof(Vertex);
mVertexBufferView.SizeInBytes = vertexBufferSize;
}
// Create synchronization objects and wait until assets have been uploaded to the GPU.
{
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;
mCommandQueue->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();
}

View file

@ -0,0 +1,87 @@
#pragma once
#include <memory>
#include <wrl.h>
#include <d3d12.h>
#include <directxmath.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;
class Win32DxWindowInterface
{
public:
Win32DxWindowInterface(Win32DxInterface* dxInterface);
~Win32DxWindowInterface();
bool initialize(mt::Window* window);
void onRender();
//void afterPaint();
//void resizeViewPort(unsigned width, unsigned height);
private:
void loadPipeline(mt::Window* window);
void loadAssets();
void populateCommandList();
void waitForPreviousFrame();
void destroyWindow();
static const UINT FrameCount = 2;
Win32DxInterface* mDxInterface{ nullptr };
bool mInitialized{ false };
struct Vertex
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT4 color;
};
CD3DX12_VIEWPORT mViewport;
CD3DX12_RECT mScissorRect;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mCommandAllocator;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;
Microsoft::WRL::ComPtr<IDXGISwapChain4> mSwapChain;
Microsoft::WRL::ComPtr<ID3D12RootSignature> mRootSignature;
Microsoft::WRL::ComPtr<ID3D12PipelineState> mPipelineState;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
UINT mRtvDescriptorSize{ 0 };
Microsoft::WRL::ComPtr<ID3D12Resource> mRenderTargets[FrameCount];
Microsoft::WRL::ComPtr<ID3D12Resource> mVertexBuffer;
D3D12_VERTEX_BUFFER_VIEW mVertexBufferView{};
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>;

View file

@ -1,5 +1,12 @@
#include "Win32UIInterface.h"
#include "Widget.h"
#include "DesktopManager.h"
#include "Win32DxInterface.h"
#include <d3d12.h>
#include <dxgi.h>
#include <dxgi1_6.h>
#include <Windows.h>
Win32UIInterface::Win32UIInterface(DesktopManager* desktopManager, std::unique_ptr<FontsManager> fontsManager, bool useHardware)
@ -11,11 +18,23 @@ Win32UIInterface::Win32UIInterface(DesktopManager* desktopManager, std::unique_p
void Win32UIInterface::initialize()
{
if (mUseHardwareRendering)
{
initializeHardwareRendering();
}
const auto num_windows = mDesktopManager->getWindowManager()->getNumWindows();
for (std::size_t idx = 0; idx < num_windows; idx++)
{
addWindow(mDesktopManager->getWindowManager()->getWindow(idx));
}
showWindow(mDesktopManager->getWindowManager()->getMainWindow());
}
void Win32UIInterface::loop()
{
initialize();
// Run the message loop.
MSG msg = { };
while (::GetMessage(&msg, NULL, 0, 0))
@ -32,10 +51,16 @@ void Win32UIInterface::shutDown()
void Win32UIInterface::showWindow(mt::Window* window)
{
mWindowInterface->Show(window);
mWindowInterface->show(window);
}
void Win32UIInterface::addWindow(mt::Window* window)
{
mWindowInterface->Add(window, mDesktopManager);
mWindowInterface->add(window, mDesktopManager, mDxInterface.get());
}
void Win32UIInterface::initializeHardwareRendering()
{
mDxInterface = std::make_unique<Win32DxInterface>();
mDxInterface->initialize();
}

View file

@ -7,6 +7,9 @@
class DesktopManager;
class Win32DxInterface;
using Win32DxInterfacePtr = std::unique_ptr<Win32DxInterface>;
class Win32UIInterface : public AbstractUIInterface
{
public:
@ -14,6 +17,8 @@ public:
~Win32UIInterface() = default;
void addWindow(mt::Window* window) override;
void initialize() override;
void loop() override;
@ -22,9 +27,8 @@ public:
void showWindow(mt::Window* window) override;
void addWindow(mt::Window* window) override;
private:
void initializeHardwareRendering() override;
Win32WindowInterfacePtr mWindowInterface;
Win32DxInterfacePtr mDxInterface;
};

View file

@ -1,33 +1,40 @@
#include "Win32Window.h"
#include "Win32WindowInterface.h"
#include "Win32DxInterface.h"
#include "Win32DxWindowInterface.h"
#include <WinUser.h>
#include "FileLogger.h"
#include "StringUtils.h"
#include "Widget.h"
#include "ui_events\KeyboardEvent.h"
#include "KeyboardEvent.h"
#include "DesktopManager.h"
#include <WinUser.h>
LRESULT CALLBACK FreeWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Win32Window::Win32Window(mt::Window* window)
Win32Window::Win32Window(mt::Window* window, Win32DxInterface* dxInterface)
: IPlatformWindow(window)
{
}
std::unique_ptr<Win32Window> Win32Window::Create(mt::Window* window)
if (dxInterface)
{
return std::make_unique<Win32Window>(window);
mDxInterface = std::make_unique<Win32DxWindowInterface>(dxInterface);
}
}
HWND Win32Window::GetHandle() const
std::unique_ptr<Win32Window> Win32Window::Create(mt::Window* window, Win32DxInterface* dxInterface)
{
return std::make_unique<Win32Window>(window, dxInterface);
}
HWND Win32Window::getHandle() const
{
return mHandle;
}
void Win32Window::CreateNative(Win32ApplicationContext* context, DesktopManager* desktopManager)
void Win32Window::createNative(Win32ApplicationContext* context, DesktopManager* desktopManager)
{
mDesktopManager = desktopManager;
@ -45,7 +52,7 @@ void Win32Window::CreateNative(Win32ApplicationContext* context, DesktopManager*
mHandle = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
"Media Tool", // Window text
"Notes TK", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
@ -94,6 +101,12 @@ LRESULT CALLBACK Win32Window::WindowProc(UINT message, WPARAM wParam, LPARAM lPa
}
case WM_PAINT:
{
if (mDxInterface)
{
mDxInterface->onRender();
}
else
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(mHandle, &ps);
@ -106,6 +119,7 @@ LRESULT CALLBACK Win32Window::WindowProc(UINT message, WPARAM wParam, LPARAM lPa
EndPaint(mHandle, &ps);
}
}
}
return DefWindowProc(mHandle, message, wParam, lParam);
}
@ -132,9 +146,17 @@ static LRESULT CALLBACK FreeWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
if (window)
{
window->SetHandle(hwnd);
window->setHandle(hwnd);
return window->WindowProc(uMsg, wParam, lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void Win32Window::beforePaint(mt::Screen* screen)
{
if (mDxInterface)
{
mDxInterface->initialize(mWindow);
}
}

View file

@ -4,36 +4,38 @@
#include <Windows.h>
class Win32ApplicationContext;
class Win32DxInterface;
class Win32DxWindowInterface;
class DesktopManager;
class Win32Window : public IPlatformWindow
{
public:
Win32Window(mt::Window* window);
Win32Window(mt::Window* window, Win32DxInterface* dxInterface = nullptr);
virtual ~Win32Window() = default;
static std::unique_ptr<Win32Window> Create(mt::Window* window);
static std::unique_ptr<Win32Window> Create(mt::Window* window, Win32DxInterface* dxInterface = nullptr);
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
HWND GetHandle() const;
HWND getHandle() const;
void SetHandle(HWND handle)
void setHandle(HWND handle)
{
mHandle = handle;
}
int GetCmdShow() const
int getCmdShow() const
{
return mCmdShow;
}
void SetCmdShow(int cmdShow)
void setCmdShow(int cmdShow)
{
mCmdShow = cmdShow;
}
void CreateNative(Win32ApplicationContext* context, DesktopManager* desktopManager);
void createNative(Win32ApplicationContext* context, DesktopManager* desktopManager);
void show() {};
@ -43,10 +45,7 @@ public:
void onResize(unsigned width, unsigned height) {};
void beforePaint(mt::Screen* screen)
{
}
void beforePaint(mt::Screen* screen);
void afterPaint(mt::Screen* screen)
{
@ -56,5 +55,6 @@ public:
private:
HWND mHandle{ 0 };
int mCmdShow{ 0 };
DesktopManager* mDesktopManager;
DesktopManager* mDesktopManager{ nullptr };
std::unique_ptr<Win32DxWindowInterface> mDxInterface;
};

View file

@ -1,33 +1,36 @@
#include "Win32WindowInterface.h"
#include "Win32Window.h"
#include <Windows.h>
#include "DesktopManager.h"
#include "DrawingContext.h"
#include "Win32DxInterface.h"
#include "Widget.h"
#include "FileLogger.h"
#include <Windows.h>
Win32WindowInterface::Win32WindowInterface()
{
}
void Win32WindowInterface::Show(mt::Window* window)
void Win32WindowInterface::show(mt::Window* window)
{
auto platformWindow = dynamic_cast<Win32Window*>(window->getPlatformWindow());
MLOG_INFO("Showing platform window: " << platformWindow->GetHandle());
::ShowWindow(platformWindow->GetHandle(), platformWindow->GetCmdShow());
MLOG_INFO("Showing platform window: " << platformWindow->getHandle());
::ShowWindow(platformWindow->getHandle(), platformWindow->getCmdShow());
}
void Win32WindowInterface::Add(mt::Window* window, DesktopManager* desktopManager)
void Win32WindowInterface::add(mt::Window* window, DesktopManager* desktopManager, Win32DxInterface* dxInterface)
{
auto context = dynamic_cast<Win32ApplicationContext*>(desktopManager->getMainApp()->GetApplicationContext());
auto win32_window = Win32Window::Create(window);
win32_window->CreateNative(context, desktopManager);
win32_window->SetCmdShow(context->nCmdShow);
auto win32_window = Win32Window::Create(window, dxInterface);
win32_window->createNative(context, desktopManager);
win32_window->setCmdShow(context->nCmdShow);
window->setPlatformWindow(std::move(win32_window), nullptr, DrawingMode::GRAPH);
window->getPlatformWindow()->beforePaint(nullptr);
}

View file

@ -9,6 +9,7 @@
class DesktopManager;
class FontsManager;
class Win32DxInterface;
class Win32ApplicationContext : public IApplicationContext
{
@ -22,9 +23,9 @@ class Win32WindowInterface
public:
Win32WindowInterface();
void Add(mt::Window* window, DesktopManager* desktopManager);
void add(mt::Window* window, DesktopManager* desktopManager, Win32DxInterface* dxInterface = nullptr);
void Show(mt::Window* window);
void show(mt::Window* window);
};
using Win32WindowInterfacePtr = std::unique_ptr<Win32WindowInterface>;

View file

@ -0,0 +1,20 @@
struct PSInput
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
PSInput VSMain(float4 position : POSITION, float4 color : COLOR)
{
PSInput result;
result.position = position;
result.color = color;
return result;
}
float4 PSMain(PSInput input) : SV_TARGET
{
return input.color;
}