#include "XCEngine/RHI/D3D12/D3D12Device.h" #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" #include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h" #include "XCEngine/RHI/D3D12/D3D12QueryHeap.h" #include "XCEngine/RHI/D3D12/D3D12RootSignature.h" #include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h" #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" #include "XCEngine/RHI/D3D12/D3D12ResourceView.h" #include "XCEngine/RHI/D3D12/D3D12RenderPass.h" #include "XCEngine/RHI/D3D12/D3D12Framebuffer.h" #include #include #ifdef _DEBUG #include #endif namespace XCEngine { namespace RHI { D3D12Device::D3D12Device() : m_isDeviceRemoved(false) , m_initialized(false) { } D3D12Device::~D3D12Device() { Shutdown(); } bool D3D12Device::Initialize(const RHIDeviceDesc& desc) { if (m_initialized) { return true; } m_deviceDesc = desc; if (!CreateDXGIFactory(desc.enableDebugLayer)) { return false; } ComPtr adapter; int adapterIndex = desc.adapterIndex; bool adapterFound = false; while (m_factory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) { DXGI_ADAPTER_DESC1 descAdapter; adapter->GetDesc1(&descAdapter); if (descAdapter.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; } 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; } QueryAdapterInfo(); m_initialized = true; return true; } void D3D12Device::Shutdown() { if (m_commandQueue) { m_commandQueue.Reset(); } 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; { 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) { OutputDebugStringA("[DEBUG] CreateDevice: start\n"); HRESULT hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)); if (FAILED(hr)) { char buf[256]; sprintf(buf, "[DEBUG] CreateDevice: D3D12CreateDevice failed! hr=%08X\n", hr); OutputDebugStringA(buf); } return SUCCEEDED(hr); } void D3D12Device::QueryAdapterInfo() { if (!m_adapter) { return; } DXGI_ADAPTER_DESC1 desc; m_adapter->GetDesc1(&desc); 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; 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; D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {}; if (SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)))) { m_capabilities.bSupportsRayTracing = 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_capabilities.bSupportsMeshShaders = options7.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; } 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; } bool D3D12Device::CheckFeatureSupport(D3D12_FEATURE feature, void* featureSupportData, uint32_t featureSupportDataSize) { return SUCCEEDED(m_device->CheckFeatureSupport(feature, featureSupportData, featureSupportDataSize)); } std::vector D3D12Device::EnumerateAdapters() { std::vector adapters; if (!m_factory) { return adapters; } ComPtr 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; } UINT D3D12Device::GetDescriptorHandleIncrementSize(DescriptorHeapType type) const { return m_device->GetDescriptorHandleIncrementSize(ToD3D12(type)); } void* D3D12Device::GetNativeHandle() const { return m_device.Get(); } 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(); D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_DEFAULT; if (desc.bufferType == static_cast(BufferType::ReadBack)) { heapType = D3D12_HEAP_TYPE_READBACK; } else if (desc.bufferType == static_cast(BufferType::Constant) || desc.bufferType == static_cast(BufferType::Vertex) || desc.bufferType == static_cast(BufferType::Index)) { 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(desc.bufferType)); return buffer; } delete buffer; return nullptr; } RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc) { auto* texture = new D3D12Texture(); D3D12_RESOURCE_DESC d3d12Desc = {}; d3d12Desc.Dimension = ToD3D12(static_cast(desc.textureType)); d3d12Desc.Width = desc.width; d3d12Desc.Height = desc.height; d3d12Desc.DepthOrArraySize = desc.depth > 0 ? desc.depth : 1; d3d12Desc.MipLevels = desc.mipLevels > 0 ? desc.mipLevels : 1; d3d12Desc.Format = static_cast(desc.format); d3d12Desc.SampleDesc.Count = desc.sampleCount > 0 ? desc.sampleCount : 1; d3d12Desc.SampleDesc.Quality = desc.sampleQuality; d3d12Desc.Flags = static_cast(desc.flags); Format format = static_cast(desc.format); if (format == Format::D24_UNorm_S8_UInt || format == Format::D32_Float || format == Format::D16_UNorm) { d3d12Desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } d3d12Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; if (texture->Initialize(m_device.Get(), d3d12Desc)) { return texture; } delete texture; return nullptr; } RHIShader* D3D12Device::CompileShader(const ShaderCompileDesc& desc) { auto* shader = new D3D12Shader(); const char* entryPoint = desc.entryPoint.empty() ? nullptr : reinterpret_cast(desc.entryPoint.c_str()); const char* profile = desc.profile.empty() ? nullptr : reinterpret_cast(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) { return shader; } delete shader; return nullptr; } RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) { auto* sampler = new D3D12Sampler(); D3D12_SAMPLER_DESC d3d12Desc = {}; d3d12Desc.Filter = static_cast(desc.filter); d3d12Desc.AddressU = static_cast(desc.addressU); d3d12Desc.AddressV = static_cast(desc.addressV); d3d12Desc.AddressW = static_cast(desc.addressW); d3d12Desc.MipLODBias = desc.mipLodBias; d3d12Desc.MaxAnisotropy = desc.maxAnisotropy; d3d12Desc.ComparisonFunc = static_cast(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)) { return sampler; } delete sampler; return nullptr; } 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; } RHIRenderPass* D3D12Device::CreateRenderPass( uint32_t colorAttachmentCount, const AttachmentDesc* colorAttachments, const AttachmentDesc* depthStencilAttachment) { auto* renderPass = new D3D12RenderPass(); if (!renderPass->Initialize(colorAttachmentCount, colorAttachments, depthStencilAttachment)) { delete renderPass; return nullptr; } return renderPass; } RHIFramebuffer* D3D12Device::CreateFramebuffer( class RHIRenderPass* renderPass, uint32_t width, uint32_t height, uint32_t colorAttachmentCount, RHIResourceView** colorAttachments, RHIResourceView* depthStencilAttachment) { auto* framebuffer = new D3D12Framebuffer(); if (!framebuffer->Initialize(renderPass, width, height, colorAttachmentCount, colorAttachments, depthStencilAttachment)) { delete framebuffer; return nullptr; } return framebuffer; } RHIDescriptorSet* D3D12Device::CreateDescriptorSet(RHIDescriptorPool* pool, const DescriptorSetLayoutDesc& layout) { if (pool == nullptr) { return nullptr; } return pool->AllocateSet(layout); } 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) { auto* swapChain = new D3D12SwapChain(); HWND hwnd = static_cast(desc.windowHandle); if (swapChain->Initialize(m_factory.Get(), m_commandQueue.Get(), hwnd, desc.width, desc.height, desc.bufferCount)) { return swapChain; } delete swapChain; return nullptr; } RHICommandList* D3D12Device::CreateCommandList(const CommandListDesc& desc) { FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f) { fprintf(f, "[CreateCommandList] Start, m_device=%p, m_initialized=%d\n", m_device.Get(), m_initialized); fclose(f); } if (!m_device) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateCommandList] Error: m_device is null\n"); fclose(f2); } return nullptr; } auto allocator = std::make_unique(); if (!allocator->Initialize(m_device.Get(), static_cast(desc.commandListType))) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateCommandList] Error: allocator Initialize failed\n"); fclose(f2); } return nullptr; } auto* cmdList = new D3D12CommandList(); if (!cmdList->Initialize(m_device.Get(), static_cast(desc.commandListType), allocator->GetCommandAllocator())) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateCommandList] Error: cmdList Initialize failed\n"); fclose(f2); } delete cmdList; return nullptr; } FILE* f3 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f3) { fprintf(f3, "[CreateCommandList] Success\n"); fclose(f3); } return cmdList; } RHICommandQueue* D3D12Device::CreateCommandQueue(const CommandQueueDesc& desc) { auto* queue = new D3D12CommandQueue(); if (queue->Initialize(m_device.Get(), static_cast(desc.queueType))) { return queue; } delete queue; return nullptr; } 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; } RHIPipelineLayout* D3D12Device::CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) { auto* pipelineLayout = new D3D12PipelineLayout(); if (!pipelineLayout->InitializeWithDevice(this, desc)) { delete pipelineLayout; return nullptr; } return pipelineLayout; } RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const ResourceViewDesc& desc) { FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f) { fprintf(f, "[CreateRenderTargetView] Start\n"); fclose(f); } if (!texture) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateRenderTargetView] Error: texture is null\n"); fclose(f2); } return nullptr; } auto* view = new D3D12ResourceView(); auto* d3d12Texture = static_cast(texture); ID3D12Resource* resource = d3d12Texture->GetResource(); if (!resource) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateRenderTargetView] Error: resource is null\n"); fclose(f2); } delete view; return nullptr; } D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; rtvDesc.Format = static_cast(desc.format); rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; auto heap = std::make_unique(); if (!heap->Initialize(m_device.Get(), DescriptorHeapType::RTV, 1, false)) { FILE* f2 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f2) { fprintf(f2, "[CreateRenderTargetView] Error: heap Initialize failed\n"); fclose(f2); } delete view; return nullptr; } view->InitializeAsRenderTarget(m_device.Get(), resource, &rtvDesc, heap.get(), 0); view->SetOwnedHeap(std::move(heap)); FILE* f3 = fopen("D:\\Xuanchi\\Main\\XCEngine\\debug_rhi.log", "a"); if (f3) { fprintf(f3, "[CreateRenderTargetView] Success\n"); fclose(f3); } return view; } RHIResourceView* D3D12Device::CreateDepthStencilView(RHITexture* texture, const ResourceViewDesc& desc) { auto* view = new D3D12ResourceView(); auto* d3d12Texture = static_cast(texture); ID3D12Resource* resource = d3d12Texture->GetResource(); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.Format = static_cast(desc.format); dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; auto heap = std::make_unique(); if (!heap->Initialize(m_device.Get(), DescriptorHeapType::DSV, 1, false)) { delete view; return nullptr; } view->InitializeAsDepthStencil(m_device.Get(), resource, &dsvDesc, heap.get(), 0); view->SetOwnedHeap(std::move(heap)); return view; } RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, const ResourceViewDesc& desc) { auto* view = new D3D12ResourceView(); auto* d3d12Texture = static_cast(texture); ID3D12Resource* resource = d3d12Texture->GetResource(); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = static_cast(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; auto heap = std::make_unique(); if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, true)) { delete view; return nullptr; } view->InitializeAsShaderResource(m_device.Get(), resource, &srvDesc, heap.get(), 0); view->SetOwnedHeap(std::move(heap)); return view; } RHIResourceView* D3D12Device::CreateUnorderedAccessView(RHITexture* texture, const ResourceViewDesc& desc) { auto* view = new D3D12ResourceView(); auto* d3d12Texture = static_cast(texture); ID3D12Resource* resource = d3d12Texture->GetResource(); D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; uavDesc.Format = static_cast(desc.format); uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; auto heap = std::make_unique(); if (!heap->Initialize(m_device.Get(), DescriptorHeapType::CBV_SRV_UAV, 1, true)) { delete view; return nullptr; } view->InitializeAsUnorderedAccess(m_device.Get(), resource, &uavDesc, heap.get(), 0); view->SetOwnedHeap(std::move(heap)); return view; } D3D12DescriptorHeap* D3D12Device::CreateDescriptorHeap(const DescriptorHeapDesc& desc) { auto* heap = new D3D12DescriptorHeap(); if (!heap->Initialize(m_device.Get(), static_cast(desc.heapType), desc.descriptorCount, desc.shaderVisible)) { delete heap; return nullptr; } return heap; } D3D12QueryHeap* D3D12Device::CreateQueryHeap(const QueryHeapDesc& desc) { auto* queryHeap = new D3D12QueryHeap(); if (!queryHeap->Initialize(m_device.Get(), static_cast(desc.queryType), desc.count)) { delete queryHeap; return nullptr; } return queryHeap; } D3D12RootSignature* D3D12Device::CreateRootSignature(const RootSignatureDesc& desc) { 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; } D3D12CommandQueue* D3D12Device::CreateCommandQueueImpl(const CommandQueueDesc& desc) { return nullptr; } D3D12CommandList* D3D12Device::CreateCommandListImpl(const CommandListDesc& desc) { return nullptr; } } // namespace RHI } // namespace XCEngine