From 7b234ec4058997c84fa5a52843f73f3d31df5006 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 4 Jan 2026 23:11:58 +0800 Subject: [PATCH] finish buggy dx11 code --- BasaltPresenter/CMakeLists.txt | 6 +- .../Deliver/PipeDeliver/CMakeLists.txt | 16 +- .../Engine/DirectX11Engine/CMakeLists.txt | 16 +- .../Plugins/Engine/DirectX11Engine/main.cpp | 404 ++++++++++-------- BasaltPresenter/Presenter/CMakeLists.txt | 3 + BasaltPresenter/Presenter/dll_loader.cpp | 63 ++- BasaltPresenter/Presenter/dll_loader.hpp | 7 + BasaltPresenter/Presenter/main.cpp | 17 +- BasaltPresenter/Shared/CMakeLists.txt | 2 + BasaltPresenter/Shared/directx_util.cpp | 67 +++ BasaltPresenter/Shared/directx_util.hpp | 10 + BasaltPresenter/Shared/pipe_operator.cpp | 40 +- 12 files changed, 432 insertions(+), 219 deletions(-) create mode 100644 BasaltPresenter/Shared/directx_util.cpp create mode 100644 BasaltPresenter/Shared/directx_util.hpp diff --git a/BasaltPresenter/CMakeLists.txt b/BasaltPresenter/CMakeLists.txt index bf42bc0..7df8fa2 100644 --- a/BasaltPresenter/CMakeLists.txt +++ b/BasaltPresenter/CMakeLists.txt @@ -24,8 +24,9 @@ option(BASALT_PIPE_DELIVER "Build with system pipe data deliver support." OFF) # 3D Objects Loaders option(BASALT_OBJ_OBJECT_LOADER "Build with Wavefront OBJ 3D object loader support." OFF) option(BASALT_GLTF_OBJECT_LOADER "Build with glTF 3D object loader support." OFF) +option(BASALT_ASSIMP_OBJECT_LOADER "Build with Assimp 3D object loader support." OFF) # Camera Motion Loaders -option(BASALT_UNKNOWN_ANIME_LOADER "Build with Unknown camera motion loader support." OFF) +option(BASALT_homemade_ANIME_LOADER "Build with homemade camera motion loader support." OFF) # Set C++ standards set(CMAKE_CXX_STANDARD 23) @@ -35,10 +36,11 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Include some essential CMake components include(GNUInstallDirs) -# Find required packages based on options +# Add out CMake in module found path set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake" ) +# Find required packages based on options if (BASALT_CUDA_DELIVER) find_package(CUDA REQUIRED) endif () diff --git a/BasaltPresenter/Plugins/Deliver/PipeDeliver/CMakeLists.txt b/BasaltPresenter/Plugins/Deliver/PipeDeliver/CMakeLists.txt index aa81b9b..eb7d6fe 100644 --- a/BasaltPresenter/Plugins/Deliver/PipeDeliver/CMakeLists.txt +++ b/BasaltPresenter/Plugins/Deliver/PipeDeliver/CMakeLists.txt @@ -1,27 +1,27 @@ # Create shared library -add_library(PipeDeliver SHARED "") +add_library(BasaltPipeDeliver SHARED "") # Setup sources -target_sources(PipeDeliver +target_sources(BasaltPipeDeliver PRIVATE main.cpp ) # Setup header infomation -target_include_directories(PipeDeliver +target_include_directories(BasaltPipeDeliver PRIVATE "${CMAKE_CURRENT_LIST_DIR}" ) # Setup linked library infomation -target_link_libraries(PipeDeliver +target_link_libraries(BasaltPipeDeliver PRIVATE BasaltShared ) # Enable export macro -target_compile_definitions(PipeDeliver +target_compile_definitions(BasaltPipeDeliver PRIVATE BS_EXPORTING ) -# Install PipeDeliver only on Release mode -install(TARGETS PipeDeliver - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugins/engine" +# Install BasaltPipeDeliver only on Release mode +install(TARGETS BasaltPipeDeliver + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugin/deliver" ) diff --git a/BasaltPresenter/Plugins/Engine/DirectX11Engine/CMakeLists.txt b/BasaltPresenter/Plugins/Engine/DirectX11Engine/CMakeLists.txt index eb9a26a..83600b2 100644 --- a/BasaltPresenter/Plugins/Engine/DirectX11Engine/CMakeLists.txt +++ b/BasaltPresenter/Plugins/Engine/DirectX11Engine/CMakeLists.txt @@ -1,28 +1,28 @@ # Create shared library -add_library(DirectX11Engine SHARED "") +add_library(BasaltDirectX11Engine SHARED "") # Setup sources -target_sources(DirectX11Engine +target_sources(BasaltDirectX11Engine PRIVATE main.cpp ) # Setup header infomation -target_include_directories(DirectX11Engine +target_include_directories(BasaltDirectX11Engine PRIVATE "${CMAKE_CURRENT_LIST_DIR}" ) # Setup linked library infomation -target_link_libraries(DirectX11Engine +target_link_libraries(BasaltDirectX11Engine PRIVATE BasaltShared ${DirectX11_LIBRARY} ) # Enable export macro -target_compile_definitions(DirectX11Engine +target_compile_definitions(BasaltDirectX11Engine PRIVATE BS_EXPORTING ) -# Install DirectX11Engine only on Release mode -install(TARGETS DirectX11Engine - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugins/engine" +# Install BasaltDirectX11Engine only on Release mode +install(TARGETS BasaltDirectX11Engine + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/plugin/engine" ) diff --git a/BasaltPresenter/Plugins/Engine/DirectX11Engine/main.cpp b/BasaltPresenter/Plugins/Engine/DirectX11Engine/main.cpp index 57c27ba..25cd495 100644 --- a/BasaltPresenter/Plugins/Engine/DirectX11Engine/main.cpp +++ b/BasaltPresenter/Plugins/Engine/DirectX11Engine/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,204 +9,78 @@ #include using Microsoft::WRL::ComPtr; +#define DXCHK(condition) \ + if (FAILED(condition)) { \ + throw std::runtime_error("bad DirectX calling"); \ + } -// 常量 -constexpr UINT Width = 800; -constexpr UINT Height = 600; -constexpr const wchar_t* PipeName = L"\\\\.\\pipe\\54da494c-301a-47a9-9d67-4fbebaeda8cf"; - -// 立方体顶点(位置) +// 绔嬫柟浣撻《鐐癸紙浣嶇疆锛 struct Vertex { float x, y, z; }; +// 绔嬫柟浣撻《鐐 Vertex CubeVertices[] = { - // 前面 + // 鍓嶉潰 {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, - // 后面 + // 鍚庨潰 {-1, -1, 1}, {-1, 1, 1}, {1, 1, 1}, {-1, -1, 1}, {1, 1, 1}, {1, -1, 1}, - // 其他面...(为简化,此处略,或用完整立方体) - // 实际建议使用完整12个三角面(36顶点) + // 宸﹂潰 + {-1, -1, -1}, + {-1, -1, 1}, + {-1, 1, 1}, + {-1, -1, -1}, + {-1, 1, 1}, + {-1, 1, -1}, + // 鍙抽潰 + {1, -1, -1}, + {1, 1, -1}, + {1, 1, 1}, + {1, -1, -1}, + {1, 1, 1}, + {1, -1, 1}, + // 椤堕潰 + {-1, 1, -1}, + {1, 1, -1}, + {1, 1, 1}, + {-1, 1, -1}, + {1, 1, 1}, + {-1, 1, 1}, + // 搴曢潰 + {-1, -1, -1}, + {-1, -1, 1}, + {1, -1, 1}, + {-1, -1, -1}, + {1, -1, 1}, + {1, -1, -1} }; -// 为简化,这里只渲染前面,实际请补全 -// 简单顶点着色器(只传位置) +// 绠鍗曢《鐐圭潃鑹插櫒锛堝彧浼犱綅缃級 const char* g_VS = R"( float4 main(float3 pos : POSITION) : SV_POSITION { return float4(pos, 1.0f); } )"; -// 简单像素着色器(返回固定颜色) +// 绠鍗曞儚绱犵潃鑹插櫒锛堣繑鍥炲浐瀹氶鑹诧級 const char* g_PS = R"( float4 main() : SV_TARGET { return float4(0.2f, 0.4f, 0.8f, 1.0f); } )"; -int main() { - // 初始化 COM - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - // 创建设备和上下文 - ComPtr device; - ComPtr context; - D3D11CreateDevice( - nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_DEBUG, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); - - // 创建交换链(窗口可选,这里仅用于渲染上下文) - ComPtr swapChain; - DXGI_SWAP_CHAIN_DESC sd = {}; - sd.BufferDesc.Width = Width; - sd.BufferDesc.Height = Height; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.SampleDesc.Count = 1; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.BufferCount = 1; - sd.OutputWindow = GetConsoleWindow(); // 或创建窗口 - sd.Windowed = TRUE; - - ComPtr dxgiDevice; - device.As(&dxgiDevice); - ComPtr adapter; - dxgiDevice->GetAdapter(&adapter); - ComPtr factory; - adapter->GetParent(IID_PPV_ARGS(&factory)); - factory->CreateSwapChain(device.Get(), &sd, &swapChain); - - // 创建渲染目标 - ComPtr rtv; - ComPtr backBuffer; - swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)); - device->CreateRenderTargetView(backBuffer.Get(), nullptr, &rtv); - - // 创建深度缓冲(D32_FLOAT) - ComPtr depthBuffer; - D3D11_TEXTURE2D_DESC depthDesc = {}; - depthDesc.Width = Width; - depthDesc.Height = Height; - depthDesc.MipLevels = 1; - depthDesc.ArraySize = 1; - depthDesc.Format = DXGI_FORMAT_D32_FLOAT; - depthDesc.SampleDesc.Count = 1; - depthDesc.Usage = D3D11_USAGE_DEFAULT; - depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - device->CreateTexture2D(&depthDesc, nullptr, &depthBuffer); - - ComPtr dsv; - device->CreateDepthStencilView(depthBuffer.Get(), nullptr, &dsv); - - // 创建 staging texture 用于 CPU 读取深度(R32_FLOAT) - ComPtr depthStaging; - D3D11_TEXTURE2D_DESC stagingDesc = depthDesc; - stagingDesc.Format = DXGI_FORMAT_R32_FLOAT; // 注意:DSV 用 D32_FLOAT,staging 用 R32_FLOAT - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.Usage = D3D11_USAGE_STAGING; - device->CreateTexture2D(&stagingDesc, nullptr, &depthStaging); - - // 编译并创建着色器 - ComPtr vs; - ComPtr ps; - ComPtr vsBlob, psBlob; - D3DCompile(g_VS, strlen(g_VS), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vsBlob, nullptr); - D3DCompile(g_PS, strlen(g_PS), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &psBlob, nullptr); - device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &vs); - device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &ps); - - // 输入布局 - D3D11_INPUT_ELEMENT_DESC layout[] = {{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}}; - ComPtr inputLayout; - device->CreateInputLayout(layout, 1, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &inputLayout); - - // 顶点缓冲 - ComPtr vertexBuffer; - D3D11_BUFFER_DESC vbDesc = {}; - vbDesc.ByteWidth = sizeof(CubeVertices); - vbDesc.Usage = D3D11_USAGE_DEFAULT; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - D3D11_SUBRESOURCE_DATA vbData = {CubeVertices}; - device->CreateBuffer(&vbDesc, &vbData, &vertexBuffer); - - // 深度测试启用 - ComPtr depthState; - D3D11_DEPTH_STENCIL_DESC dsDesc = {}; - dsDesc.DepthEnable = TRUE; - dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - dsDesc.DepthFunc = D3D11_COMPARISON_LESS; - device->CreateDepthStencilState(&dsDesc, &depthState); - - // 视口 - D3D11_VIEWPORT vp = {0, 0, (float) Width, (float) Height, 0, 1}; - context->RSSetViewports(1, &vp); - - // 打开命名管道(需另一进程已创建) - HANDLE hPipe = CreateFileW(PipeName, GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); - - if (hPipe == INVALID_HANDLE_VALUE) { - std::cerr << "Failed to open named pipe. Ensure another process created it.\n"; - return -1; - } - - constexpr size_t depthSize = Width * Height * sizeof(float); - std::vector depthData(depthSize); - - // 渲染循环(示例只渲染10帧) - for (int frame = 0; frame < 10; ++frame) { - // 清屏 - float clearColor[] = {0.1f, 0.1f, 0.1f, 1.0f}; - context->ClearRenderTargetView(rtv.Get(), clearColor); - context->ClearDepthStencilView(dsv.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); - - // 设置管线 - context->OMSetRenderTargets(1, rtv.GetAddressOf(), dsv.Get()); - context->OMSetDepthStencilState(depthState.Get(), 1); - context->VSSetShader(vs.Get(), nullptr, 0); - context->PSSetShader(ps.Get(), nullptr, 0); - context->IASetInputLayout(inputLayout.Get()); - UINT stride = sizeof(Vertex), offset = 0; - context->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset); - context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - - // 绘制立方体 - context->Draw(6, 0); // 仅前面,实际应为36 - - // 复制深度缓冲到 staging texture - context->CopyResource(depthStaging.Get(), depthBuffer.Get()); - - // Map 获取数据 - D3D11_MAPPED_SUBRESOURCE mapped; - context->Map(depthStaging.Get(), 0, D3D11_MAP_READ, 0, &mapped); - memcpy(depthData.data(), mapped.pData, depthSize); - context->Unmap(depthStaging.Get(), 0); - - // 写入命名管道 - DWORD written; - if (!WriteFile(hPipe, depthData.data(), static_cast(depthSize), &written, nullptr) || written != depthSize) { - std::cerr << "WriteFile failed or incomplete.\n"; - break; - } - - // 呈现(可选) - swapChain->Present(0, 0); - } - - CloseHandle(hPipe); - CoUninitialize(); - return 0; -} - using ::Basalt::Shared::Engine::EngineConfig; using ::Basalt::Shared::Engine::IEngine; +namespace DxUtil = ::Basalt::Shared::DirectX; class DirectX11Engine : public IEngine { public: @@ -213,15 +88,198 @@ public: virtual ~DirectX11Engine() {} private: - ComPtr device; ///< 设备 - ComPtr context; ///< 上下文 - ComPtr swapChain; ///< 交换链 - + ComPtr device; ///< 璁惧 + ComPtr context; ///< 涓婁笅鏂 + ComPtr swap_chain; ///< 浜ゆ崲閾 + ComPtr rtv; ///< 娓叉煋鐩爣瑙嗗浘 + ComPtr back_buffer; ///< 鍚庣紦鍐 + ComPtr depth_buffer; ///< 娣卞害缂撳啿 + ComPtr dsv; ///< 娣卞害妯℃澘瑙嗗浘 + ComPtr depth_staging; ///< 鐢ㄤ簬CPU璇诲彇鐨勬繁搴︽殏瀛樼汗鐞 + ComPtr vs; ///< 椤剁偣鐫鑹插櫒 + ComPtr ps; ///< 鍍忕礌鐫鑹插櫒 + ComPtr vs_blob; ///< 椤剁偣鐫鑹插櫒瀛楄妭鐮 + ComPtr ps_blob; ///< 鍍忕礌鐫鑹插櫒瀛楄妭鐮 + ComPtr input_layout; ///< 杈撳叆甯冨眬 + ComPtr vertex_buffer; ///< 椤剁偣缂撳啿 + ComPtr depth_state; ///< 娣卞害鐘舵 + std::vector depth_data; ///< 娣卞害鏁版嵁 public: - virtual void Startup(EngineConfig&& config) override { IEngine::Startup(std::move(config)); } - virtual void Tick() override { IEngine::Tick(); } - virtual void Shutdown() override { IEngine::Shutdown(); } + virtual void Startup(EngineConfig&& config) override { + IEngine::Startup(std::move(config)); + + // 鍒濆鍖 COM + DXCHK(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + + // 鍒涘缓璁惧鍜屼笂涓嬫枃 + DXCHK(D3D11CreateDevice(nullptr, + D3D_DRIVER_TYPE_HARDWARE, + nullptr, + D3D11_CREATE_DEVICE_DEBUG, + nullptr, + 0, + D3D11_SDK_VERSION, + &device, + nullptr, + &context)); + + // 鍒涘缓浜ゆ崲閾撅紙绐楀彛鍙夛紝杩欓噷浠呯敤浜庢覆鏌撲笂涓嬫枃锛 + DXGI_SWAP_CHAIN_DESC sd = {}; + sd.BufferDesc.Width = this->config.width; + sd.BufferDesc.Height = this->config.height; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.SampleDesc.Count = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.BufferCount = 1; + sd.OutputWindow = DxUtil::CreateRenderWindow(this->config.width, this->config.height, this->config.title); // 鍒涘缓绐楀彛 + sd.Windowed = TRUE; + + ComPtr dxgi_device; + DXCHK(device.As(&dxgi_device)); + ComPtr adapter; + DXCHK(dxgi_device->GetAdapter(&adapter)); + ComPtr factory; + DXCHK(adapter->GetParent(IID_PPV_ARGS(&factory))); + DXCHK(factory->CreateSwapChain(device.Get(), &sd, &swap_chain)); + + // 鍒涘缓娓叉煋鐩爣 + DXCHK(swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer))); + DXCHK(device->CreateRenderTargetView(back_buffer.Get(), nullptr, &rtv)); + + // 鍒涘缓娣卞害缂撳啿锛圖32_FLOAT锛 + D3D11_TEXTURE2D_DESC depth_desc = {}; + depth_desc.Width = this->config.width; + depth_desc.Height = this->config.height; + depth_desc.MipLevels = 1; + depth_desc.ArraySize = 1; + depth_desc.Format = DXGI_FORMAT_D32_FLOAT; + depth_desc.SampleDesc.Count = 1; + depth_desc.Usage = D3D11_USAGE_DEFAULT; + depth_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + DXCHK(device->CreateTexture2D(&depth_desc, nullptr, &depth_buffer)); + + DXCHK(device->CreateDepthStencilView(depth_buffer.Get(), nullptr, &dsv)); + + // 鍒涘缓 staging texture 鐢ㄤ簬 CPU 璇诲彇娣卞害锛圧32_FLOAT锛 + D3D11_TEXTURE2D_DESC staging_desc = depth_desc; + staging_desc.Format = DXGI_FORMAT_R32_FLOAT; // 娉ㄦ剰锛欴SV 鐢 D32_FLOAT锛宻taging 鐢 R32_FLOAT + staging_desc.BindFlags = 0; + staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + staging_desc.Usage = D3D11_USAGE_STAGING; + DXCHK(device->CreateTexture2D(&staging_desc, nullptr, &depth_staging)); + + // 缂栬瘧骞跺垱寤虹潃鑹插櫒 + DXCHK(D3DCompile(g_VS, static_cast(strlen(g_VS)), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vs_blob, nullptr)); + DXCHK(D3DCompile(g_PS, static_cast(strlen(g_PS)), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &ps_blob, nullptr)); + DXCHK(device->CreateVertexShader(vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), nullptr, &vs)); + DXCHK(device->CreatePixelShader(ps_blob->GetBufferPointer(), ps_blob->GetBufferSize(), nullptr, &ps)); + + // 杈撳叆甯冨眬 + D3D11_INPUT_ELEMENT_DESC layout[] = {{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}}; + DXCHK(device->CreateInputLayout(layout, 1, vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &input_layout)); + + // 椤剁偣缂撳啿 + D3D11_BUFFER_DESC vb_desc = {}; + vb_desc.ByteWidth = sizeof(CubeVertices); + vb_desc.Usage = D3D11_USAGE_DEFAULT; + vb_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + D3D11_SUBRESOURCE_DATA vb_data = {CubeVertices}; + DXCHK(device->CreateBuffer(&vb_desc, &vb_data, &vertex_buffer)); + + // 娣卞害娴嬭瘯鍚敤 + D3D11_DEPTH_STENCIL_DESC ds_desc = {}; + ds_desc.DepthEnable = TRUE; + ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + ds_desc.DepthFunc = D3D11_COMPARISON_LESS; + DXCHK(device->CreateDepthStencilState(&ds_desc, &depth_state)); + + // 瑙嗗彛 + D3D11_VIEWPORT vp; + ZeroMemory(&vp, sizeof(D3D11_VIEWPORT)); + vp.TopLeftX = 0; + vp.TopLeftY = 0; + vp.Width = (float) this->config.width; + vp.Height = (float) this->config.height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + context->RSSetViewports(1, &vp); // RSSetViewports doesn't return HRESULT, so no need to wrap + + //// 鎵撳紑鍛藉悕绠¢亾锛堥渶鍙︿竴杩涚▼宸插垱寤猴級 + //constexpr const wchar_t* PipeName = L"\\\\.\\pipe\\54da494c-301a-47a9-9d67-4fbebaeda8cf"; + //hPipe = CreateFileW(PipeName, GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); + + //if (hPipe == INVALID_HANDLE_VALUE) { + // std::cerr << "Failed to open named pipe. Ensure another process created it.\n"; + // return; + //} + + // 缂╂斁娣卞害鏁版嵁鏁扮粍鍒版寚瀹氬ぇ灏 + depth_data.resize(this->config.width * this->config.height * sizeof(float)); + + // 璁剧疆绠$嚎 + context->OMSetRenderTargets(1, rtv.GetAddressOf(), dsv.Get()); + context->OMSetDepthStencilState(depth_state.Get(), 1); + context->VSSetShader(vs.Get(), nullptr, 0); + context->PSSetShader(ps.Get(), nullptr, 0); + context->IASetInputLayout(input_layout.Get()); + UINT stride = sizeof(Vertex), offset = 0; + context->IASetVertexBuffers(0, 1, vertex_buffer.GetAddressOf(), &stride, &offset); + context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + //frameCount = 0; + } + + virtual void Tick() override { + IEngine::Tick(); + + // 娓呭睆 + float clear_color[] = {0.8f, 0.1f, 0.1f, 1.0f}; + context->ClearRenderTargetView(rtv.Get(), clear_color); + //context->ClearDepthStencilView(dsv.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); + + //// 璁剧疆绠$嚎 + //context->OMSetRenderTargets(1, rtv.GetAddressOf(), dsv.Get()); + //context->OMSetDepthStencilState(depth_state.Get(), 1); + //context->VSSetShader(vs.Get(), nullptr, 0); + //context->PSSetShader(ps.Get(), nullptr, 0); + //context->IASetInputLayout(input_layout.Get()); + //UINT stride = sizeof(Vertex), offset = 0; + //context->IASetVertexBuffers(0, 1, vertex_buffer.GetAddressOf(), &stride, &offset); + //context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + // 缁樺埗绔嬫柟浣 + context->Draw(sizeof(CubeVertices) / sizeof(Vertex), 0); // 鑷姩璁$畻椤剁偣鏁 + + //// 澶嶅埗娣卞害缂撳啿鍒 staging texture + //context->CopyResource(depth_staging.Get(), depth_buffer.Get()); + + //// Map 鑾峰彇鏁版嵁 + //D3D11_MAPPED_SUBRESOURCE mapped; + //DXCHK(context->Map(depth_staging.Get(), 0, D3D11_MAP_READ, 0, &mapped)); + //memcpy(depth_data.data(), mapped.pData, this->config.width * this->config.height * sizeof(float)); + //context->Unmap(depth_staging.Get(), 0); + + //// 鍐欏叆鍛藉悕绠¢亾 + //DWORD written; + //if (!WriteFile(hPipe, depth_data.data(), static_cast(this->config.width * this->config.height * sizeof(float)), &written, nullptr) || written != this->config.width * this->config.height * sizeof(float)) { + // std::cerr << "WriteFile failed or incomplete.\n"; + //} + + // 鍛堢幇锛堝彲閫夛級 + DXCHK(swap_chain->Present(0, 0)); + + //frameCount++; + } + + virtual void Shutdown() override { + IEngine::Shutdown(); + + //if (hPipe != INVALID_HANDLE_VALUE) { + // CloseHandle(hPipe); + //} + CoUninitialize(); + } }; BS_EXPORT void* BSCreateInstance() { @@ -230,4 +288,4 @@ BS_EXPORT void* BSCreateInstance() { BS_EXPORT void BSDestroyInstance(void* instance) { delete reinterpret_cast(instance); -} +} \ No newline at end of file diff --git a/BasaltPresenter/Presenter/CMakeLists.txt b/BasaltPresenter/Presenter/CMakeLists.txt index f61ddfa..6ad7e8d 100644 --- a/BasaltPresenter/Presenter/CMakeLists.txt +++ b/BasaltPresenter/Presenter/CMakeLists.txt @@ -19,3 +19,6 @@ PRIVATE BasaltShared ) +install(TARGETS BasaltPresenter + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/BasaltPresenter/Presenter/dll_loader.cpp b/BasaltPresenter/Presenter/dll_loader.cpp index a92c858..dd00b4e 100644 --- a/BasaltPresenter/Presenter/dll_loader.cpp +++ b/BasaltPresenter/Presenter/dll_loader.cpp @@ -1,18 +1,67 @@ #include "dll_loader.hpp" +#include #include +#include + +#if defined(BASALT_OS_WINDOWS) +#include +#else +#include +#endif namespace Basalt::Presenter { - DllLoader::DllLoader(DllKind kind, const std::basic_string_view filename) { - // TODO: - // Add current executable location supports. - // Add sub directories supports. - // Fix file name terminal error. + static std::filesystem::path get_executable() { #if defined(BASALT_OS_WINDOWS) - m_Handle = LoadLibraryW(filename.data()); + wchar_t buffer[MAX_PATH]; + DWORD hr = GetModuleFileNameW(NULL, buffer, MAX_PATH); + if (hr == 0) { + throw std::runtime_error("Failed to get executable path"); + } else { + return std::filesystem::path(buffer); + } #else - m_Handle = dlopen(filename.data(), RTLD_LAZY); + char buffer[PATH_MAX]; + ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); + if (len != -1) { + buffer[len] = '\0'; + return std::filesystem::path(buffer); + } else { + throw std::runtime_error("Failed to get executable path"); + } #endif + } + + DllLoader::DllLoader(DllKind kind, const std::basic_string_view filename) { + // Build DLL full path + auto dll_path = get_executable().parent_path(); + dll_path /= BSTEXT("plugin"); + switch (kind) { + case DllKind::Engine: + dll_path /= BSTEXT("engine"); + break; + case DllKind::Deliver: + dll_path /= BSTEXT("deliver"); + break; + case DllKind::ObjectLoader: + dll_path /= BSTEXT("object_loader"); + break; + case DllKind::AnimeLoader: + dll_path /= BSTEXT("anime_loader"); + break; + } + dll_path /= filename; +#if defined(BASALT_OS_WINDOWS) + dll_path.replace_extension(BSTEXT(".dll")); +#endif + + // Load DLL +#if defined(BASALT_OS_WINDOWS) + m_Handle = LoadLibraryW(dll_path.wstring().c_str()); +#else + m_Handle = dlopen(dll_path.string().c_str(), RTLD_LAZY); +#endif + // Check loaded DLL if (!m_Handle) throw std::runtime_error("Can not load given dynamic library."); } diff --git a/BasaltPresenter/Presenter/dll_loader.hpp b/BasaltPresenter/Presenter/dll_loader.hpp index 47ede80..ef507ce 100644 --- a/BasaltPresenter/Presenter/dll_loader.hpp +++ b/BasaltPresenter/Presenter/dll_loader.hpp @@ -39,6 +39,13 @@ namespace Basalt::Presenter { auto fct = (Fct) GetFunctionPointer(EXPOSE_FUNC_NAME); return fct(); } + template + void DestroyInstance(T* instance) { + using Fct = void (*) (T*); + constexpr char EXPOSE_FUNC_NAME[] = "BSDestroyInstance"; + auto fct = (Fct) GetFunctionPointer(EXPOSE_FUNC_NAME); + fct(instance); + } private: Handle m_Handle; diff --git a/BasaltPresenter/Presenter/main.cpp b/BasaltPresenter/Presenter/main.cpp index 1334cc9..8545383 100644 --- a/BasaltPresenter/Presenter/main.cpp +++ b/BasaltPresenter/Presenter/main.cpp @@ -1,4 +1,19 @@ +#include "dll_loader.hpp" +#include +#include + +namespace Presenter = ::Basalt::Presenter; +namespace Shared = ::Basalt::Shared; int main(int argc, char* argv[]) { - return 0; + auto engine_dll = Presenter::DllLoader(Presenter::DllKind::Engine, BSTEXT("BasaltDirectX11Engine")); + auto* engine = engine_dll.CreateInstance(); + Shared::Engine::EngineConfig engine_config{.is_headless = false, .title = BSTEXT("Fuck You"), .width = 800, .height = 600}; + engine->Startup(std::move(engine_config)); + + while (true) { + engine->Tick(); + } + + engine->Shutdown(); } diff --git a/BasaltPresenter/Shared/CMakeLists.txt b/BasaltPresenter/Shared/CMakeLists.txt index 1227198..f9050d6 100644 --- a/BasaltPresenter/Shared/CMakeLists.txt +++ b/BasaltPresenter/Shared/CMakeLists.txt @@ -5,6 +5,7 @@ PRIVATE pipe_operator.cpp engine.cpp deliver.cpp + directx_util.cpp ) target_sources(BasaltShared PUBLIC @@ -16,6 +17,7 @@ FILES pipe_operator.hpp engine.hpp deliver.hpp + directx_util.hpp ) target_include_directories(BasaltShared PUBLIC diff --git a/BasaltPresenter/Shared/directx_util.cpp b/BasaltPresenter/Shared/directx_util.cpp new file mode 100644 index 0000000..b5ddd8a --- /dev/null +++ b/BasaltPresenter/Shared/directx_util.cpp @@ -0,0 +1,67 @@ +#include "directx_util.hpp" +#include +#include + +namespace Basalt::Shared::DirectX { + + // Window procedure for the render window + LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + case WM_CLOSE: + PostQuitMessage(0); + return 0; + default: + break; + } + return DefWindowProcW(hwnd, msg, wParam, lParam); + } + + // Create a render window for DirectX + HWND CreateRenderWindow(std::uint32_t width, std::uint32_t height, const std::wstring_view& title) { + static bool g_CLSREG = false; + constexpr wchar_t class_name[] = L"DirectXRenderWindowClass"; + std::wstring c_title(title); + + if (!g_CLSREG) { + WNDCLASSEXW wc = {0}; + wc.cbSize = sizeof(WNDCLASSEXW); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandleW(nullptr); + wc.hCursor = LoadCursorW(nullptr, IDC_ARROW); + wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); + wc.lpszClassName = class_name; + + if (!RegisterClassExW(&wc)) { + throw std::runtime_error("Failed to register window class"); + } + g_CLSREG = true; + } + + // Calculate window size including borders + RECT rect = {0, 0, static_cast(width), static_cast(height)}; + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + + HWND hwnd = CreateWindowExW(0, + class_name, + c_title.c_str(), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + rect.right - rect.left, + rect.bottom - rect.top, + nullptr, + nullptr, + GetModuleHandleW(nullptr), + nullptr); + if (!hwnd) { + throw std::runtime_error("Failed to create render window"); + } + + ShowWindow(hwnd, SW_SHOW); + UpdateWindow(hwnd); + + return hwnd; + } + +} diff --git a/BasaltPresenter/Shared/directx_util.hpp b/BasaltPresenter/Shared/directx_util.hpp new file mode 100644 index 0000000..1d022a8 --- /dev/null +++ b/BasaltPresenter/Shared/directx_util.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include + +namespace Basalt::Shared::DirectX { + + HWND CreateRenderWindow(std::uint32_t width, std::uint32_t height, const std::wstring_view& title); + +} diff --git a/BasaltPresenter/Shared/pipe_operator.cpp b/BasaltPresenter/Shared/pipe_operator.cpp index 3387ca9..76691fa 100644 --- a/BasaltPresenter/Shared/pipe_operator.cpp +++ b/BasaltPresenter/Shared/pipe_operator.cpp @@ -16,13 +16,13 @@ namespace Basalt::Shared { // Create Windows pipe name from given name auto fullname = std::format(BSTEXT("\\\\.\\pipe\\{}"), name); - m_Handle = CreateFileW(fullname.c_str(), // 管道名称 - GENERIC_READ | GENERIC_WRITE, // 读写权限 - 0, // 不共享 - NULL, // 默认安全属性 - OPEN_EXISTING, // 打开已存在的管道 - 0, // 默认属性 - NULL // 无模板文件 + m_Handle = CreateFileW(fullname.c_str(), // 绠¢亾鍚嶇О + GENERIC_READ | GENERIC_WRITE, // 璇诲啓鏉冮檺 + 0, // 涓嶅叡浜 + NULL, // 榛樿瀹夊叏灞炴 + OPEN_EXISTING, // 鎵撳紑宸插瓨鍦ㄧ殑绠¢亾 + 0, // 榛樿灞炴 + NULL // 鏃犳ā鏉挎枃浠 ); if (m_Handle == BAD_PIPE_HANDLE) { @@ -80,16 +80,16 @@ namespace Basalt::Shared { void PipeOperator::Read(void *buffer, size_t size) { if (size == 0) { - return; // 读取0字节直接返回 + return; // 璇诲彇0瀛楄妭鐩存帴杩斿洖 } #if defined(BASALT_OS_WINDOWS) DWORD bytesRead = 0; - BOOL success = ReadFile(m_Handle, // 管道句柄 - buffer, // 缓冲区 - static_cast(size), // 缓冲区大小 - &bytesRead, // 实际读取的字节数 - NULL // 不使用重叠I/O + BOOL success = ReadFile(m_Handle, // 绠¢亾鍙ユ焺 + buffer, // 缂撳啿鍖 + static_cast(size), // 缂撳啿鍖哄ぇ灏 + &bytesRead, // 瀹為檯璇诲彇鐨勫瓧鑺傛暟 + NULL // 涓嶄娇鐢ㄩ噸鍙營/O ); if (!success) { @@ -111,7 +111,7 @@ namespace Basalt::Shared { } if (bytesRead == 0) { - // 管道已关闭或到达末尾 + // 绠¢亾宸插叧闂垨鍒拌揪鏈熬 throw std::runtime_error("Named pipe closed during read."); } @@ -126,16 +126,16 @@ namespace Basalt::Shared { void PipeOperator::Write(const void *buffer, size_t size) { if (size == 0) { - return; // 写入0字节直接返回 + return; // 鍐欏叆0瀛楄妭鐩存帴杩斿洖 } #if defined(BASALT_OS_WINDOWS) DWORD bytesWritten = 0; - BOOL success = WriteFile(m_Handle, // 管道句柄 - buffer, // 数据缓冲区 - static_cast(size), // 数据大小 - &bytesWritten, // 实际写入的字节数 - NULL // 不使用重叠I/O + BOOL success = WriteFile(m_Handle, // 绠¢亾鍙ユ焺 + buffer, // 鏁版嵁缂撳啿鍖 + static_cast(size), // 鏁版嵁澶у皬 + &bytesWritten, // 瀹為檯鍐欏叆鐨勫瓧鑺傛暟 + NULL // 涓嶄娇鐢ㄩ噸鍙營/O ); if (!success) {