From 92d1f24613e006823cf2e209fb68df111fecd5a6 Mon Sep 17 00:00:00 2001 From: jmsgrogan Date: Tue, 3 Jan 2023 20:33:18 +0000 Subject: [PATCH] Initial directx example. --- .gitignore | 1 + apps/CMakeLists.txt | 5 - apps/directx-practice/CMakeLists.txt | 16 - apps/directx-practice/directx-practice.cpp | 111 ------- apps/notes_tk/NotesTk.cpp | 4 +- apps/notes_tk/NotesTk.h | 2 +- apps/notes_tk/main-win.cpp | 7 +- .../audio_interfaces/WasapiInterface.cpp | 2 +- src/client/GuiApplication.cpp | 13 +- src/client/GuiApplication.h | 2 +- .../database_interfaces/SqliteInterface.cpp | 3 +- src/graphics/CMakeLists.txt | 45 +-- src/graphics/directx/DirectXPainter.cpp | 0 src/graphics/directx/DirectXPainter.h | 0 .../desktop_elements/IPlatformWindow.h | 1 - src/windows/CMakeLists.txt | 10 + .../ui_interfaces/UiInterfaceFactory.cpp | 2 +- .../ui_interfaces/win32/Win32DxInterface.cpp | 91 ++++++ .../ui_interfaces/win32/Win32DxInterface.h | 24 ++ .../win32/Win32DxWindowInterface.cpp | 304 ++++++++++++++++++ .../win32/Win32DxWindowInterface.h | 87 +++++ .../ui_interfaces/win32/Win32UIInterface.cpp | 29 +- .../ui_interfaces/win32/Win32UIInterface.h | 10 +- .../ui_interfaces/win32/Win32Window.cpp | 54 +++- src/windows/ui_interfaces/win32/Win32Window.h | 24 +- .../win32/Win32WindowInterface.cpp | 23 +- .../win32/Win32WindowInterface.h | 5 +- src/windows/ui_interfaces/win32/shaders.hlsl | 20 ++ 28 files changed, 683 insertions(+), 212 deletions(-) delete mode 100644 apps/directx-practice/CMakeLists.txt delete mode 100644 apps/directx-practice/directx-practice.cpp create mode 100644 src/graphics/directx/DirectXPainter.cpp create mode 100644 src/graphics/directx/DirectXPainter.h create mode 100644 src/windows/ui_interfaces/win32/Win32DxInterface.cpp create mode 100644 src/windows/ui_interfaces/win32/Win32DxInterface.h create mode 100644 src/windows/ui_interfaces/win32/Win32DxWindowInterface.cpp create mode 100644 src/windows/ui_interfaces/win32/Win32DxWindowInterface.h create mode 100644 src/windows/ui_interfaces/win32/shaders.hlsl diff --git a/.gitignore b/.gitignore index d9bfa54..ce22109 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .cproject .project .pydevproject +.vscode .settings/ /Debug/ /build/ diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 304c8d8..22f274c 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -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) diff --git a/apps/directx-practice/CMakeLists.txt b/apps/directx-practice/CMakeLists.txt deleted file mode 100644 index 46d253f..0000000 --- a/apps/directx-practice/CMakeLists.txt +++ /dev/null @@ -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) - diff --git a/apps/directx-practice/directx-practice.cpp b/apps/directx-practice/directx-practice.cpp deleted file mode 100644 index 678e5c0..0000000 --- a/apps/directx-practice/directx-practice.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "loggers/FileLogger.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - - -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 adapterList; - - Microsoft::WRL::ComPtr 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; -} \ No newline at end of file diff --git a/apps/notes_tk/NotesTk.cpp b/apps/notes_tk/NotesTk.cpp index e6d986b..701e0cd 100644 --- a/apps/notes_tk/NotesTk.cpp +++ b/apps/notes_tk/NotesTk.cpp @@ -16,8 +16,8 @@ #include "DesktopManager.h" #include "MainApplication.h" -NotesTk::NotesTk(std::unique_ptr args) - : GuiApplication(std::move(args)) +NotesTk::NotesTk(std::unique_ptr args, std::unique_ptr mainApp) + : GuiApplication(std::move(args), std::move(mainApp)) { } diff --git a/apps/notes_tk/NotesTk.h b/apps/notes_tk/NotesTk.h index a7139e8..29e0567 100644 --- a/apps/notes_tk/NotesTk.h +++ b/apps/notes_tk/NotesTk.h @@ -5,7 +5,7 @@ class NotesTk : public GuiApplication { public: - NotesTk(std::unique_ptr args); + NotesTk(std::unique_ptr args = nullptr, std::unique_ptr mainApp = nullptr); protected: void initializeViews() override; diff --git a/apps/notes_tk/main-win.cpp b/apps/notes_tk/main-win.cpp index 697c017..1dac674 100644 --- a/apps/notes_tk/main-win.cpp +++ b/apps/notes_tk/main-win.cpp @@ -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; } diff --git a/src/audio/audio_interfaces/WasapiInterface.cpp b/src/audio/audio_interfaces/WasapiInterface.cpp index 6df7c30..eaae01c 100644 --- a/src/audio/audio_interfaces/WasapiInterface.cpp +++ b/src/audio/audio_interfaces/WasapiInterface.cpp @@ -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(); diff --git a/src/client/GuiApplication.cpp b/src/client/GuiApplication.cpp index 7d8ce05..8f6d270 100644 --- a/src/client/GuiApplication.cpp +++ b/src/client/GuiApplication.cpp @@ -11,12 +11,19 @@ #include "FileLogger.h" -GuiApplication::GuiApplication(std::unique_ptr args) +GuiApplication::GuiApplication(std::unique_ptr args, std::unique_ptr mainApp) : AbstractDesktopApp(), - mMainApplication(MainApplication::Create()), mDesktopManager(DesktopManager::Create(this)) { - mMainApplication->initialize(args ? std::move(args) : CommandLineArgs::Create()); + if (mainApp) + { + mMainApplication = std::move(mainApp); + } + else + { + mMainApplication = MainApplication::Create(); + mMainApplication->initialize(args ? std::move(args) : CommandLineArgs::Create()); + } } GuiApplication::~GuiApplication() diff --git a/src/client/GuiApplication.h b/src/client/GuiApplication.h index a32b62f..2d9cbf4 100644 --- a/src/client/GuiApplication.h +++ b/src/client/GuiApplication.h @@ -13,7 +13,7 @@ class AbstractUiInterface; class GuiApplication : public AbstractDesktopApp { public: - GuiApplication(std::unique_ptr args = nullptr); + GuiApplication(std::unique_ptr args = nullptr, std::unique_ptr mainApp = nullptr); ~GuiApplication(); diff --git a/src/database/database_interfaces/SqliteInterface.cpp b/src/database/database_interfaces/SqliteInterface.cpp index 955a437..5de71f3 100644 --- a/src/database/database_interfaces/SqliteInterface.cpp +++ b/src/database/database_interfaces/SqliteInterface.cpp @@ -20,7 +20,8 @@ std::unique_ptr 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)); diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index 968a3e7..44d3edc 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -21,27 +21,32 @@ list(APPEND graphics_HEADERS PainterFactory.h ) if(UNIX) -set(OpenGL_GL_PREFERENCE "GLVND") -find_package(OpenGL QUIET) -if (OpenGL_FOUND) - list(APPEND platform_LIBS OpenGL::GL OpenGL::GLU) - list(APPEND graphics_LIB_INCLUDES - opengl/OpenGlPainter.cpp - opengl/OpenGlTextPainter.cpp - opengl/OpenGlMeshPainter.cpp - opengl/OpenGlFontTexture.cpp - opengl/OpenGlShaderProgram.cpp - ) - list(APPEND ${MODULE_NAME} - opengl/OpenGlPainter.h - opengl/OpenGlTextPainter.h - opengl/OpenGlMeshPainter.h - opengl/OpenGlFontTexture.h - opengl/OpenGlShaderProgram.h) - list(APPEND DEFINES "HAS_OPENGL") + set(OpenGL_GL_PREFERENCE "GLVND") + find_package(OpenGL QUIET) + if (OpenGL_FOUND) + list(APPEND platform_LIBS OpenGL::GL OpenGL::GLU) + list(APPEND graphics_LIB_INCLUDES + opengl/OpenGlPainter.cpp + opengl/OpenGlTextPainter.cpp + opengl/OpenGlMeshPainter.cpp + opengl/OpenGlFontTexture.cpp + opengl/OpenGlShaderProgram.cpp + ) + list(APPEND ${MODULE_NAME} + opengl/OpenGlPainter.h + opengl/OpenGlTextPainter.h + opengl/OpenGlMeshPainter.h + opengl/OpenGlFontTexture.h + opengl/OpenGlShaderProgram.h) + list(APPEND DEFINES "HAS_OPENGL") + else() + message(STATUS "OpenGL not found - skipping support") + endif() else() - message(STATUS "OpenGL not found - skipping support") -endif() + list(APPEND graphics_LIB_INCLUDES + directx/DirectXPainter.cpp) + list(APPEND graphics_HEADERS + directx/DirectXPainter.h) endif() add_library(${MODULE_NAME} SHARED diff --git a/src/graphics/directx/DirectXPainter.cpp b/src/graphics/directx/DirectXPainter.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/graphics/directx/DirectXPainter.h b/src/graphics/directx/DirectXPainter.h new file mode 100644 index 0000000..e69de29 diff --git a/src/ui_elements/desktop_elements/IPlatformWindow.h b/src/ui_elements/desktop_elements/IPlatformWindow.h index 2f46b54..570ae28 100644 --- a/src/ui_elements/desktop_elements/IPlatformWindow.h +++ b/src/ui_elements/desktop_elements/IPlatformWindow.h @@ -34,7 +34,6 @@ public: virtual void clear() = 0; virtual void onResize(unsigned width, unsigned height) = 0; - protected: mt::Window* mWindow{nullptr}; }; diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index a127447..874f650 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -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 diff --git a/src/windows/ui_interfaces/UiInterfaceFactory.cpp b/src/windows/ui_interfaces/UiInterfaceFactory.cpp index ec29331..3369499 100644 --- a/src/windows/ui_interfaces/UiInterfaceFactory.cpp +++ b/src/windows/ui_interfaces/UiInterfaceFactory.cpp @@ -45,6 +45,6 @@ std::unique_ptr UiInterfaceFactory::create(DesktopManager* #endif } #else - return std::make_unique(desktopManager, std::move(fonts_manager)); + return std::make_unique(desktopManager, std::move(fonts_manager), true); #endif } diff --git a/src/windows/ui_interfaces/win32/Win32DxInterface.cpp b/src/windows/ui_interfaces/win32/Win32DxInterface.cpp new file mode 100644 index 0000000..9f3f516 --- /dev/null +++ b/src/windows/ui_interfaces/win32/Win32DxInterface.cpp @@ -0,0 +1,91 @@ +#include "Win32DxInterface.h" + +#include "FileLogger.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +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; +} \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32DxInterface.h b/src/windows/ui_interfaces/win32/Win32DxInterface.h new file mode 100644 index 0000000..691bb02 --- /dev/null +++ b/src/windows/ui_interfaces/win32/Win32DxInterface.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +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 mFactory; + Microsoft::WRL::ComPtr mDevice; +}; \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32DxWindowInterface.cpp b/src/windows/ui_interfaces/win32/Win32DxWindowInterface.cpp new file mode 100644 index 0000000..89d8241 --- /dev/null +++ b/src/windows/ui_interfaces/win32/Win32DxWindowInterface.cpp @@ -0,0 +1,304 @@ +#include "Win32DxWindowInterface.h" + +#include "Win32DxInterface.h" +#include "Win32Window.h" +#include "Window.h" +#include "Widget.h" + +#include +#include +#include +#include + +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(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(window->getPlatformWindow())->getHandle(); + + Microsoft::WRL::ComPtr 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 signature; + Microsoft::WRL::ComPtr 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 vertexShader; + Microsoft::WRL::ComPtr 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(&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(); +} \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32DxWindowInterface.h b/src/windows/ui_interfaces/win32/Win32DxWindowInterface.h new file mode 100644 index 0000000..f1547f9 --- /dev/null +++ b/src/windows/ui_interfaces/win32/Win32DxWindowInterface.h @@ -0,0 +1,87 @@ +#pragma once + +#include + +#include +#include +#include +#include + +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 mCommandQueue; + Microsoft::WRL::ComPtr mCommandAllocator; + Microsoft::WRL::ComPtr mCommandList; + + Microsoft::WRL::ComPtr mSwapChain; + + Microsoft::WRL::ComPtr mRootSignature; + Microsoft::WRL::ComPtr mPipelineState; + + Microsoft::WRL::ComPtr mRtvHeap; + UINT mRtvDescriptorSize{ 0 }; + + Microsoft::WRL::ComPtr mRenderTargets[FrameCount]; + + Microsoft::WRL::ComPtr mVertexBuffer; + D3D12_VERTEX_BUFFER_VIEW mVertexBufferView{}; + + Microsoft::WRL::ComPtr mFence; + uint64_t mFenceValue = 0; + uint64_t mFrameFenceValues[FrameCount] = {}; + HANDLE mFenceEvent{}; + + uint64_t mFrameIndex{ 0 }; +}; + +using XcbGlWindowInterfacePtr = std::unique_ptr; \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32UIInterface.cpp b/src/windows/ui_interfaces/win32/Win32UIInterface.cpp index 9dd2d30..8fb090d 100644 --- a/src/windows/ui_interfaces/win32/Win32UIInterface.cpp +++ b/src/windows/ui_interfaces/win32/Win32UIInterface.cpp @@ -1,5 +1,12 @@ #include "Win32UIInterface.h" +#include "Widget.h" +#include "DesktopManager.h" +#include "Win32DxInterface.h" + +#include +#include +#include #include Win32UIInterface::Win32UIInterface(DesktopManager* desktopManager, std::unique_ptr 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(); + mDxInterface->initialize(); } \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32UIInterface.h b/src/windows/ui_interfaces/win32/Win32UIInterface.h index 4dff753..994105d 100644 --- a/src/windows/ui_interfaces/win32/Win32UIInterface.h +++ b/src/windows/ui_interfaces/win32/Win32UIInterface.h @@ -7,6 +7,9 @@ class DesktopManager; +class Win32DxInterface; +using Win32DxInterfacePtr = std::unique_ptr; + 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; }; \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32Window.cpp b/src/windows/ui_interfaces/win32/Win32Window.cpp index 4851a73..f9ef4b2 100644 --- a/src/windows/ui_interfaces/win32/Win32Window.cpp +++ b/src/windows/ui_interfaces/win32/Win32Window.cpp @@ -1,33 +1,40 @@ #include "Win32Window.h" #include "Win32WindowInterface.h" +#include "Win32DxInterface.h" +#include "Win32DxWindowInterface.h" -#include #include "FileLogger.h" #include "StringUtils.h" +#include "Widget.h" -#include "ui_events\KeyboardEvent.h" +#include "KeyboardEvent.h" #include "DesktopManager.h" +#include + 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) { - + if (dxInterface) + { + mDxInterface = std::make_unique(dxInterface); + } } -std::unique_ptr Win32Window::Create(mt::Window* window) +std::unique_ptr Win32Window::Create(mt::Window* window, Win32DxInterface* dxInterface) { - return std::make_unique(window); + return std::make_unique(window, dxInterface); } -HWND Win32Window::GetHandle() const +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 @@ -95,15 +102,22 @@ LRESULT CALLBACK Win32Window::WindowProc(UINT message, WPARAM wParam, LPARAM lPa case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(mHandle, &ps); + if (mDxInterface) + { + mDxInterface->onRender(); + } + else + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(mHandle, &ps); - FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); + FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); - auto text = L"Hello World"; - auto val = DrawText(hdc, (LPCSTR)(&text[0]), -1, &ps.rcPaint, 0); + auto text = L"Hello World"; + auto val = DrawText(hdc, (LPCSTR)(&text[0]), -1, &ps.rcPaint, 0); - EndPaint(mHandle, &ps); + 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); + } } \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32Window.h b/src/windows/ui_interfaces/win32/Win32Window.h index 440cb46..b160d2e 100644 --- a/src/windows/ui_interfaces/win32/Win32Window.h +++ b/src/windows/ui_interfaces/win32/Win32Window.h @@ -4,36 +4,38 @@ #include 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 Create(mt::Window* window); + static std::unique_ptr 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 mDxInterface; }; \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32WindowInterface.cpp b/src/windows/ui_interfaces/win32/Win32WindowInterface.cpp index 3989cc1..8dc153e 100644 --- a/src/windows/ui_interfaces/win32/Win32WindowInterface.cpp +++ b/src/windows/ui_interfaces/win32/Win32WindowInterface.cpp @@ -1,33 +1,36 @@ #include "Win32WindowInterface.h" #include "Win32Window.h" - -#include - #include "DesktopManager.h" #include "DrawingContext.h" +#include "Win32DxInterface.h" +#include "Widget.h" #include "FileLogger.h" +#include + Win32WindowInterface::Win32WindowInterface() { } -void Win32WindowInterface::Show(mt::Window* window) +void Win32WindowInterface::show(mt::Window* window) { auto platformWindow = dynamic_cast(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(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); } diff --git a/src/windows/ui_interfaces/win32/Win32WindowInterface.h b/src/windows/ui_interfaces/win32/Win32WindowInterface.h index 7db63f2..adb425a 100644 --- a/src/windows/ui_interfaces/win32/Win32WindowInterface.h +++ b/src/windows/ui_interfaces/win32/Win32WindowInterface.h @@ -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; \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/shaders.hlsl b/src/windows/ui_interfaces/win32/shaders.hlsl new file mode 100644 index 0000000..c13404b --- /dev/null +++ b/src/windows/ui_interfaces/win32/shaders.hlsl @@ -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; +} \ No newline at end of file