2026-03-15 03:02:15 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Device.h"
|
2026-03-15 23:03:06 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12CommandQueue.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12CommandList.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12CommandAllocator.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Fence.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
2026-03-25 00:26:16 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
2026-03-15 23:03:06 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12QueryHeap.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12RootSignature.h"
|
2026-03-24 19:47:22 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
2026-03-15 23:03:06 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12PipelineState.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Sampler.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Texture.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Buffer.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12SwapChain.h"
|
|
|
|
|
#include "XCEngine/RHI/D3D12/D3D12Shader.h"
|
2026-03-24 03:49:13 +08:00
|
|
|
#include "XCEngine/RHI/D3D12/D3D12ResourceView.h"
|
2026-03-15 12:51:18 +08:00
|
|
|
#include <stdio.h>
|
2026-03-15 03:02:15 +08:00
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
#include <dxgidebug.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace RHI {
|
|
|
|
|
|
|
|
|
|
D3D12Device::D3D12Device()
|
|
|
|
|
: m_isDeviceRemoved(false)
|
|
|
|
|
, m_initialized(false)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12Device::~D3D12Device() {
|
|
|
|
|
Shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
bool D3D12Device::Initialize(const RHIDeviceDesc& desc) {
|
2026-03-15 03:02:15 +08:00
|
|
|
if (m_initialized) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 18:53:29 +08:00
|
|
|
m_deviceDesc = desc;
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
if (!CreateDXGIFactory(desc.enableDebugLayer)) {
|
2026-03-15 03:02:15 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ComPtr<IDXGIAdapter1> adapter;
|
2026-03-17 17:45:01 +08:00
|
|
|
int adapterIndex = desc.adapterIndex;
|
2026-03-15 03:02:15 +08:00
|
|
|
bool adapterFound = false;
|
|
|
|
|
|
|
|
|
|
while (m_factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
2026-03-17 17:45:01 +08:00
|
|
|
DXGI_ADAPTER_DESC1 descAdapter;
|
|
|
|
|
adapter->GetDesc1(&descAdapter);
|
2026-03-15 03:02:15 +08:00
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
if (descAdapter.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
2026-03-15 03:02:15 +08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 18:53:29 +08:00
|
|
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
|
|
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
|
|
|
queueDesc.Priority = 0;
|
|
|
|
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
|
|
|
queueDesc.NodeMask = 0;
|
|
|
|
|
if (FAILED(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)))) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 21:50:54 +08:00
|
|
|
QueryAdapterInfo();
|
2026-03-15 03:02:15 +08:00
|
|
|
m_initialized = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void D3D12Device::Shutdown() {
|
2026-03-23 18:53:29 +08:00
|
|
|
if (m_commandQueue) {
|
|
|
|
|
m_commandQueue.Reset();
|
|
|
|
|
}
|
2026-03-15 03:02:15 +08:00
|
|
|
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;
|
|
|
|
|
|
2026-03-15 12:51:18 +08:00
|
|
|
{
|
2026-03-15 03:02:15 +08:00
|
|
|
ID3D12Debug* debugController = nullptr;
|
|
|
|
|
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
|
|
|
|
debugController->EnableDebugLayer();
|
|
|
|
|
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
|
|
|
|
debugController->Release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT hr = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&m_factory));
|
|
|
|
|
return SUCCEEDED(hr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool D3D12Device::CreateDevice(IDXGIAdapter1* adapter) {
|
2026-03-15 12:51:18 +08:00
|
|
|
OutputDebugStringA("[DEBUG] CreateDevice: start\n");
|
2026-03-15 03:02:15 +08:00
|
|
|
HRESULT hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
2026-03-15 12:51:18 +08:00
|
|
|
if (FAILED(hr)) {
|
|
|
|
|
char buf[256];
|
|
|
|
|
sprintf(buf, "[DEBUG] CreateDevice: D3D12CreateDevice failed! hr=%08X\n", hr);
|
|
|
|
|
OutputDebugStringA(buf);
|
|
|
|
|
}
|
2026-03-15 03:02:15 +08:00
|
|
|
return SUCCEEDED(hr);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 21:50:54 +08:00
|
|
|
void D3D12Device::QueryAdapterInfo() {
|
2026-03-15 03:02:15 +08:00
|
|
|
if (!m_adapter) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
|
|
|
|
m_adapter->GetDesc1(&desc);
|
|
|
|
|
|
2026-03-16 21:50:54 +08:00
|
|
|
m_adapterInfo.vendorId = desc.VendorId;
|
|
|
|
|
m_adapterInfo.deviceId = desc.DeviceId;
|
|
|
|
|
m_adapterInfo.dedicatedVideoMemory = desc.DedicatedVideoMemory;
|
|
|
|
|
m_adapterInfo.dedicatedSystemMemory = desc.DedicatedSystemMemory;
|
|
|
|
|
m_adapterInfo.sharedSystemMemory = desc.SharedSystemMemory;
|
|
|
|
|
m_adapterInfo.description = desc.Description;
|
|
|
|
|
m_adapterInfo.isSoftware = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0;
|
2026-03-15 03:02:15 +08:00
|
|
|
|
2026-03-23 18:53:29 +08:00
|
|
|
m_deviceInfo.description = desc.Description;
|
|
|
|
|
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.isSoftware = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != 0;
|
|
|
|
|
|
|
|
|
|
switch (desc.VendorId) {
|
|
|
|
|
case 0x10DE: m_deviceInfo.vendor = L"NVIDIA"; break;
|
|
|
|
|
case 0x1002: m_deviceInfo.vendor = L"AMD"; break;
|
|
|
|
|
case 0x8086: m_deviceInfo.vendor = L"Intel"; break;
|
|
|
|
|
default: m_deviceInfo.vendor = L"Unknown"; break;
|
|
|
|
|
}
|
|
|
|
|
m_deviceInfo.renderer = desc.Description;
|
|
|
|
|
|
2026-03-15 03:02:15 +08:00
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {};
|
|
|
|
|
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)))) {
|
2026-03-23 18:53:29 +08:00
|
|
|
m_capabilities.bSupportsRayTracing = options5.RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED;
|
2026-03-15 03:02:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7 = {};
|
|
|
|
|
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options7, sizeof(options7)))) {
|
2026-03-23 18:53:29 +08:00
|
|
|
m_capabilities.bSupportsMeshShaders = options7.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED;
|
2026-03-15 03:02:15 +08:00
|
|
|
}
|
2026-03-23 18:53:29 +08:00
|
|
|
|
|
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
|
|
|
|
|
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) {
|
|
|
|
|
m_capabilities.bSupportsConservativeRasterization = options.ConservativeRasterizationTier != D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS3 options3 = {};
|
|
|
|
|
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &options3, sizeof(options3)))) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12_FEATURE_DATA_D3D12_OPTIONS4 options4 = {};
|
|
|
|
|
if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4, &options4, sizeof(options4)))) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_capabilities.maxRenderTargets = 8;
|
|
|
|
|
m_capabilities.maxViewports = 16;
|
|
|
|
|
m_capabilities.maxVertexAttribs = 8;
|
|
|
|
|
m_capabilities.maxColorAttachments = 8;
|
|
|
|
|
m_capabilities.maxConstantBufferSize = D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;
|
|
|
|
|
m_capabilities.maxAnisotropy = D3D12_MAX_MAXANISOTROPY;
|
|
|
|
|
m_capabilities.maxTexture2DSize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
|
|
|
|
m_capabilities.maxTexture3DSize = D3D12_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
|
|
|
|
|
m_capabilities.maxTextureCubeSize = D3D12_REQ_TEXTURECUBE_DIMENSION;
|
2026-03-15 03:02:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 20:31:37 +08:00
|
|
|
UINT D3D12Device::GetDescriptorHandleIncrementSize(DescriptorHeapType type) const {
|
|
|
|
|
return m_device->GetDescriptorHandleIncrementSize(ToD3D12(type));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 23:03:06 +08:00
|
|
|
void* D3D12Device::GetNativeHandle() const {
|
|
|
|
|
return m_device.Get();
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
void* D3D12Device::GetNativeDevice() {
|
|
|
|
|
return m_device.Get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const RHICapabilities& D3D12Device::GetCapabilities() const {
|
|
|
|
|
return m_capabilities;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const RHIDeviceInfo& D3D12Device::GetDeviceInfo() const {
|
|
|
|
|
return m_deviceInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIBuffer* D3D12Device::CreateBuffer(const BufferDesc& desc) {
|
|
|
|
|
auto* buffer = new D3D12Buffer();
|
2026-03-17 19:35:51 +08:00
|
|
|
D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_DEFAULT;
|
|
|
|
|
if (desc.bufferType == static_cast<uint32_t>(BufferType::ReadBack)) {
|
|
|
|
|
heapType = D3D12_HEAP_TYPE_READBACK;
|
2026-03-23 18:53:29 +08:00
|
|
|
} else if (desc.bufferType == static_cast<uint32_t>(BufferType::Constant) ||
|
|
|
|
|
desc.bufferType == static_cast<uint32_t>(BufferType::Vertex) ||
|
|
|
|
|
desc.bufferType == static_cast<uint32_t>(BufferType::Index)) {
|
2026-03-17 19:35:51 +08:00
|
|
|
heapType = D3D12_HEAP_TYPE_UPLOAD;
|
|
|
|
|
}
|
|
|
|
|
if (buffer->Initialize(m_device.Get(), desc.size, D3D12_RESOURCE_STATE_COMMON, heapType)) {
|
|
|
|
|
buffer->SetStride(desc.stride);
|
|
|
|
|
buffer->SetBufferType(static_cast<BufferType>(desc.bufferType));
|
2026-03-17 17:45:01 +08:00
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
delete buffer;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) {
|
|
|
|
|
auto* texture = new D3D12Texture();
|
2026-03-17 19:35:51 +08:00
|
|
|
D3D12_RESOURCE_DESC d3d12Desc = {};
|
refactor: improve test infrastructure and fix OpenGL GLAD initialization
- Rename D3D12Enum.h to D3D12Enums.h for naming consistency
- Fix OpenGL unit test GLAD initialization by using gladLoadGL()
instead of gladLoadGLLoader(wglGetProcAddress) for fallback support
- Migrate remaining tests to use gtest_discover_tests for granular
test discovery (math, core, containers, memory, threading, debug,
components, scene, resources, input, opengl)
- Remove obsolete TEST_RESOURCES_DIR and copy_directory commands
from OpenGL unit test CMakeLists (minimal/Res doesn't exist)
- Update TEST_SPEC.md with performance metrics and per-module
build/test commands for faster development workflow
- Update CMake path references to use lowercase paths
2026-03-23 00:43:02 +08:00
|
|
|
|
|
|
|
|
d3d12Desc.Dimension = ToD3D12(static_cast<TextureType>(desc.textureType));
|
|
|
|
|
|
2026-03-17 19:35:51 +08:00
|
|
|
d3d12Desc.Width = desc.width;
|
|
|
|
|
d3d12Desc.Height = desc.height;
|
2026-03-23 21:46:14 +08:00
|
|
|
d3d12Desc.DepthOrArraySize = desc.depth > 0 ? desc.depth : 1;
|
|
|
|
|
d3d12Desc.MipLevels = desc.mipLevels > 0 ? desc.mipLevels : 1;
|
2026-03-17 19:35:51 +08:00
|
|
|
d3d12Desc.Format = static_cast<DXGI_FORMAT>(desc.format);
|
2026-03-23 21:46:14 +08:00
|
|
|
d3d12Desc.SampleDesc.Count = desc.sampleCount > 0 ? desc.sampleCount : 1;
|
2026-03-17 19:35:51 +08:00
|
|
|
d3d12Desc.SampleDesc.Quality = desc.sampleQuality;
|
|
|
|
|
d3d12Desc.Flags = static_cast<D3D12_RESOURCE_FLAGS>(desc.flags);
|
|
|
|
|
d3d12Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
|
|
|
|
if (texture->Initialize(m_device.Get(), d3d12Desc)) {
|
2026-03-17 17:45:01 +08:00
|
|
|
return texture;
|
|
|
|
|
}
|
|
|
|
|
delete texture;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIShader* D3D12Device::CompileShader(const ShaderCompileDesc& desc) {
|
|
|
|
|
auto* shader = new D3D12Shader();
|
2026-03-25 12:00:26 +08:00
|
|
|
const char* entryPoint = desc.entryPoint.empty() ? nullptr : reinterpret_cast<const char*>(desc.entryPoint.c_str());
|
|
|
|
|
const char* profile = desc.profile.empty() ? nullptr : reinterpret_cast<const char*>(desc.profile.c_str());
|
|
|
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
|
if (!desc.source.empty()) {
|
|
|
|
|
success = shader->Compile(desc.source.data(), desc.source.size(), entryPoint, profile);
|
|
|
|
|
} else if (!desc.fileName.empty()) {
|
|
|
|
|
success = shader->CompileFromFile(desc.fileName.c_str(), entryPoint, profile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (success) {
|
2026-03-17 17:45:01 +08:00
|
|
|
return shader;
|
|
|
|
|
}
|
|
|
|
|
delete shader;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) {
|
|
|
|
|
auto* sampler = new D3D12Sampler();
|
2026-03-17 19:35:51 +08:00
|
|
|
D3D12_SAMPLER_DESC d3d12Desc = {};
|
|
|
|
|
d3d12Desc.Filter = static_cast<D3D12_FILTER>(desc.filter);
|
|
|
|
|
d3d12Desc.AddressU = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressU);
|
|
|
|
|
d3d12Desc.AddressV = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressV);
|
|
|
|
|
d3d12Desc.AddressW = static_cast<D3D12_TEXTURE_ADDRESS_MODE>(desc.addressW);
|
|
|
|
|
d3d12Desc.MipLODBias = desc.mipLodBias;
|
|
|
|
|
d3d12Desc.MaxAnisotropy = desc.maxAnisotropy;
|
|
|
|
|
d3d12Desc.ComparisonFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.comparisonFunc);
|
|
|
|
|
d3d12Desc.BorderColor[0] = desc.borderColorR;
|
|
|
|
|
d3d12Desc.BorderColor[1] = desc.borderColorG;
|
|
|
|
|
d3d12Desc.BorderColor[2] = desc.borderColorB;
|
|
|
|
|
d3d12Desc.BorderColor[3] = desc.borderColorA;
|
|
|
|
|
d3d12Desc.MinLOD = desc.minLod;
|
|
|
|
|
d3d12Desc.MaxLOD = desc.maxLod;
|
|
|
|
|
if (sampler->Initialize(m_device.Get(), d3d12Desc)) {
|
2026-03-17 17:45:01 +08:00
|
|
|
return sampler;
|
|
|
|
|
}
|
|
|
|
|
delete sampler;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 00:26:16 +08:00
|
|
|
RHIDescriptorPool* D3D12Device::CreateDescriptorPool(const DescriptorPoolDesc& desc) {
|
|
|
|
|
auto* pool = new D3D12DescriptorHeap();
|
|
|
|
|
DescriptorPoolDesc poolDesc = desc;
|
|
|
|
|
poolDesc.device = m_device.Get();
|
|
|
|
|
if (pool->Initialize(poolDesc)) {
|
|
|
|
|
return pool;
|
|
|
|
|
}
|
|
|
|
|
delete pool;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIDescriptorSet* D3D12Device::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) {
|
|
|
|
|
if (pool == nullptr) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return pool->AllocateSet(layout);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
RHIFence* D3D12Device::CreateFence(const FenceDesc& desc) {
|
|
|
|
|
auto* fence = new D3D12Fence();
|
|
|
|
|
if (fence->Initialize(m_device.Get(), desc.initialValue)) {
|
|
|
|
|
return fence;
|
|
|
|
|
}
|
|
|
|
|
delete fence;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHISwapChain* D3D12Device::CreateSwapChain(const SwapChainDesc& desc) {
|
2026-03-23 18:53:29 +08:00
|
|
|
auto* swapChain = new D3D12SwapChain();
|
2026-03-24 23:00:49 +08:00
|
|
|
HWND hwnd = static_cast<HWND>(desc.windowHandle);
|
2026-03-23 18:53:29 +08:00
|
|
|
if (swapChain->Initialize(m_factory.Get(), m_commandQueue.Get(), hwnd,
|
|
|
|
|
desc.width, desc.height, desc.bufferCount)) {
|
|
|
|
|
return swapChain;
|
|
|
|
|
}
|
|
|
|
|
delete swapChain;
|
2026-03-17 17:45:01 +08:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHICommandList* D3D12Device::CreateCommandList(const CommandListDesc& desc) {
|
2026-03-23 18:53:29 +08:00
|
|
|
auto* allocator = new D3D12CommandAllocator();
|
|
|
|
|
if (!allocator->Initialize(m_device.Get(), static_cast<CommandQueueType>(desc.commandListType))) {
|
|
|
|
|
delete allocator;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto* cmdList = new D3D12CommandList();
|
|
|
|
|
if (!cmdList->Initialize(m_device.Get(), static_cast<CommandQueueType>(desc.commandListType), allocator->GetCommandAllocator())) {
|
|
|
|
|
delete allocator;
|
|
|
|
|
delete cmdList;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return cmdList;
|
2026-03-17 17:45:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHICommandQueue* D3D12Device::CreateCommandQueue(const CommandQueueDesc& desc) {
|
2026-03-23 18:53:29 +08:00
|
|
|
auto* queue = new D3D12CommandQueue();
|
|
|
|
|
if (queue->Initialize(m_device.Get(), static_cast<CommandQueueType>(desc.queueType))) {
|
|
|
|
|
return queue;
|
|
|
|
|
}
|
|
|
|
|
delete queue;
|
2026-03-17 17:45:01 +08:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 18:33:16 +08:00
|
|
|
RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& desc) {
|
|
|
|
|
auto* pso = new D3D12PipelineState(m_device.Get());
|
|
|
|
|
pso->SetInputLayout(desc.inputLayout);
|
|
|
|
|
pso->SetRasterizerState(desc.rasterizerState);
|
|
|
|
|
pso->SetBlendState(desc.blendState);
|
|
|
|
|
pso->SetDepthStencilState(desc.depthStencilState);
|
|
|
|
|
pso->SetTopology(desc.topologyType);
|
|
|
|
|
pso->SetRenderTargetFormats(desc.renderTargetCount, desc.renderTargetFormats, desc.depthStencilFormat);
|
|
|
|
|
pso->SetSampleCount(desc.sampleCount);
|
|
|
|
|
return pso;
|
2026-03-17 17:45:01 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-24 19:47:22 +08:00
|
|
|
RHIPipelineLayout* D3D12Device::CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) {
|
|
|
|
|
auto* pipelineLayout = new D3D12PipelineLayout();
|
|
|
|
|
if (!pipelineLayout->InitializeWithDevice(this, desc)) {
|
|
|
|
|
delete pipelineLayout;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return pipelineLayout;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 03:49:13 +08:00
|
|
|
RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) {
|
|
|
|
|
auto* view = new D3D12ResourceView();
|
|
|
|
|
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
|
|
|
|
|
ID3D12Resource* resource = d3d12Texture->GetResource();
|
|
|
|
|
|
|
|
|
|
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
|
|
|
|
rtvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
|
|
|
|
|
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
|
|
|
|
|
|
|
|
|
DescriptorHeapDesc heapDesc = {};
|
|
|
|
|
heapDesc.descriptorCount = 1;
|
|
|
|
|
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::RTV);
|
|
|
|
|
heapDesc.shaderVisible = false;
|
|
|
|
|
auto* heapPool = CreateDescriptorHeap(heapDesc);
|
|
|
|
|
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
|
|
|
|
|
|
|
|
|
|
view->InitializeAsRenderTarget(m_device.Get(), resource, &rtvDesc, heap, 0);
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIResourceView* D3D12Device::CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) {
|
|
|
|
|
auto* view = new D3D12ResourceView();
|
|
|
|
|
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
|
|
|
|
|
ID3D12Resource* resource = d3d12Texture->GetResource();
|
|
|
|
|
|
|
|
|
|
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
|
|
|
|
|
dsvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
|
|
|
|
|
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
|
|
|
|
|
|
|
|
|
|
DescriptorHeapDesc heapDesc = {};
|
|
|
|
|
heapDesc.descriptorCount = 1;
|
|
|
|
|
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::DSV);
|
|
|
|
|
heapDesc.shaderVisible = false;
|
|
|
|
|
auto* heapPool = CreateDescriptorHeap(heapDesc);
|
|
|
|
|
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
|
|
|
|
|
|
|
|
|
|
view->InitializeAsDepthStencil(m_device.Get(), resource, &dsvDesc, heap, 0);
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) {
|
|
|
|
|
auto* view = new D3D12ResourceView();
|
|
|
|
|
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
|
|
|
|
|
ID3D12Resource* resource = d3d12Texture->GetResource();
|
|
|
|
|
|
|
|
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
|
|
|
srvDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
|
|
|
|
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
|
|
|
|
srvDesc.Texture2D.MipLevels = desc.mipLevel > 0 ? desc.mipLevel : 1;
|
|
|
|
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
|
|
|
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
|
|
|
|
|
|
|
|
|
DescriptorHeapDesc heapDesc = {};
|
|
|
|
|
heapDesc.descriptorCount = 1;
|
|
|
|
|
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::CBV_SRV_UAV);
|
|
|
|
|
heapDesc.shaderVisible = true;
|
|
|
|
|
auto* heapPool = CreateDescriptorHeap(heapDesc);
|
|
|
|
|
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
|
|
|
|
|
|
|
|
|
|
view->InitializeAsShaderResource(m_device.Get(), resource, &srvDesc, heap, 0);
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RHIResourceView* D3D12Device::CreateUnorderedAccessView(RHITexture* texture, const ResourceViewDesc& desc) {
|
|
|
|
|
auto* view = new D3D12ResourceView();
|
|
|
|
|
auto* d3d12Texture = static_cast<D3D12Texture*>(texture);
|
|
|
|
|
ID3D12Resource* resource = d3d12Texture->GetResource();
|
|
|
|
|
|
|
|
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
|
|
|
|
|
uavDesc.Format = static_cast<DXGI_FORMAT>(desc.format);
|
|
|
|
|
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
|
|
|
|
|
|
|
|
|
|
DescriptorHeapDesc heapDesc = {};
|
|
|
|
|
heapDesc.descriptorCount = 1;
|
|
|
|
|
heapDesc.heapType = static_cast<uint32_t>(DescriptorHeapType::CBV_SRV_UAV);
|
|
|
|
|
heapDesc.shaderVisible = true;
|
|
|
|
|
auto* heapPool = CreateDescriptorHeap(heapDesc);
|
|
|
|
|
auto* heap = static_cast<D3D12DescriptorHeap*>(heapPool);
|
|
|
|
|
|
|
|
|
|
view->InitializeAsUnorderedAccess(m_device.Get(), resource, &uavDesc, heap, 0);
|
|
|
|
|
return view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12DescriptorHeap* D3D12Device::CreateDescriptorHeap(const DescriptorHeapDesc& desc) {
|
|
|
|
|
auto* heap = new D3D12DescriptorHeap();
|
|
|
|
|
if (!heap->Initialize(m_device.Get(),
|
|
|
|
|
static_cast<DescriptorHeapType>(desc.heapType),
|
|
|
|
|
desc.descriptorCount,
|
|
|
|
|
desc.shaderVisible)) {
|
|
|
|
|
delete heap;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return heap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12QueryHeap* D3D12Device::CreateQueryHeap(const QueryHeapDesc& desc) {
|
2026-03-24 17:20:51 +08:00
|
|
|
auto* queryHeap = new D3D12QueryHeap();
|
|
|
|
|
if (!queryHeap->Initialize(m_device.Get(), static_cast<QueryType>(desc.queryType), desc.count)) {
|
|
|
|
|
delete queryHeap;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return queryHeap;
|
2026-03-24 03:49:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12RootSignature* D3D12Device::CreateRootSignature(const RootSignatureDesc& desc) {
|
2026-03-24 17:20:51 +08:00
|
|
|
auto* rootSig = new D3D12RootSignature();
|
|
|
|
|
|
|
|
|
|
D3D12_ROOT_SIGNATURE_DESC rootSigDesc = {};
|
|
|
|
|
rootSigDesc.NumParameters = 0;
|
|
|
|
|
rootSigDesc.NumStaticSamplers = 0;
|
|
|
|
|
rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
|
|
|
|
|
|
|
|
|
if (!rootSig->Initialize(m_device.Get(), rootSigDesc)) {
|
|
|
|
|
delete rootSig;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rootSig;
|
2026-03-24 03:49:13 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
D3D12CommandQueue* D3D12Device::CreateCommandQueueImpl(const CommandQueueDesc& desc) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
D3D12CommandList* D3D12Device::CreateCommandListImpl(const CommandListDesc& desc) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-15 03:02:15 +08:00
|
|
|
} // namespace RHI
|
|
|
|
|
} // namespace XCEngine
|