//-------------------------------------------------------------------------- void D3D12Renderer::Term() { for (auto pkWindow : m_kRenderWindowList) { pkWindow->Term(); } VE_ASSERT(m_kRenderWindowList.empty()); m_kSRVHeap.Term(); m_kDSVHeap.Term(); m_kRTVHeap.Term(); VE_SAFE_RELEASE(m_pkDevice); VE_SAFE_RELEASE(m_pkDefaultAdapter); VE_SAFE_RELEASE(m_pkDXGIFactory); D3D12GetDebugInterface = nullptr; D3D12CreateDevice = nullptr; D3D12SerializeRootSignature = nullptr; CreateDXGIFactory1 = nullptr; D3DCompile = nullptr; m_spD3D12 = nullptr; m_spDXGI = nullptr; m_spD3DCompiler = nullptr; }
//-------------------------------------------------------------------------- void D3D12RenderWindow::Init(D3D12Renderer& kRenderer) noexcept { if ((!m_kNode.is_attach()) && m_spTargetWindow) { D3D12_COMMAND_QUEUE_DESC kQueueDesc = {}; kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc, IID_PPV_ARGS(&m_pkCommandQueue)), S_OK); DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {}; kSwapChainDesc.BufferCount = D3D12Renderer::FRAME_COUNT; kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth(); kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight(); kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; kSwapChainDesc.OutputWindow = (HWND)(m_spTargetWindow->GetNativeHandle()); kSwapChainDesc.SampleDesc.Count = 1; kSwapChainDesc.Windowed = TRUE; IDXGISwapChain* pkSwapChain; VE_ASSERT_GE(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue, &kSwapChainDesc, &pkSwapChain), S_OK); VE_ASSERT_GE(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain)), S_OK); VE_SAFE_RELEASE(pkSwapChain); VE_ASSERT(m_pkCommandQueue && m_pkSwapChain); for (uint32_t i(0); i < D3D12Renderer::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK); kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc(); kRenderer.m_pkDevice->CreateRenderTargetView( kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK); kFrame.m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, kFrame.m_pkDirectAllocator, nullptr, IID_PPV_ARGS(&kFrame.m_pkTestList)), S_OK); VE_ASSERT_GE(kFrame.m_pkTestList->Close(), S_OK); } m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK); m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); VE_ASSERT(m_kFenceEvent); const uint64_t u64FenceToWaitFor = m_u64FenceValue++; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK); VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); m_u32FramePtr = m_pkSwapChain->GetCurrentBackBufferIndex(); m_u64FrameIndex = 0; m_spTargetWindow->Show(); kRenderer.m_kRenderWindowList.attach_back(m_kNode); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::ResizeBundleList(VeSizeT stNum) noexcept { for (VeInt32 i(0); i < VeRendererD3D12::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(kFrame.m_pkBundleAllocator->Reset(), S_OK); VeSizeT stCurrentNum = kFrame.m_kBundleCommandList.size(); if (stNum >= stCurrentNum) { for (auto& list : kFrame.m_kBundleCommandList) { VE_ASSERT_GE(list->Reset(kFrame.m_pkBundleAllocator, nullptr), S_OK); } kFrame.m_kBundleCommandList.resize(stNum); VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); for (VeSizeT i(stCurrentNum); i < stNum; ++i) { VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_BUNDLE, kFrame.m_pkBundleAllocator, nullptr, IID_PPV_ARGS(&kFrame.m_kBundleCommandList[i])), S_OK); } } else if (stNum < stCurrentNum) { for (VeSizeT i(stNum); i < stCurrentNum; ++i) { VE_ASSERT_GE(kFrame.m_kBundleCommandList[i]->Close(), S_OK); VE_SAFE_RELEASE(kFrame.m_kBundleCommandList[i]); } kFrame.m_kBundleCommandList.resize(stNum); } } }
//-------------------------------------------------------------------------- void D3D12RenderWindow::Term() noexcept { if (m_kNode.is_attach()) { D3D12Renderer& kRenderer = *vtd::member_cast( &D3D12Renderer::m_kRenderWindowList, m_kNode.get_list()); const uint64_t u64LastCompleted = m_pkFence->GetCompletedValue(); VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue), S_OK); if (u64LastCompleted < m_u64FenceValue) { VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(m_u64FenceValue, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); } CloseHandle(m_kFenceEvent); VE_SAFE_RELEASE(m_pkFence); for (auto& kFrame : m_akFrameCache) { VE_SAFE_RELEASE(kFrame.m_pkTestList); for (auto& list : kFrame.m_kDirectCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkDirectAllocator); kFrame.m_kDirectCommandList.clear(); for (auto& list : kFrame.m_kBundleCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkBundleAllocator); kFrame.m_kBundleCommandList.clear(); kRenderer.m_kRTVHeap.Free((uint32_t)(kFrame.m_hHandle.ptr - kRenderer.m_kRTVHeap.GetCPUStart().ptr)); VE_SAFE_RELEASE(kFrame.m_pkBufferResource); } VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); m_kNode.detach(); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Term() noexcept { if (m_kNode.is_attach()) { VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); const VeUInt64 u64LastCompleted = m_pkFence->GetCompletedValue(); VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, m_u64FenceValue), S_OK); if (u64LastCompleted < m_u64FenceValue) { VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(m_u64FenceValue, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); } CloseHandle(m_kFenceEvent); VE_SAFE_RELEASE(m_pkFence); m_kResourceMap.clear(); m_kRecorderList.clear(); m_kCameraList.clear(); m_kProcessList.clear(); for (VeInt32 i(VeRendererD3D12::FRAME_COUNT - 1); i >= 0; --i) { FrameCache& kFrame = m_akFrameCache[i]; for (auto& list : kFrame.m_kDirectCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkDirectAllocator); kFrame.m_kDirectCommandList.clear(); for (auto& list : kFrame.m_kBundleCommandList) { VE_SAFE_RELEASE(list); } VE_SAFE_RELEASE(kFrame.m_pkBundleAllocator); kFrame.m_kBundleCommandList.clear(); kRenderer.m_kRTVHeap.Free(kFrame.m_hHandle.ptr - kRenderer.m_kRTVHeap.GetCPUStart().ptr); VE_SAFE_RELEASE(kFrame.m_pkBufferResource); } VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); m_kNode.detach(); } }
//-------------------------------------------------------------------------- void D3D12Renderer::Init() { m_spD3D12 = VE_NEW VeSharedLib(LIB_D3D12); if (!m_spD3D12->Load()) { THROW("Failed to load " LIB_D3D12 "."); } m_spDXGI = VE_NEW VeSharedLib(LIB_DXGI); if (!m_spDXGI->Load()) { THROW("Failed to load " LIB_DXGI "."); } m_spD3DCompiler = VE_NEW VeSharedLib(LIB_D3DCOMPLIER); if (!m_spD3DCompiler->Load()) { THROW("Failed to load " LIB_D3DCOMPLIER "."); } D3D12GetDebugInterface = (decltype(D3D12GetDebugInterface)) m_spD3D12->GetProc("D3D12GetDebugInterface"); if (!D3D12GetDebugInterface) { THROW("Failed to fetch function D3D12GetDebugInterface."); } D3D12CreateDevice = (decltype(D3D12CreateDevice)) m_spD3D12->GetProc("D3D12CreateDevice"); if (!D3D12CreateDevice) { THROW("Failed to fetch function D3D12CreateDevice."); } D3D12SerializeRootSignature = (decltype(D3D12SerializeRootSignature)) m_spD3D12->GetProc("D3D12SerializeRootSignature"); if (!D3D12SerializeRootSignature) { THROW("Failed to fetch function D3D12SerializeRootSignature."); } CreateDXGIFactory1 = (decltype(CreateDXGIFactory1)) m_spDXGI->GetProc("CreateDXGIFactory1"); if (!CreateDXGIFactory1) { THROW("Failed to fetch function CreateDXGIFactory1."); } D3DCompile = (decltype(D3DCompile)) m_spD3DCompiler->GetProc("D3DCompile"); if (!D3DCompile) { THROW("Failed to fetch function D3DCompile."); } # ifdef VE_DEBUG { ID3D12Debug* pkDebugController(nullptr); if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pkDebugController)))) { pkDebugController->EnableDebugLayer(); } VE_SAFE_RELEASE(pkDebugController); } # endif if (VE_FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&m_pkDXGIFactory)))) { THROW("Failed to create DXGI factory."); } if (m_pkDXGIFactory->EnumAdapters1(0, &m_pkDefaultAdapter) == DXGI_ERROR_NOT_FOUND) { THROW("Failed to get main adapter."); } if (VE_FAILED(D3D12CreateDevice(m_pkDefaultAdapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pkDevice)))) { THROW("Failed to create d3d12 device."); } m_kRTVHeap.Init(m_pkDevice); m_kDSVHeap.Init(m_pkDevice); m_kSRVHeap.Init(m_pkDevice); VeCoreLogI("D3D12Renderer created successfully."); }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Init(VeRendererD3D12& kRenderer) noexcept { if ((!m_kNode.is_attach()) && m_spTargetWindow) { D3D12_COMMAND_QUEUE_DESC kQueueDesc = {}; kQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; kQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; if (FAILED(kRenderer.m_pkDevice->CreateCommandQueue(&kQueueDesc, IID_PPV_ARGS(&m_pkCommandQueue)))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(m_pkSwapChain); return; } DXGI_SWAP_CHAIN_DESC kSwapChainDesc = {}; kSwapChainDesc.BufferCount = VeRendererD3D12::FRAME_COUNT; kSwapChainDesc.BufferDesc.Width = m_spTargetWindow->GetWidth(); kSwapChainDesc.BufferDesc.Height = m_spTargetWindow->GetHeight(); kSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; kSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; kSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; kSwapChainDesc.OutputWindow = m_spTargetWindow->GetWMInfo().win.window; kSwapChainDesc.SampleDesc.Count = 1; kSwapChainDesc.Windowed = TRUE; IDXGISwapChain* pkSwapChain; if (FAILED(kRenderer.m_pkDXGIFactory->CreateSwapChain(m_pkCommandQueue, &kSwapChainDesc, &pkSwapChain))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(pkSwapChain); return; } if (FAILED(pkSwapChain->QueryInterface(IID_PPV_ARGS(&m_pkSwapChain)))) { VE_SAFE_RELEASE(m_pkCommandQueue); VE_SAFE_RELEASE(pkSwapChain); VE_SAFE_RELEASE(m_pkSwapChain); return; } else { VE_SAFE_RELEASE(pkSwapChain); } VE_ASSERT(m_pkCommandQueue && m_pkSwapChain); for (VeInt32 i(0); i < VeRendererD3D12::FRAME_COUNT; ++i) { FrameCache& kFrame = m_akFrameCache[i]; VE_ASSERT_GE(m_pkSwapChain->GetBuffer(i, IID_PPV_ARGS(&kFrame.m_pkBufferResource)), S_OK); kFrame.m_hHandle.ptr = kRenderer.m_kRTVHeap.GetCPUStart().ptr + kRenderer.m_kRTVHeap.Alloc(); kRenderer.m_pkDevice->CreateRenderTargetView( kFrame.m_pkBufferResource, nullptr, kFrame.m_hHandle); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&kFrame.m_pkDirectAllocator)), S_OK); VE_ASSERT_GE(kRenderer.m_pkDevice->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&kFrame.m_pkBundleAllocator)), S_OK); kFrame.m_u64FenceValue = 0; } m_u64FenceValue = 0; VE_ASSERT_GE(kRenderer.m_pkDevice->CreateFence(m_u64FenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pkFence)), S_OK); m_kFenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); VE_ASSERT(m_kFenceEvent); const VeUInt64 u64FenceToWaitFor = m_u64FenceValue++; VE_ASSERT_GE(m_pkCommandQueue->Signal(m_pkFence, u64FenceToWaitFor), S_OK); VE_ASSERT_GE(m_pkFence->SetEventOnCompletion(u64FenceToWaitFor, m_kFenceEvent), S_OK); WaitForSingleObject(m_kFenceEvent, INFINITE); m_u32FrameIndex = m_pkSwapChain->GetCurrentBackBufferIndex(); kRenderer.m_kRenderWindowList.attach_back(m_kNode); } m_kViewport.TopLeftX = 0; m_kViewport.TopLeftY = 0; m_kViewport.Width = m_spTargetWindow->GetWidth(); m_kViewport.Height = m_spTargetWindow->GetHeight(); m_kViewport.MinDepth = 0.0f; m_kViewport.MaxDepth = 1.0f; m_kScissorRect.left = 0; m_kScissorRect.right = m_spTargetWindow->GetWidth(); m_kScissorRect.top = 0; m_kScissorRect.bottom = m_spTargetWindow->GetHeight(); { m_vertexBufferView.BufferLocation = kRenderer.m_kRenderBufferList.get_tail_node()->m_Content->m_pkResource->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(VE_FLOAT3); m_vertexBufferView.SizeInBytes = kRenderer.m_kRenderBufferList.get_head_node()->m_Content->GetSize(); } }
void Compile(VeChar8* pcFileName, VeChar8* pcDstDir) { VeChar8* pcFile = VeStrrchr(pcFileName, '/'); VeSizeT stNum = pcFile - pcFileName; VeChar8 acBuffer[2048]; VeMemcpy(acBuffer, pcFileName, stNum); acBuffer[stNum] = 0; ++pcFile; VeFileDir kFile(acBuffer); VeChar8* pcContent; VeChar8* pcTemp = VeStrtok(pcDstDir, "/", &pcContent); VE_ASSERT(pcTemp && *pcTemp); VeFileDir kDstFile(pcTemp); pcTemp = VeStrtok(NULL, "/", &pcContent); while(pcTemp && *pcTemp) { kDstFile.Change(pcTemp); pcTemp = VeStrtok(NULL, "/", &pcContent); } VeBinaryIStreamPtr spStream = kFile.OpenSync(pcFile); VE_ASSERT(spStream); VeXMLDocument kDoc; (*spStream) >> kDoc; VE_ASSERT(!kDoc.Error()); VeXMLElement* pkRoot = kDoc.RootElement(); VeXMLElement* pkGroup = pkRoot->FirstChildElement("Group"); while(pkGroup) { VeXMLElement* pkShader = pkGroup->FirstChildElement(); while(pkShader) { const VeChar8* pcName = pkShader->Value(); const VeChar8* pcSrc = pkShader->GetAttribute("src"); const VeChar8* pcEntry = pkShader->GetAttribute("entry"); VeStringA kFile(acBuffer); kFile += '/'; kFile += pcSrc; VeVector<const VeChar8*> kProfileList; VeXMLElement* pkProfile = pkShader->FirstChildElement("Profile"); while(pkProfile) { const VeChar8* pcProfile = pkProfile->GetAttribute("value"); kProfileList.PushBack(pcProfile); pkProfile = pkProfile->NextSiblingElement("Profile"); } VeVector<D3D_SHADER_MACRO> kMacroList; VeXMLElement* pkMacro = pkShader->FirstChildElement("Macro"); while(pkMacro) { D3D_SHADER_MACRO kMac; kMac.Name = pkMacro->GetAttribute("name"); kMac.Definition = pkMacro->GetAttribute("define"); kMacroList.PushBack(kMac); pkMacro = pkMacro->NextSiblingElement("Macro"); } D3D_SHADER_MACRO kLast = {NULL, NULL}; kMacroList.PushBack(kLast); for(VeVector<const VeChar8*>::iterator it = kProfileList.Begin(); it != kProfileList.End(); ++it) { HRESULT hRes = S_OK; ID3DBlob* pkOut; ID3DBlob* pkErrorBlob; hRes = D3DX11CompileFromFile(kFile, kMacroList.Begin(), NULL, pcEntry, *it, D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR, 0, NULL, &pkOut, &pkErrorBlob, NULL); if(VE_FAILED(hRes)) { if(pkErrorBlob) { VE_LOG_EString("HLSLComplier", (VeChar8*)pkErrorBlob->GetBufferPointer()); } } else { VeStringA kOutputName(pcName); kOutputName += '.'; kOutputName += *it; VeMemoryOStreamPtr spOutputStream = VE_NEW VeMemoryOStream(); spOutputStream->AddBlob(pkOut->GetBufferPointer(), pkOut->GetBufferSize()); kDstFile.WriteAsync(kOutputName, spOutputStream, g_kWriteDelegate); } VE_SAFE_RELEASE(pkOut); VE_SAFE_RELEASE(pkErrorBlob); } pkShader = pkShader->NextSiblingElement(); } pkGroup = pkGroup->NextSiblingElement("Group"); } }