From 6603555c3c6a11f5f5aaf61900270b10d5f048b9 Mon Sep 17 00:00:00 2001 From: Marc Noon Date: Tue, 22 Apr 2025 21:27:45 -0700 Subject: [PATCH] Add operation for connecting to video card thru directx 11 --- BasicGameEngine.sln | 19 ++ BasicGameEngine/BasicGameEngine.vcxproj | 4 + .../BasicGameEngine.vcxproj.filters | 3 + BasicGameEngine/include/DirectXIncludes.h | 0 .../BasicGameEngine_UnitTest.vcxproj | 7 + .../BasicGameEngine_UnitTest.vcxproj.filters | 9 + .../DirextXOperation_UnitTest.cpp | 62 +++++++ .../VideoCard_UnitTest.cpp | 42 +++++ BasicGameEngine_UnitTest/VideoCard_UnitTest.h | 5 + DX11Operation/DX11Operation.vcxproj | 163 ++++++++++++++++++ DX11Operation/DX11Operation.vcxproj.filters | 39 +++++ DX11Operation/DirectXOperation.h | 29 ++++ DX11Operation/DirextXOperation.cpp | 97 +++++++++++ DX11Operation/DirextXOperation.h | 0 DX11Operation/dllmain.cpp | 19 ++ DX11Operation/framework.h | 5 + DX11Operation/pch.cpp | 5 + DX11Operation/pch.h | 13 ++ 18 files changed, 521 insertions(+) create mode 100644 BasicGameEngine/include/DirectXIncludes.h create mode 100644 BasicGameEngine_UnitTest/DirextXOperation_UnitTest.cpp create mode 100644 BasicGameEngine_UnitTest/VideoCard_UnitTest.cpp create mode 100644 BasicGameEngine_UnitTest/VideoCard_UnitTest.h create mode 100644 DX11Operation/DX11Operation.vcxproj create mode 100644 DX11Operation/DX11Operation.vcxproj.filters create mode 100644 DX11Operation/DirectXOperation.h create mode 100644 DX11Operation/DirextXOperation.cpp create mode 100644 DX11Operation/DirextXOperation.h create mode 100644 DX11Operation/dllmain.cpp create mode 100644 DX11Operation/framework.h create mode 100644 DX11Operation/pch.cpp create mode 100644 DX11Operation/pch.h diff --git a/BasicGameEngine.sln b/BasicGameEngine.sln index 89c2b20..311e88c 100644 --- a/BasicGameEngine.sln +++ b/BasicGameEngine.sln @@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommandHistoryOperation", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommandHistoryOperation1", "CommandHistoryOperation1\CommandHistoryOperation1.vcxproj", "{D1C1B5AB-583B-4D92-817E-580102AF2E21}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DX11Operation", "DX11Operation\DX11Operation.vcxproj", "{482D7C56-57B0-468F-8490-011B0B4BB56D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -107,6 +109,22 @@ Global {D1C1B5AB-583B-4D92-817E-580102AF2E21}.Release|x64.Build.0 = Release|x64 {D1C1B5AB-583B-4D92-817E-580102AF2E21}.Release|x86.ActiveCfg = Release|Win32 {D1C1B5AB-583B-4D92-817E-580102AF2E21}.Release|x86.Build.0 = Release|Win32 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|ARM.ActiveCfg = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|ARM.Build.0 = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|ARM64.ActiveCfg = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|ARM64.Build.0 = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|x64.ActiveCfg = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|x64.Build.0 = Debug|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|x86.ActiveCfg = Debug|Win32 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Debug|x86.Build.0 = Debug|Win32 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|ARM.ActiveCfg = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|ARM.Build.0 = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|ARM64.ActiveCfg = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|ARM64.Build.0 = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|x64.ActiveCfg = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|x64.Build.0 = Release|x64 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|x86.ActiveCfg = Release|Win32 + {482D7C56-57B0-468F-8490-011B0B4BB56D}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -114,6 +132,7 @@ Global GlobalSection(NestedProjects) = preSolution {9E3D9643-A834-4FDA-A406-52540CCD6226} = {9980BB65-19FB-4941-83BA-74534825FB9D} {D1C1B5AB-583B-4D92-817E-580102AF2E21} = {9980BB65-19FB-4941-83BA-74534825FB9D} + {482D7C56-57B0-468F-8490-011B0B4BB56D} = {9980BB65-19FB-4941-83BA-74534825FB9D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D3E28ACF-2934-43DE-B490-360214FA35D3} diff --git a/BasicGameEngine/BasicGameEngine.vcxproj b/BasicGameEngine/BasicGameEngine.vcxproj index cfeb4bb..3a063a0 100644 --- a/BasicGameEngine/BasicGameEngine.vcxproj +++ b/BasicGameEngine/BasicGameEngine.vcxproj @@ -118,10 +118,13 @@ false false stdc17 + $(WindowsSDK_IncludePath);$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) Windows true + User32.lib;Gdi32.lib;Shell32.lib;Advapi32.lib;Ole32.lib; + $(DXSDK_DIR)Lib\x86 @@ -143,6 +146,7 @@ + diff --git a/BasicGameEngine/BasicGameEngine.vcxproj.filters b/BasicGameEngine/BasicGameEngine.vcxproj.filters index a29eca4..b1fe313 100644 --- a/BasicGameEngine/BasicGameEngine.vcxproj.filters +++ b/BasicGameEngine/BasicGameEngine.vcxproj.filters @@ -57,6 +57,9 @@ Header Files + + Header Files + diff --git a/BasicGameEngine/include/DirectXIncludes.h b/BasicGameEngine/include/DirectXIncludes.h new file mode 100644 index 0000000..e69de29 diff --git a/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj b/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj index 4151ba7..81786c5 100644 --- a/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj +++ b/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj @@ -106,6 +106,7 @@ Windows $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + d3d11.lib;dxgi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) @@ -166,21 +167,27 @@ + Create Create Create Create + + {9e3d9643-a834-4fda-a406-52540ccd6226} + + {482d7c56-57b0-468f-8490-011b0b4bb56d} + {bb84b704-82c7-4696-b2b4-b8b5b51f57f7} diff --git a/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj.filters b/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj.filters index bc3d82c..abaa8ce 100644 --- a/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj.filters +++ b/BasicGameEngine_UnitTest/BasicGameEngine_UnitTest.vcxproj.filters @@ -24,6 +24,12 @@ Source Files + + Source Files + + + Source Files + @@ -32,5 +38,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/BasicGameEngine_UnitTest/DirextXOperation_UnitTest.cpp b/BasicGameEngine_UnitTest/DirextXOperation_UnitTest.cpp new file mode 100644 index 0000000..c6aa718 --- /dev/null +++ b/BasicGameEngine_UnitTest/DirextXOperation_UnitTest.cpp @@ -0,0 +1,62 @@ +// DirectXOperation_UnitTest.cpp +#include "pch.h" +#include "CppUnitTest.h" +#include "../DX11Operation/DirectXOperation.h" +#include // Include Windows API header for LoadLibrary, FreeLibrary +#include +#include +#include +#include "../OpNode/IOperate.h" // Include IOperate from OpNode project + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace DirectXOperationTests { + + // Simple window procedure for a dummy window. + LRESULT CALLBACK DummyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + return DefWindowProc(hWnd, message, wParam, lParam); + } + + // Helper function to create a hidden window. + HWND CreateDummyWindow() { + const wchar_t CLASS_NAME[] = L"DummyWindowClass"; + + WNDCLASS wc = {}; + wc.lpfnWndProc = DummyWndProc; + wc.hInstance = GetModuleHandle(nullptr); + wc.lpszClassName = CLASS_NAME; + RegisterClass(&wc); + + HWND hWnd = CreateWindowEx( + 0, // Optional window styles. + CLASS_NAME, // Window class + L"Dummy Window", // Window text + WS_OVERLAPPEDWINDOW, // Window style + CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, + nullptr, // Parent window + nullptr, // Menu + GetModuleHandle(nullptr), // Instance handle + nullptr // Additional application data + ); + + // Hide the window (for unit testing, no need to show it). + ShowWindow(hWnd, SW_HIDE); + return hWnd; + } + + TEST_CLASS(DirectXOperationUnitTests) + { + public: + TEST_METHOD(TestDirectXInitialization) { + HWND hWnd = CreateDummyWindow(); + DirectXOperation dxOp; + bool result = dxOp.Initialize(hWnd, 800, 600); + Assert::IsTrue(result, L"DirectXOperation should initialize successfully."); + + // Optionally call Render to see if the device works. + dxOp.Render(); + dxOp.Cleanup(); + DestroyWindow(hWnd); // Clean up dummy window. + } + }; +} diff --git a/BasicGameEngine_UnitTest/VideoCard_UnitTest.cpp b/BasicGameEngine_UnitTest/VideoCard_UnitTest.cpp new file mode 100644 index 0000000..1cadcc1 --- /dev/null +++ b/BasicGameEngine_UnitTest/VideoCard_UnitTest.cpp @@ -0,0 +1,42 @@ +#include "pch.h" +#include "VideoCard_UnitTest.h" + +#include "CppUnitTest.h" +#include +#include +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; +using Microsoft::WRL::ComPtr; + +namespace BasicGameEngine_UnitTests +{ + TEST_CLASS(VideoCardTests) + { + public: + TEST_METHOD(TestEnumerateVideoCards) + { + // Create a DXGI factory + ComPtr factory; + HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast(factory.GetAddressOf())); + Assert::IsTrue(SUCCEEDED(hr), L"Failed to create DXGIFactory."); + + // Enumerate the first adapter (video card) + ComPtr adapter; + hr = factory->EnumAdapters(0, &adapter); + Assert::IsTrue(SUCCEEDED(hr), L"No video adapter found."); + + // Retrieve the adapter description + DXGI_ADAPTER_DESC adapterDesc = {}; + hr = adapter->GetDesc(&adapterDesc); + Assert::IsTrue(SUCCEEDED(hr), L"Failed to get adapter description."); + + // Convert the wide string description to a wstring + std::wstring adapterDescription(adapterDesc.Description); + Logger::WriteMessage((L"Video Card: " + adapterDescription).c_str()); + + // Assert that the description is not empty + Assert::IsFalse(adapterDescription.empty(), L"Adapter description is empty."); + } + }; +} \ No newline at end of file diff --git a/BasicGameEngine_UnitTest/VideoCard_UnitTest.h b/BasicGameEngine_UnitTest/VideoCard_UnitTest.h new file mode 100644 index 0000000..f6d1e1b --- /dev/null +++ b/BasicGameEngine_UnitTest/VideoCard_UnitTest.h @@ -0,0 +1,5 @@ +#pragma once +class VideoCard_UnitTest +{ +}; + diff --git a/DX11Operation/DX11Operation.vcxproj b/DX11Operation/DX11Operation.vcxproj new file mode 100644 index 0000000..2b9e7a0 --- /dev/null +++ b/DX11Operation/DX11Operation.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {482d7c56-57b0-468f-8490-011b0b4bb56d} + DX11Operation + 10.0 + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + StaticLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;DX11OPERATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;DX11OPERATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + _DEBUG;DX11OPERATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + stdcpp20 + $(DXSDK_DIR)Include + + + Windows + true + false + d3d11.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;DX11OPERATION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + + + + + + + + Create + Create + Create + Create + + + + + {bb84b704-82c7-4696-b2b4-b8b5b51f57f7} + + + + + + \ No newline at end of file diff --git a/DX11Operation/DX11Operation.vcxproj.filters b/DX11Operation/DX11Operation.vcxproj.filters new file mode 100644 index 0000000..8b372cd --- /dev/null +++ b/DX11Operation/DX11Operation.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/DX11Operation/DirectXOperation.h b/DX11Operation/DirectXOperation.h new file mode 100644 index 0000000..f27af2b --- /dev/null +++ b/DX11Operation/DirectXOperation.h @@ -0,0 +1,29 @@ +// DirectXOperation.h +#pragma once + +#include +#include +#include +#include "../OpNode/IOperate.h" +#include + +class DirectXOperation : public IOperate { +public: + DirectXOperation(); + ~DirectXOperation(); + + // IOperate interface implementation. + std::string Symbol() const override; + void Operate(std::shared_ptr node) override; + + // DirectX initialization and usage. + bool Initialize(HWND hWnd, int width, int height); + void Render(); + void Cleanup(); + +private: + Microsoft::WRL::ComPtr device_; + Microsoft::WRL::ComPtr context_; + Microsoft::WRL::ComPtr swapChain_; + Microsoft::WRL::ComPtr renderTargetView_; +}; diff --git a/DX11Operation/DirextXOperation.cpp b/DX11Operation/DirextXOperation.cpp new file mode 100644 index 0000000..b1ed6b9 --- /dev/null +++ b/DX11Operation/DirextXOperation.cpp @@ -0,0 +1,97 @@ +#pragma comment(lib, "d3d11.lib") +#pragma comment(lib, "dxgi.lib") +#include "pch.h" + +// DirectXOperation.cpp +#include "DirectXOperation.h" +#include "../OpNode/OpNode.h" // Include the OpNode header to resolve incomplete type errors +#include +#include +#include + +DirectXOperation::DirectXOperation() {} +DirectXOperation::~DirectXOperation() { + Cleanup(); +} + +std::string DirectXOperation::Symbol() const { + return "DX11"; +} + +void DirectXOperation::Operate(std::shared_ptr node) { + // For demonstration, print the operation. + if (node) { + std::cout << "DirectXOperation processing node: " << node->GetName() << std::endl; // Dereference node to access GetName + } +} + +bool DirectXOperation::Initialize(HWND hWnd, int width, int height) { + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.OutputWindow = hWnd; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.Windowed = TRUE; + + UINT createDeviceFlags = 0; +#if defined(_DEBUG) + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_FEATURE_LEVEL featureLevel; + HRESULT hr = D3D11CreateDeviceAndSwapChain( + nullptr, + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + createDeviceFlags, + nullptr, + 0, + D3D11_SDK_VERSION, + &swapChainDesc, + &swapChain_, + &device_, + &featureLevel, + &context_ + ); + if (FAILED(hr)) { + std::cerr << "D3D11CreateDeviceAndSwapChain failed: " << hr << std::endl; + return false; + } + + Microsoft::WRL::ComPtr backBuffer; + hr = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(backBuffer.GetAddressOf())); + if (FAILED(hr)) { + std::cerr << "GetBuffer failed: " << hr << std::endl; + return false; + } + + hr = device_->CreateRenderTargetView(backBuffer.Get(), nullptr, &renderTargetView_); + if (FAILED(hr)) { + std::cerr << "CreateRenderTargetView failed: " << hr << std::endl; + return false; + } + + context_->OMSetRenderTargets(1, renderTargetView_.GetAddressOf(), nullptr); + + D3D11_VIEWPORT viewport = {}; + viewport.Width = static_cast(width); + viewport.Height = static_cast(height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + context_->RSSetViewports(1, &viewport); + + return true; +} + +void DirectXOperation::Render() { + FLOAT clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f }; + context_->ClearRenderTargetView(renderTargetView_.Get(), clearColor); + swapChain_->Present(1, 0); +} + +void DirectXOperation::Cleanup() { + // ComPtr releases resources automatically. +} \ No newline at end of file diff --git a/DX11Operation/DirextXOperation.h b/DX11Operation/DirextXOperation.h new file mode 100644 index 0000000..e69de29 diff --git a/DX11Operation/dllmain.cpp b/DX11Operation/dllmain.cpp new file mode 100644 index 0000000..f266597 --- /dev/null +++ b/DX11Operation/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/DX11Operation/framework.h b/DX11Operation/framework.h new file mode 100644 index 0000000..54b83e9 --- /dev/null +++ b/DX11Operation/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/DX11Operation/pch.cpp b/DX11Operation/pch.cpp new file mode 100644 index 0000000..64b7eef --- /dev/null +++ b/DX11Operation/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/DX11Operation/pch.h b/DX11Operation/pch.h new file mode 100644 index 0000000..885d5d6 --- /dev/null +++ b/DX11Operation/pch.h @@ -0,0 +1,13 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#include "framework.h" + +#endif //PCH_H