D3D12: Fix Quad test screenshot and update texture
- Fix SetGraphicsRootDescriptorTable call order (SetRootSignature before SetPipelineState) - Rename texture earth_d.jpg -> earth.png - Fix vertex order for TriangleStrip quad rendering - Add integration test README - Add debug logging to D3D12Screenshot - Remove obsolete run.bat
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "RHI/D3D12/D3D12Texture.h"
|
||||
#include "Debug/Logger.h"
|
||||
#include <d3d12.h>
|
||||
#include <dxgi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -65,6 +66,13 @@ bool D3D12Screenshot::CopyToReadbackAndSave(ID3D12Device* device,
|
||||
ID3D12CommandAllocator* cmdAlloc = nullptr;
|
||||
HRESULT hr = device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
|
||||
if (FAILED(hr)) {
|
||||
XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::Rendering, "Screenshot: CreateCommandAllocator failed");
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED) {
|
||||
HRESULT removedReason = device->GetDeviceRemovedReason();
|
||||
char reasonMsg[256];
|
||||
sprintf_s(reasonMsg, sizeof(reasonMsg), "Screenshot: Device removed reason: 0x%X", removedReason);
|
||||
XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::Rendering, reasonMsg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -93,6 +101,7 @@ bool D3D12Screenshot::CopyToReadbackAndSave(ID3D12Device* device,
|
||||
IID_PPV_ARGS(&readbackBuffer));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::Rendering, "Screenshot: CreateCommittedResource failed");
|
||||
cmdAlloc->Release();
|
||||
return false;
|
||||
}
|
||||
@@ -100,6 +109,7 @@ bool D3D12Screenshot::CopyToReadbackAndSave(ID3D12Device* device,
|
||||
ID3D12GraphicsCommandList* cmdList = nullptr;
|
||||
hr = device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdList));
|
||||
if (FAILED(hr)) {
|
||||
XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::Rendering, "Screenshot: CreateCommandList failed");
|
||||
cmdAlloc->Release();
|
||||
readbackBuffer->Release();
|
||||
return false;
|
||||
@@ -140,11 +150,21 @@ bool D3D12Screenshot::CopyToReadbackAndSave(ID3D12Device* device,
|
||||
cmdList->Close();
|
||||
ID3D12CommandList* ppCmdLists[] = { cmdList };
|
||||
commandQueue->ExecuteCommandLists(1, ppCmdLists);
|
||||
XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::Rendering, "Screenshot: ExecuteCommandLists done, waiting for fence...");
|
||||
|
||||
HANDLE fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
ID3D12Fence* fence = nullptr;
|
||||
hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::Rendering, "Screenshot: CreateFence failed");
|
||||
cmdList->Release();
|
||||
cmdAlloc->Release();
|
||||
readbackBuffer->Release();
|
||||
CloseHandle(fenceEvent);
|
||||
return false;
|
||||
}
|
||||
XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::Rendering, "Screenshot: Fence created, waiting...");
|
||||
{
|
||||
UINT64 fenceValue = 1;
|
||||
commandQueue->Signal(fence, fenceValue);
|
||||
if (fence->GetCompletedValue() < fenceValue) {
|
||||
|
||||
@@ -8,4 +8,5 @@ enable_testing()
|
||||
|
||||
add_subdirectory(minimal)
|
||||
add_subdirectory(triangle)
|
||||
add_subdirectory(quad)
|
||||
add_subdirectory(render_model)
|
||||
|
||||
36
tests/RHI/D3D12/integration/README.md
Normal file
36
tests/RHI/D3D12/integration/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# D3D12 Integration Tests
|
||||
|
||||
## minimal
|
||||
**后端**: D3D12Device, DXGIFactory, CommandQueue, CommandList, SwapChain
|
||||
**内容**: 最小 D3D12 初始化流程,创建窗口和交换链,无渲染输出
|
||||
|
||||
---
|
||||
|
||||
## triangle
|
||||
**后端**: D3D12Device, DXGIFactory, CommandQueue, CommandList, SwapChain, Buffer, Shader, RootSignature, PipelineState, RenderTargetView, DepthStencilView, Screenshot
|
||||
**内容**:
|
||||
- 基础三角形渲染
|
||||
- 顶点 buffer 上传
|
||||
- HLSL shader 编译 (vs_5_1, ps_5_1)
|
||||
- Root signature + PSO 创建
|
||||
- RenderTarget 切换 (Present ↔ RenderTarget)
|
||||
- 截图功能验证
|
||||
|
||||
---
|
||||
|
||||
## quad
|
||||
**后端**: triangle 的全部 + Texture, DescriptorHeap, ShaderResourceView
|
||||
**内容**:
|
||||
- 四边形纹理采样渲染
|
||||
- Texture 加载与初始化 (stb_image)
|
||||
- DescriptorHeap (CBV_SRV_UAV) + SRV 创建
|
||||
- 静态采样器配置
|
||||
- Root signature descriptor table
|
||||
- SetDescriptorHeaps + SetGraphicsRootDescriptorTable
|
||||
- 截图功能验证
|
||||
|
||||
---
|
||||
|
||||
## render_model
|
||||
**后端**: (TODO)
|
||||
**内容**: 模型渲染 (待实现)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
@@ -95,8 +95,6 @@ bool LoadTexture(const char* filename, D3D12Texture& texture, D3D12ShaderResourc
|
||||
return false;
|
||||
}
|
||||
|
||||
Log("[INFO] Loaded texture %s: %dx%d", filename, width, height);
|
||||
|
||||
allocator.Reset();
|
||||
commandList->Reset(allocator.GetCommandAllocator(), nullptr);
|
||||
|
||||
@@ -112,9 +110,8 @@ bool LoadTexture(const char* filename, D3D12Texture& texture, D3D12ShaderResourc
|
||||
queue.WaitForIdle();
|
||||
|
||||
texture.SetName(filename);
|
||||
stbi_image_free(pixels);
|
||||
|
||||
srvHeap.Initialize(device, DescriptorHeapType::CBV_SRV_UAV, 1);
|
||||
srvHeap.Initialize(device, DescriptorHeapType::CBV_SRV_UAV, 1, true);
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = D3D12ShaderResourceView::CreateDesc(Format::R8G8B8A8_UNorm, D3D12_SRV_DIMENSION_TEXTURE2D);
|
||||
srv.InitializeAt(device, texture.GetResource(), srvHeap.GetCPUDescriptorHandleForHeapStart(), &srvDesc);
|
||||
|
||||
@@ -263,8 +260,8 @@ bool InitD3D12() {
|
||||
Vertex vertices[] = {
|
||||
{ { -0.5f, -0.5f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 0.0f } },
|
||||
{ { -0.5f, 0.5f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 0.0f } },
|
||||
{ { 0.5f, 0.5f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 0.0f } },
|
||||
{ { 0.5f, -0.5f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 0.0f } },
|
||||
{ { 0.5f, 0.5f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 0.0f } },
|
||||
};
|
||||
|
||||
if (!gVertexBuffer.InitializeWithData(device, gCommandList.GetCommandList(), vertices, sizeof(vertices), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)) {
|
||||
@@ -274,7 +271,7 @@ bool InitD3D12() {
|
||||
gVertexBuffer.SetStride(sizeof(Vertex));
|
||||
gVertexBuffer.SetBufferType(BufferType::Vertex);
|
||||
|
||||
if (!LoadTexture("Res/Image/earth_d.jpg", gDiffuseTexture, gDiffuseSRV, device, gSRVHeap, gCommandList.GetCommandList(), gCommandAllocator, gCommandQueue)) {
|
||||
if (!LoadTexture("Res/Image/earth.png", gDiffuseTexture, gDiffuseSRV, device, gSRVHeap, gCommandList.GetCommandList(), gCommandAllocator, gCommandQueue)) {
|
||||
Log("[ERROR] Failed to load texture");
|
||||
return false;
|
||||
}
|
||||
@@ -384,23 +381,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
|
||||
BeginRender();
|
||||
|
||||
gCommandList.SetRootSignature(gRootSignature.GetRootSignature());
|
||||
gCommandList.SetPipelineState(gPipelineState.GetPipelineState());
|
||||
|
||||
ID3D12DescriptorHeap* heaps[] = { gSRVHeap.GetDescriptorHeap() };
|
||||
gCommandList.SetDescriptorHeaps(1, heaps);
|
||||
gCommandList.SetGraphicsRootDescriptorTable(0, gSRVHeap.GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
gCommandList.SetPipelineState(gPipelineState.GetPipelineState());
|
||||
gCommandList.SetRootSignature(gRootSignature.GetRootSignature());
|
||||
gCommandList.SetPrimitiveTopology(PrimitiveTopology::TriangleList);
|
||||
gCommandList.SetPrimitiveTopology(PrimitiveTopology::TriangleStrip);
|
||||
gCommandList.SetVertexBuffer(0, gVertexBuffer.GetResource(), 0, gVertexBuffer.GetStride());
|
||||
gCommandList.Draw(4, 1, 0, 0);
|
||||
|
||||
frameCount++;
|
||||
|
||||
if (frameCount >= targetFrameCount) {
|
||||
Log("[INFO] Reached target frame count %d - taking screenshot!", targetFrameCount);
|
||||
ExecuteCommandList();
|
||||
WaitForGPU();
|
||||
Log("[INFO] GPU idle, taking screenshot...");
|
||||
|
||||
bool screenshotResult = D3D12Screenshot::Capture(
|
||||
gDevice,
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
@echo off
|
||||
cd /d "%~dp0..\..\..\..\build\tests\RHI\D3D12\integration\Debug"
|
||||
if exist "D3D12_engine_log.txt" del "D3D12_engine_log.txt"
|
||||
if exist "screenshot.ppm" del "screenshot.ppm"
|
||||
D3D12.exe
|
||||
python "%~dp0compare_ppm.py" "screenshot.ppm" "GT.ppm" 5
|
||||
pause
|
||||
Reference in New Issue
Block a user