feat: 实现D3D12Device类,整合D3D12Enum.h转换函数

- 简化D3D12Device,仅封装ID3D12Device和IDXGIFactory
- 将D3D12Common.h中的转换函数合并到D3D12Enum.h
- 添加ResourceStates枚举到Enums.h
- 更新测试项目使用新的D3D12Device类
- 更新CMake配置
This commit is contained in:
2026-03-15 03:02:15 +08:00
parent b2c7627a1b
commit cba4f9c838
8 changed files with 429 additions and 63 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(XCEngine)
project(XCEngineLib)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -83,6 +83,9 @@ add_library(XCEngine STATIC
# RHI
include/XCEngine/RHI/Enums.h
include/XCEngine/RHI/D3D12/D3D12Enum.h
include/XCEngine/RHI/D3D12/D3D12Device.h
src/RHI/D3D12Device.cpp
)
target_include_directories(XCEngine PUBLIC

View File

@@ -0,0 +1,74 @@
#pragma once
#include <d3d12.h>
#include <dxgi1_4.h>
#include <wrl/client.h>
#include <string>
#include <vector>
#include "../Enums.h"
#include "D3D12Enum.h"
using Microsoft::WRL::ComPtr;
namespace XCEngine {
namespace RHI {
struct AdapterInfo {
std::wstring description;
uint64_t dedicatedVideoMemory;
uint64_t dedicatedSystemMemory;
uint64_t sharedSystemMemory;
uint32_t vendorId;
uint32_t deviceId;
bool isSoftware;
};
struct DeviceInfo {
std::wstring deviceName;
std::wstring driverVersion;
uint64_t dedicatedVideoMemory;
uint64_t dedicatedSystemMemory;
uint64_t sharedSystemMemory;
uint32_t vendorId;
uint32_t deviceId;
bool supportsRaytracing;
bool supportsMeshShaders;
bool supportsSamplerFeedback;
};
class D3D12Device {
public:
D3D12Device();
~D3D12Device();
bool Initialize(bool enableDebugLayer = false);
void Shutdown();
ID3D12Device* GetDevice() const { return m_device.Get(); }
IDXGIFactory4* GetFactory() const { return m_factory.Get(); }
const DeviceInfo& GetDeviceInfo() const { return m_deviceInfo; }
std::vector<AdapterInfo> EnumerateAdapters();
bool CheckFeatureSupport(D3D12_FEATURE feature, void* featureSupportData, uint32_t featureSupportDataSize);
void SetDeviceRemoved() { m_isDeviceRemoved = true; }
bool IsDeviceRemoved() const { return m_isDeviceRemoved; }
private:
bool CreateDXGIFactory(bool enableDebugLayer);
bool CreateDevice(IDXGIAdapter1* adapter);
void QueryDeviceInfo();
ComPtr<ID3D12Device> m_device;
ComPtr<IDXGIFactory4> m_factory;
ComPtr<IDXGIAdapter1> m_adapter;
DeviceInfo m_deviceInfo;
bool m_isDeviceRemoved;
bool m_initialized;
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -1,6 +1,7 @@
#pragma once
#include <d3d12.h>
#include <dxgi1_4.h>
#include "../Enums.h"
namespace XCEngine {
@@ -131,5 +132,146 @@ inline D3D12_SHADER_VISIBILITY ToD3D12(ShaderVisibility visibility) {
return D3D12_SHADER_VISIBILITY_ALL;
}
inline DXGI_FORMAT ToD3D12(Format format) {
switch (format) {
case Format::Unknown: return DXGI_FORMAT_UNKNOWN;
case Format::R8_UNorm: return DXGI_FORMAT_R8_UNORM;
case Format::R8G8_UNorm: return DXGI_FORMAT_R8G8_UNORM;
case Format::R8G8B8A8_UNorm: return DXGI_FORMAT_R8G8B8A8_UNORM;
case Format::R16G16B16A16_Float: return DXGI_FORMAT_R16G16B16A16_FLOAT;
case Format::R32G32B32A32_Float: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case Format::R16_Float: return DXGI_FORMAT_R16_FLOAT;
case Format::R32_Float: return DXGI_FORMAT_R32_FLOAT;
case Format::D16_UNorm: return DXGI_FORMAT_D16_UNORM;
case Format::D24_UNorm_S8_UInt: return DXGI_FORMAT_D24_UNORM_S8_UINT;
case Format::D32_Float: return DXGI_FORMAT_D32_FLOAT;
case Format::BC1_UNorm: return DXGI_FORMAT_BC1_UNORM;
case Format::BC2_UNorm: return DXGI_FORMAT_BC2_UNORM;
case Format::BC3_UNorm: return DXGI_FORMAT_BC3_UNORM;
case Format::BC4_UNorm: return DXGI_FORMAT_BC4_UNORM;
case Format::BC5_UNorm: return DXGI_FORMAT_BC5_UNORM;
case Format::BC6H_UF16: return DXGI_FORMAT_BC6H_UF16;
case Format::BC7_UNorm: return DXGI_FORMAT_BC7_UNORM;
case Format::R32G32B32A32_UInt: return DXGI_FORMAT_R32G32B32A32_UINT;
case Format::R32_UInt: return DXGI_FORMAT_R32_UINT;
}
return DXGI_FORMAT_UNKNOWN;
}
inline D3D12_RESOURCE_STATES ToD3D12(ResourceStates state) {
switch (state) {
case ResourceStates::Common: return D3D12_RESOURCE_STATE_COMMON;
case ResourceStates::VertexAndConstantBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
case ResourceStates::IndexBuffer: return D3D12_RESOURCE_STATE_INDEX_BUFFER;
case ResourceStates::RenderTarget: return D3D12_RESOURCE_STATE_RENDER_TARGET;
case ResourceStates::UnorderedAccess: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
case ResourceStates::DepthWrite: return D3D12_RESOURCE_STATE_DEPTH_WRITE;
case ResourceStates::DepthRead: return D3D12_RESOURCE_STATE_DEPTH_READ;
case ResourceStates::NonPixelShaderResource: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
case ResourceStates::PixelShaderResource: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
case ResourceStates::CopySrc: return D3D12_RESOURCE_STATE_COPY_SOURCE;
case ResourceStates::CopyDst: return D3D12_RESOURCE_STATE_COPY_DEST;
case ResourceStates::Present: return D3D12_RESOURCE_STATE_PRESENT;
}
return D3D12_RESOURCE_STATE_COMMON;
}
inline D3D12_PRIMITIVE_TOPOLOGY_TYPE ToD3D12(PrimitiveTopology topology) {
switch (topology) {
case PrimitiveTopology::PointList: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case PrimitiveTopology::LineList:
case PrimitiveTopology::LineStrip:
case PrimitiveTopology::LineListAdj:
case PrimitiveTopology::LineStripAdj:
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case PrimitiveTopology::TriangleList:
case PrimitiveTopology::TriangleStrip:
case PrimitiveTopology::TriangleListAdj:
case PrimitiveTopology::TriangleStripAdj:
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case PrimitiveTopology::PatchList:
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
}
return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
}
inline D3D12_PRIMITIVE_TOPOLOGY ToD3D12Topology(PrimitiveTopology topology) {
switch (topology) {
case PrimitiveTopology::Undefined: return D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
case PrimitiveTopology::PointList: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case PrimitiveTopology::LineList: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
case PrimitiveTopology::LineStrip: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
case PrimitiveTopology::TriangleList: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case PrimitiveTopology::TriangleStrip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case PrimitiveTopology::LineListAdj: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
case PrimitiveTopology::LineStripAdj: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
case PrimitiveTopology::TriangleListAdj: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
case PrimitiveTopology::TriangleStripAdj: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
case PrimitiveTopology::PatchList: return D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST;
}
return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
inline D3D12_DESCRIPTOR_HEAP_TYPE ToD3D12(DescriptorHeapType type) {
switch (type) {
case DescriptorHeapType::CBV_SRV_UAV: return D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
case DescriptorHeapType::Sampler: return D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
case DescriptorHeapType::RTV: return D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
case DescriptorHeapType::DSV: return D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
}
return D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
}
inline D3D12_QUERY_TYPE ToD3D12(QueryType type) {
switch (type) {
case QueryType::Occlusion: return D3D12_QUERY_TYPE_OCCLUSION;
case QueryType::Timestamp: return D3D12_QUERY_TYPE_TIMESTAMP;
case QueryType::PipelineStatistics: return D3D12_QUERY_TYPE_PIPELINE_STATISTICS;
}
return D3D12_QUERY_TYPE_OCCLUSION;
}
inline D3D12_ROOT_PARAMETER_TYPE ToD3D12(RootParameterType type) {
switch (type) {
case RootParameterType::DescriptorTable: return D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
case RootParameterType::Constants: return D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
case RootParameterType::CBV: return D3D12_ROOT_PARAMETER_TYPE_CBV;
case RootParameterType::SRV: return D3D12_ROOT_PARAMETER_TYPE_SRV;
case RootParameterType::UAV: return D3D12_ROOT_PARAMETER_TYPE_UAV;
}
return D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
}
inline DXGI_FORMAT ToDXGI(Format format) {
return ToD3D12(format);
}
inline D3D12_RESOURCE_DIMENSION ToD3D12(TextureType type) {
switch (type) {
case TextureType::Texture1D: return D3D12_RESOURCE_DIMENSION_TEXTURE1D;
case TextureType::Texture2D:
case TextureType::Texture2DArray:
case TextureType::TextureCube:
case TextureType::TextureCubeArray:
return D3D12_RESOURCE_DIMENSION_TEXTURE2D;
case TextureType::Texture3D: return D3D12_RESOURCE_DIMENSION_TEXTURE3D;
}
return D3D12_RESOURCE_DIMENSION_TEXTURE2D;
}
inline D3D12_STENCIL_OP ToD3D12(StencilOp op) {
switch (op) {
case StencilOp::Keep: return D3D12_STENCIL_OP_KEEP;
case StencilOp::Zero: return D3D12_STENCIL_OP_ZERO;
case StencilOp::Replace: return D3D12_STENCIL_OP_REPLACE;
case StencilOp::IncrSat: return D3D12_STENCIL_OP_INCR_SAT;
case StencilOp::DecrSat: return D3D12_STENCIL_OP_DECR_SAT;
case StencilOp::Invert: return D3D12_STENCIL_OP_INVERT;
case StencilOp::Incr: return D3D12_STENCIL_OP_INCR;
case StencilOp::Decr: return D3D12_STENCIL_OP_DECR;
}
return D3D12_STENCIL_OP_KEEP;
}
} // namespace RHI
} // namespace XCEngine

View File

@@ -268,5 +268,20 @@ enum class Format : uint32_t {
R32_UInt
};
enum class ResourceStates : uint32_t {
Common,
VertexAndConstantBuffer,
IndexBuffer,
RenderTarget,
UnorderedAccess,
DepthWrite,
DepthRead,
NonPixelShaderResource,
PixelShaderResource,
CopySrc,
CopyDst,
Present
};
} // namespace RHI
} // namespace XCEngine

View File

@@ -0,0 +1,164 @@
#include "XCEngine/RHI/D3D12/D3D12Device.h"
#ifdef _DEBUG
#include <dxgidebug.h>
#endif
namespace XCEngine {
namespace RHI {
D3D12Device::D3D12Device()
: m_isDeviceRemoved(false)
, m_initialized(false)
{
}
D3D12Device::~D3D12Device() {
Shutdown();
}
bool D3D12Device::Initialize(bool enableDebugLayer) {
if (m_initialized) {
return true;
}
if (!CreateDXGIFactory(enableDebugLayer)) {
return false;
}
ComPtr<IDXGIAdapter1> adapter;
int adapterIndex = 0;
bool adapterFound = false;
while (m_factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
adapterIndex++;
continue;
}
HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
if (SUCCEEDED(hr)) {
adapterFound = true;
m_adapter = adapter;
break;
}
adapterIndex++;
}
if (!adapterFound) {
return false;
}
if (!CreateDevice(m_adapter.Get())) {
return false;
}
QueryDeviceInfo();
m_initialized = true;
return true;
}
void D3D12Device::Shutdown() {
if (m_device) {
m_device.Reset();
}
if (m_factory) {
m_factory.Reset();
}
m_adapter.Reset();
m_initialized = false;
}
bool D3D12Device::CreateDXGIFactory(bool enableDebugLayer) {
UINT dxgiFactoryFlags = 0;
#ifdef _DEBUG
if (enableDebugLayer) {
ID3D12Debug* debugController = nullptr;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
debugController->EnableDebugLayer();
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
debugController->Release();
}
}
#endif
HRESULT hr = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&m_factory));
return SUCCEEDED(hr);
}
bool D3D12Device::CreateDevice(IDXGIAdapter1* adapter) {
HRESULT hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
return SUCCEEDED(hr);
}
void D3D12Device::QueryDeviceInfo() {
if (!m_adapter) {
return;
}
DXGI_ADAPTER_DESC1 desc;
m_adapter->GetDesc1(&desc);
m_deviceInfo.vendorId = desc.VendorId;
m_deviceInfo.deviceId = desc.DeviceId;
m_deviceInfo.dedicatedVideoMemory = desc.DedicatedVideoMemory;
m_deviceInfo.dedicatedSystemMemory = desc.DedicatedSystemMemory;
m_deviceInfo.sharedSystemMemory = desc.SharedSystemMemory;
m_deviceInfo.deviceName = desc.Description;
m_deviceInfo.supportsRaytracing = false;
m_deviceInfo.supportsMeshShaders = false;
m_deviceInfo.supportsSamplerFeedback = false;
D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {};
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)))) {
m_deviceInfo.supportsRaytracing = (options5.RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED);
}
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7 = {};
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options7, sizeof(options7)))) {
m_deviceInfo.supportsSamplerFeedback = (options7.SamplerFeedbackTier != D3D12_SAMPLER_FEEDBACK_TIER_NOT_SUPPORTED);
m_deviceInfo.supportsMeshShaders = (options7.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED);
}
}
bool D3D12Device::CheckFeatureSupport(D3D12_FEATURE feature, void* featureSupportData, uint32_t featureSupportDataSize) {
return SUCCEEDED(m_device->CheckFeatureSupport(feature, featureSupportData, featureSupportDataSize));
}
std::vector<AdapterInfo> D3D12Device::EnumerateAdapters() {
std::vector<AdapterInfo> adapters;
if (!m_factory) {
return adapters;
}
ComPtr<IDXGIAdapter1> adapter;
int adapterIndex = 0;
while (m_factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
AdapterInfo info;
info.description = desc.Description;
info.dedicatedVideoMemory = desc.DedicatedVideoMemory;
info.dedicatedSystemMemory = desc.DedicatedSystemMemory;
info.sharedSystemMemory = desc.SharedSystemMemory;
info.vendorId = desc.VendorId;
info.deviceId = desc.DeviceId;
info.isSoftware = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0;
adapters.push_back(info);
adapterIndex++;
}
return adapters;
}
} // namespace RHI
} // namespace XCEngine