#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 #include #ifdef _DEBUG #include #endif namespace XCEngine { namespace RHI { namespace { std::string NarrowAscii(const std::wstring& value) { std::string result; result.reserve(value.size()); for (wchar_t ch : value) { result.push_back(static_cast(ch)); } return result; } bool HasShaderPayload(const ShaderCompileDesc& desc) { return !desc.source.empty() || !desc.fileName.empty(); } bool CompileD3D12Shader(const ShaderCompileDesc& desc, D3D12Shader& shader) { const std::string entryPoint = NarrowAscii(desc.entryPoint); const std::string profile = NarrowAscii(desc.profile); const char* entryPointPtr = entryPoint.empty() ? nullptr : entryPoint.c_str(); const char* profilePtr = profile.empty() ? nullptr : profile.c_str(); if (!desc.source.empty()) { return shader.Compile(desc.source.data(), desc.source.size(), entryPointPtr, profilePtr); } if (!desc.fileName.empty()) { return shader.CompileFromFile(desc.fileName.c_str(), entryPointPtr, profilePtr); } return false; } uint32_t GetFormatBytesPerPixel(Format format) { switch (format) { case Format::R8_UNorm: return 1; case Format::R8G8_UNorm: return 2; case Format::R8G8B8A8_UNorm: return 4; case Format::R16_Float: return 2; case Format::R16G16B16A16_Float: return 8; case Format::R32_Float: return 4; case Format::R32G32_Float: return 8; case Format::R32G32B32A32_Float: return 16; default: return 0; } } } // namespace 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; } QueryAdapterInfo(); 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; if (enableDebugLayer) { 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 = ToD3D12(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; } else if (d3d12Desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.width > 0 && desc.height > 0) { d3d12Desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; } d3d12Desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; const bool isDepthFormat = format == Format::D24_UNorm_S8_UInt || format == Format::D32_Float || format == Format::D16_UNorm; const D3D12_RESOURCE_STATES initialState = isDepthFormat ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_COMMON; if (texture->Initialize(m_device.Get(), d3d12Desc, initialState)) { if (isDepthFormat) { texture->SetState(ResourceStates::DepthWrite); } return texture; } delete texture; return nullptr; } RHITexture* D3D12Device::CreateTexture(const TextureDesc& desc, const void* initialData, size_t initialDataSize, uint32_t rowPitch) { (void)initialDataSize; if (initialData == nullptr) { return CreateTexture(desc); } if (desc.textureType != static_cast(TextureType::Texture2D)) { return nullptr; } const Format format = static_cast(desc.format); uint32_t resolvedRowPitch = rowPitch; if (resolvedRowPitch == 0) { const uint32_t bytesPerPixel = GetFormatBytesPerPixel(format); if (bytesPerPixel == 0) { return nullptr; } resolvedRowPitch = desc.width * bytesPerPixel; } D3D12CommandQueue uploadQueue; if (!uploadQueue.Initialize(m_device.Get(), CommandQueueType::Direct)) { return nullptr; } D3D12CommandAllocator uploadAllocator; if (!uploadAllocator.Initialize(m_device.Get(), CommandQueueType::Direct)) { uploadQueue.Shutdown(); return nullptr; } D3D12CommandList uploadCommandList; if (!uploadCommandList.Initialize(m_device.Get(), CommandQueueType::Direct, uploadAllocator.GetCommandAllocator())) { uploadAllocator.Shutdown(); uploadQueue.Shutdown(); return nullptr; } uploadAllocator.Reset(); uploadCommandList.Reset(); auto* texture = new D3D12Texture(); ComPtr uploadBuffer; if (!texture->InitializeFromData( m_device.Get(), uploadCommandList.GetCommandList(), initialData, desc.width, desc.height, ToD3D12(format), resolvedRowPitch, &uploadBuffer)) { delete texture; uploadCommandList.Shutdown(); uploadAllocator.Shutdown(); uploadQueue.Shutdown(); return nullptr; } texture->SetState(ResourceStates::PixelShaderResource); uploadCommandList.Close(); ID3D12CommandList* commandLists[] = { uploadCommandList.GetCommandList() }; uploadQueue.ExecuteCommandListsInternal(1, commandLists); uploadQueue.WaitForIdle(); uploadBuffer.Reset(); uploadCommandList.Shutdown(); uploadAllocator.Shutdown(); uploadQueue.Shutdown(); return texture; } RHIShader* D3D12Device::CreateShader(const ShaderCompileDesc& desc) { auto* shader = new D3D12Shader(); const std::string entryPoint = NarrowAscii(desc.entryPoint); const std::string profile = NarrowAscii(desc.profile); const char* entryPointPtr = entryPoint.empty() ? nullptr : entryPoint.c_str(); const char* profilePtr = profile.empty() ? nullptr : profile.c_str(); bool success = false; if (!desc.source.empty()) { success = shader->Compile(desc.source.data(), desc.source.size(), entryPointPtr, profilePtr); } else if (!desc.fileName.empty()) { success = shader->CompileFromFile(desc.fileName.c_str(), entryPointPtr, profilePtr); } if (success) { return shader; } delete shader; return nullptr; } RHISampler* D3D12Device::CreateSampler(const SamplerDesc& desc) { auto* sampler = new D3D12Sampler(); D3D12_SAMPLER_DESC d3d12Desc = {}; d3d12Desc.Filter = ToD3D12(static_cast(desc.filter)); d3d12Desc.AddressU = ToD3D12(static_cast(desc.addressU)); d3d12Desc.AddressV = ToD3D12(static_cast(desc.addressV)); d3d12Desc.AddressW = ToD3D12(static_cast(desc.addressW)); d3d12Desc.MipLODBias = desc.mipLodBias; d3d12Desc.MaxAnisotropy = desc.maxAnisotropy; d3d12Desc.ComparisonFunc = ToD3D12(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; } RHIResourceView* D3D12Device::CreateVertexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) { if (!buffer) { return nullptr; } auto* view = new D3D12ResourceView(); view->InitializeAsVertexBuffer(static_cast(buffer), desc); if (!view->IsValid()) { delete view; return nullptr; } return view; } RHIResourceView* D3D12Device::CreateIndexBufferView(RHIBuffer* buffer, const ResourceViewDesc& desc) { if (!buffer) { return nullptr; } auto* view = new D3D12ResourceView(); view->InitializeAsIndexBuffer(static_cast(buffer), desc); if (!view->IsValid()) { delete view; return nullptr; } return view; } RHISwapChain* D3D12Device::CreateSwapChain(const SwapChainDesc& desc, RHICommandQueue* presentQueue) { if (presentQueue == nullptr) { return nullptr; } auto* nativeQueue = static_cast(presentQueue->GetNativeHandle()); if (nativeQueue == nullptr) { return nullptr; } auto* swapChain = new D3D12SwapChain(); HWND hwnd = static_cast(desc.windowHandle); if (swapChain->Initialize(m_factory.Get(), nativeQueue, hwnd, desc.width, desc.height, desc.bufferCount)) { return swapChain; } delete swapChain; return nullptr; } RHICommandList* D3D12Device::CreateCommandList(const CommandListDesc& desc) { if (!m_device) { return nullptr; } auto allocator = std::make_unique(); if (!allocator->Initialize(m_device.Get(), static_cast(desc.commandListType))) { return nullptr; } auto* cmdList = new D3D12CommandList(); if (!cmdList->Initialize(m_device.Get(), static_cast(desc.commandListType), allocator->GetCommandAllocator())) { delete cmdList; return nullptr; } 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); const bool hasVertexShader = HasShaderPayload(desc.vertexShader); const bool hasFragmentShader = HasShaderPayload(desc.fragmentShader); const bool hasGeometryShader = HasShaderPayload(desc.geometryShader); if (!hasVertexShader && !hasFragmentShader && !hasGeometryShader) { return pso; } if (!hasVertexShader || !hasFragmentShader) { delete pso; return nullptr; } D3D12RootSignature* rootSignature = nullptr; if (desc.pipelineLayout != nullptr) { auto* pipelineLayout = static_cast(desc.pipelineLayout); pso->SetRootSignature(pipelineLayout->GetRootSignature()); } else { rootSignature = CreateRootSignature({}); if (rootSignature == nullptr) { delete pso; return nullptr; } pso->SetRootSignature(rootSignature->GetRootSignature()); } D3D12Shader vertexShader; D3D12Shader fragmentShader; D3D12Shader geometryShader; const bool vertexCompiled = CompileD3D12Shader(desc.vertexShader, vertexShader); const bool fragmentCompiled = CompileD3D12Shader(desc.fragmentShader, fragmentShader); const bool geometryCompiled = !hasGeometryShader || CompileD3D12Shader(desc.geometryShader, geometryShader); if (!vertexCompiled || !fragmentCompiled || !geometryCompiled) { if (rootSignature != nullptr) { rootSignature->Shutdown(); delete rootSignature; } delete pso; return nullptr; } pso->SetShaderBytecodes( vertexShader.GetD3D12Bytecode(), fragmentShader.GetD3D12Bytecode(), hasGeometryShader ? geometryShader.GetD3D12Bytecode() : D3D12_SHADER_BYTECODE{}); pso->EnsureValid(); if (rootSignature != nullptr) { rootSignature->Shutdown(); delete rootSignature; } if (!pso->IsValid()) { delete pso; return nullptr; } 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) { if (!texture) { return nullptr; } auto* view = new D3D12ResourceView(); auto* d3d12Texture = static_cast(texture); ID3D12Resource* resource = d3d12Texture->GetResource(); if (!resource) { delete view; return nullptr; } D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; rtvDesc.Format = ToD3D12(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)) { delete view; return nullptr; } view->InitializeAsRenderTarget(m_device.Get(), resource, &rtvDesc, heap.get(), 0); view->SetOwnedHeap(std::move(heap)); 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 = ToD3D12(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 = ToD3D12(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, false)) { 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, false)) { 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