- 添加RHI接口定义(IRHIDevice, ICommandList, IResource等) - 实现D3D12Device, D3D12CommandList, D3D12PipelineState等 - 修复RootSignature参数数量(3->4)与HelloEarth一致 - 修复DSV格式设置(Unknown->D24_UNorm_S8_UInt) - 添加Geometry Shader编译 - 创建XCEngineDemo项目验证RHI功能
244 lines
7.9 KiB
C++
244 lines
7.9 KiB
C++
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <RHI\IRHIDevice.h>
|
|
#include <RHI\IRHIResources.h>
|
|
#include <Rendering\Resources.h>
|
|
#include <Rendering\RenderContext.h>
|
|
#include <Rendering\StaticMeshComponent.h>
|
|
#include <Rendering\Shader.h>
|
|
#include <RHI\D3D12\D3D12RHI.h>
|
|
#include <RHI\D3D12\D3D12Resources.h>
|
|
|
|
#pragma comment(lib,"d3d12.lib")
|
|
#pragma comment(lib,"dxgi.lib")
|
|
#pragma comment(lib,"d3dcompiler.lib")
|
|
#pragma comment(lib,"winmm.lib")
|
|
|
|
using namespace XCEngine;
|
|
using namespace XCEngine::RHI;
|
|
|
|
LPCWSTR gWindowClassName = L"XCEngineDemo";
|
|
|
|
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|
switch (msg) {
|
|
case WM_CLOSE:
|
|
PostQuitMessage(0);
|
|
break;
|
|
}
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPWSTR lpCmdLine, int nShowCmd) {
|
|
AttachConsole(ATTACH_PARENT_PROCESS);
|
|
freopen("CONOUT$", "w", stdout);
|
|
freopen("CONOUT$", "w", stderr);
|
|
|
|
printf("=== XCEngine Demo Started ===\n");
|
|
printf("Registering window class...\n");
|
|
|
|
WNDCLASSEX wndClass = {};
|
|
wndClass.cbSize = sizeof(WNDCLASSEX);
|
|
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
|
wndClass.hInstance = hInstance;
|
|
wndClass.lpszClassName = gWindowClassName;
|
|
wndClass.lpfnWndProc = WindowProc;
|
|
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
if (!RegisterClassEx(&wndClass)) {
|
|
printf("RegisterClassEx failed!\n");
|
|
return -1;
|
|
}
|
|
printf("Window class registered\n");
|
|
printf("Creating window...\n");
|
|
|
|
int width = 1280;
|
|
int height = 720;
|
|
RECT rect = {0, 0, width, height};
|
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
|
|
HWND hwnd = CreateWindowExW(NULL, gWindowClassName, L"XCEngine Demo",
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);
|
|
|
|
if (!hwnd) {
|
|
printf("CreateWindowExW failed!\n");
|
|
return -1;
|
|
}
|
|
printf("Window created\n");
|
|
printf("Creating D3D12Device...\n");
|
|
|
|
D3D12Device* device = new D3D12Device();
|
|
if (!device->Initialize(hwnd, width, height)) {
|
|
printf("D3D12Device Init Failed!\n");
|
|
return -1;
|
|
}
|
|
printf("D3D12Device initialized\n");
|
|
|
|
RenderContext renderContext(device);
|
|
if (!renderContext.Initialize(width, height)) {
|
|
printf("RenderContext Init Failed!\n");
|
|
return -1;
|
|
}
|
|
|
|
ICommandList* cmdList = renderContext.GetCommandList();
|
|
|
|
ShaderBytecode vs, ps, gs = {};
|
|
if (!CompileShader("Res/Shader/gs.hlsl", "MainVS", "vs_5_1", vs)) {
|
|
printf("Compile VS Failed!\n");
|
|
return -1;
|
|
}
|
|
if (!CompileShader("Res/Shader/gs.hlsl", "MainPS", "ps_5_1", ps)) {
|
|
printf("Compile PS Failed!\n");
|
|
return -1;
|
|
}
|
|
if (!CompileShader("Res/Shader/gs.hlsl", "MainGS", "gs_5_1", gs)) {
|
|
printf("Compile GS Failed!\n");
|
|
return -1;
|
|
}
|
|
printf("Shaders compiled: VS=%llu, PS=%llu, GS=%llu\n",
|
|
(unsigned long long)vs.size, (unsigned long long)ps.size, (unsigned long long)gs.size);
|
|
|
|
RootParameter params[4] = {};
|
|
params[0].type = RootParameterType::CBV;
|
|
params[0].shaderRegister = 1;
|
|
params[0].registerSpace = 0;
|
|
params[0].visibility = ShaderVisibility::All;
|
|
|
|
params[1].type = RootParameterType::Constants;
|
|
params[1].shaderRegister = 0;
|
|
params[1].registerSpace = 0;
|
|
params[1].num32BitValues = 4;
|
|
params[1].visibility = ShaderVisibility::Vertex;
|
|
|
|
params[2].type = RootParameterType::DescriptorTable;
|
|
params[2].shaderRegister = 0;
|
|
params[2].registerSpace = 0;
|
|
params[2].visibility = ShaderVisibility::Pixel;
|
|
|
|
params[3].type = RootParameterType::SRV;
|
|
params[3].shaderRegister = 0;
|
|
params[3].registerSpace = 1;
|
|
params[3].visibility = ShaderVisibility::All;
|
|
|
|
RootSignatureDesc rsDesc = {};
|
|
rsDesc.parameters = params;
|
|
rsDesc.parameterCount = 4;
|
|
|
|
IRootSignature* rootSignature = nullptr;
|
|
if (!device->CreateRootSignature(&rootSignature, rsDesc)) {
|
|
printf("CreateRootSignature Failed!\n");
|
|
return -1;
|
|
}
|
|
printf("RootSignature created\n");
|
|
|
|
InputElementDesc inputElements[4] = {};
|
|
inputElements[0].semanticName = "POSITION";
|
|
inputElements[0].semanticIndex = 0;
|
|
inputElements[0].format = Format::R32G32B32A32_Float;
|
|
inputElements[0].inputSlot = 0;
|
|
inputElements[0].alignedByteOffset = 0;
|
|
|
|
inputElements[1].semanticName = "TEXCOORD";
|
|
inputElements[1].semanticIndex = 0;
|
|
inputElements[1].format = Format::R32G32B32A32_Float;
|
|
inputElements[1].inputSlot = 0;
|
|
inputElements[1].alignedByteOffset = 16;
|
|
|
|
inputElements[2].semanticName = "NORMAL";
|
|
inputElements[2].semanticIndex = 0;
|
|
inputElements[2].format = Format::R32G32B32A32_Float;
|
|
inputElements[2].inputSlot = 0;
|
|
inputElements[2].alignedByteOffset = 32;
|
|
|
|
inputElements[3].semanticName = "TANGENT";
|
|
inputElements[3].semanticIndex = 0;
|
|
inputElements[3].format = Format::R32G32B32A32_Float;
|
|
inputElements[3].inputSlot = 0;
|
|
inputElements[3].alignedByteOffset = 48;
|
|
|
|
InputLayoutDesc inputLayout = {};
|
|
inputLayout.elements = inputElements;
|
|
inputLayout.elementCount = 4;
|
|
|
|
PipelineDesc psoDesc = {};
|
|
psoDesc.rootSignature = rootSignature;
|
|
psoDesc.vertexShader = vs;
|
|
psoDesc.pixelShader = ps;
|
|
psoDesc.geometryShader = gs;
|
|
psoDesc.inputLayout = inputLayout;
|
|
psoDesc.topologyType = PrimitiveTopologyType::Triangle;
|
|
psoDesc.numRenderTargets = 1;
|
|
psoDesc.rtvFormats[0] = Format::R8G8B8A8_UNorm;
|
|
psoDesc.dsvFormat = Format::D24_UNorm_S8_UInt;
|
|
|
|
IPipelineState* pso = nullptr;
|
|
printf("Creating PipelineState...\n");
|
|
if (!device->CreatePipelineState(&pso, psoDesc)) {
|
|
printf("CreatePipelineState Failed!\n");
|
|
return -1;
|
|
}
|
|
printf("PipelineState created\n");
|
|
|
|
IConstantBuffer* cb = nullptr;
|
|
if (!CreateConstantBuffer(device, 65536, &cb)) {
|
|
printf("CreateConstantBuffer Failed!\n");
|
|
return -1;
|
|
}
|
|
|
|
float matrices[64] = {};
|
|
matrices[0] = 1.0f; matrices[5] = 1.0f; matrices[10] = 1.0f; matrices[15] = 1.0f;
|
|
matrices[16] = 1.0f; matrices[21] = 1.0f; matrices[26] = 1.0f; matrices[31] = 1.0f;
|
|
matrices[32] = 1.0f; matrices[37] = 1.0f; matrices[42] = 1.0f; matrices[47] = 1.0f;
|
|
matrices[48] = 1.0f; matrices[53] = 1.0f; matrices[58] = 1.0f; matrices[63] = 1.0f;
|
|
UpdateConstantBuffer(cb, matrices, sizeof(matrices));
|
|
|
|
StaticMeshComponent mesh;
|
|
if (!mesh.Initialize(cmdList, "Res/Model/Sphere.lhsm")) {
|
|
printf("Load Mesh Failed!\n");
|
|
return -1;
|
|
}
|
|
|
|
cmdList->Close();
|
|
ICommandQueue* queue = device->GetCommandQueue();
|
|
void* cmdListPtr = cmdList->GetNativeCommandList();
|
|
queue->ExecuteCommandLists(&cmdListPtr, 1);
|
|
|
|
ShowWindow(hwnd, nShowCmd);
|
|
UpdateWindow(hwnd);
|
|
|
|
MSG msg = {};
|
|
while (true) {
|
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
if (msg.message == WM_QUIT) break;
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
} else {
|
|
renderContext.BeginFrame();
|
|
|
|
renderContext.SetViewport((float)width, (float)height);
|
|
renderContext.SetScissor(width, height);
|
|
|
|
float color[4] = {0.5f, 0.5f, 0.5f, 1.0f};
|
|
renderContext.ClearRenderTarget(color);
|
|
renderContext.ClearDepthStencil();
|
|
|
|
cmdList->SetPipelineState(pso);
|
|
cmdList->SetRootSignature(rootSignature);
|
|
cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
|
|
|
mesh.Render(cmdList);
|
|
|
|
renderContext.EndFrame();
|
|
renderContext.Present();
|
|
}
|
|
}
|
|
|
|
renderContext.Shutdown();
|
|
delete pso;
|
|
delete rootSignature;
|
|
delete cb;
|
|
delete device;
|
|
|
|
return 0;
|
|
}
|