// Load the rendering pipeline dependencies. void D3D1211on12::LoadPipeline() { UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; D2D1_FACTORY_OPTIONS d2dFactoryOptions = {}; #if defined(_DEBUG) // Enable the D2D debug layer. d2dFactoryOptions.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; // Enable the D3D11 debug layer. d3d11DeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_d3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForHwnd( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr, &swapChain )); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create an 11 device wrapped around the 12 device and share // 12's command queue. ComPtr<ID3D11Device> d3d11Device; ThrowIfFailed(D3D11On12CreateDevice( m_d3d12Device.Get(), d3d11DeviceFlags, nullptr, 0, reinterpret_cast<IUnknown**>(m_commandQueue.GetAddressOf()), 1, 0, &d3d11Device, &m_d3d11DeviceContext, nullptr )); // Query the 11On12 device from the 11 device. ThrowIfFailed(d3d11Device.As(&m_d3d11On12Device)); // Create D2D/DWrite components. { D2D1_DEVICE_CONTEXT_OPTIONS deviceOptions = D2D1_DEVICE_CONTEXT_OPTIONS_NONE; ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory3), &d2dFactoryOptions, &m_d2dFactory)); ComPtr<IDXGIDevice> dxgiDevice; ThrowIfFailed(m_d3d11On12Device.As(&dxgiDevice)); ThrowIfFailed(m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)); ThrowIfFailed(m_d2dDevice->CreateDeviceContext(deviceOptions, &m_d2dDeviceContext)); ThrowIfFailed(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &m_dWriteFactory)); } // Query the desktop's dpi settings, which will be used to create // D2D's render targets. float dpiX; float dpiY; m_d2dFactory->GetDesktopDpi(&dpiX, &dpiY); D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1( D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), dpiX, dpiY ); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_d3d12Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); m_rtvDescriptorSize = m_d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV, D2D render target, and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_d3d12Device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); WCHAR name[25]; if (swprintf_s(name, L"m_renderTargets[%u]", n) > 0) { SetName(m_renderTargets[n].Get(), name); } // Create a wrapped 11On12 resource of this back buffer. Since we are // rendering all D3D12 content first and then all D2D content, we specify // the In resource state as RENDER_TARGET - because D3D12 will have last // used it in this state - and the Out resource state as PRESENT. When // ReleaseWrappedResources() is called on the 11On12 device, the resource // will be transitioned to the PRESENT state. D3D11_RESOURCE_FLAGS d3d11Flags = { D3D11_BIND_RENDER_TARGET }; ThrowIfFailed(m_d3d11On12Device->CreateWrappedResource( m_renderTargets[n].Get(), &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&m_wrappedBackBuffers[n]) )); // Create a render target for D2D to draw directly to this back buffer. ComPtr<IDXGISurface> surface; ThrowIfFailed(m_wrappedBackBuffers[n].As(&surface)); ThrowIfFailed(m_d2dDeviceContext->CreateBitmapFromDxgiSurface( surface.Get(), &bitmapProperties, &m_d2dRenderTargets[n] )); rtvHandle.Offset(1, m_rtvDescriptorSize); ThrowIfFailed(m_d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } }
// Load the rendering pipeline dependencies. void D3D12Bundles::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForCoreWindow( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. reinterpret_cast<IUnknown*>(Windows::UI::Core::CoreWindow::GetForCurrentThread()), &swapChainDesc, nullptr, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a shader resource view (SRV) and constant // buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvSrvHeapDesc = {}; cbvSrvHeapDesc.NumDescriptors = FrameCount * CityRowCount * CityColumnCount // FrameCount frames * CityRowCount * CityColumnCount. + 1; // + 1 for the SRV. cbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvHeapDesc, IID_PPV_ARGS(&m_cbvSrvHeap))); NAME_D3D12_OBJECT(m_cbvSrvHeap); // Describe and create a sampler descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {}; samplerHeapDesc.NumDescriptors = 1; samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&m_samplerHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator))); }
void DeviceManDX12::Create(HWND hWnd) { Destroy(); #ifndef NDEBUG ComPtr<ID3D12Debug> debug; if (S_OK == D3D12GetDebugInterface(IID_PPV_ARGS(&debug))) { debug->EnableDebugLayer(); } #endif if (S_OK != CreateDXGIFactory1(IID_PPV_ARGS(&factory))) { Destroy(); return; } ComPtr<IDXGIAdapter1> adapter; for (int i = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(i, &adapter); i++) { if (S_OK == D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device))) { break; } } if (!device) { Destroy(); return; } 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 (S_OK != device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue))) { Destroy(); return; } RECT rc; GetClientRect(hWnd, &rc); DXGI_SWAP_CHAIN_DESC sd = {}; sd.BufferCount = numFrameBuffers; sd.BufferDesc.Width = rc.right - rc.left; sd.BufferDesc.Height = rc.bottom - rc.top; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.Windowed = TRUE; ComPtr<IDXGISwapChain> sc; if (S_OK != factory->CreateSwapChain(deviceMan.GetCommandQueue().Get(), &sd, &sc)) { Destroy(); return; } if (S_OK != sc.As(&swapChain)) { Destroy(); return; } D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = numFrameBuffers; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)); for (int i = 0; i < numFrameBuffers; i++) { if (S_OK != deviceMan.GetSwapChain()->GetBuffer(i, IID_PPV_ARGS(&renderTargets[i]))) { Destroy(); return; } D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap->GetCPUDescriptorHandleForHeapStart(); rtvHandle.ptr += i * device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); device->CreateRenderTargetView(renderTargets[i].Get(), nullptr, rtvHandle); } factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator)); device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator.Get(), nullptr, IID_PPV_ARGS(&commandList)); commandList->Close(); if (S_OK != device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))) { Destroy(); return; } fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); assert (fenceEvent); BeginScene(); }
void XApp::init() { //// Basic initialization if (initialized) return; initialized = true; if (!ovrRendering) ovrMirror = false; if (ovrRendering) vr.init(); if (appName.length() == 0) { // no app name specified - just use first one from iterator auto it = appMap.begin(); XAppBase *a = it->second; if (a != nullptr) { appName = it->first; Log("WARNING: xapp not specified, using this app: " << appName.c_str() << endl); } } //assert(appName.length() > 0); app = getApp(appName); if (app != nullptr) { //Log("initializing " << appName.c_str() << "\n"); SetWindowText(getHWND(), string2wstring(app->getWindowTitle())); } else { Log("ERROR: xapp not available " << appName.c_str() << endl); // throw assertion error in debug mode assert(app != nullptr); } #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } HRESULT getAnalysis = DXGIGetDebugInterface1(0, __uuidof(pGraphicsAnalysis), reinterpret_cast<void**>(&pGraphicsAnalysis)); } #endif //// Viewport and Scissor /* D3D12_RECT rect; if (GetWindowRect(getHWND(), &rect)) { int width = rect.right - rect.left; int height = rect.bottom - rect.top; viewport.MinDepth = 0.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; viewport.Width = static_cast<float>(width); viewport.Height = static_cast<float>(height); viewport.MaxDepth = 1.0f; scissorRect.left = 0; scissorRect.top = 0; scissorRect.right = static_cast<LONG>(width); scissorRect.bottom = static_cast<LONG>(height); vr.adaptViews(viewport, scissorRect); } */ //// Pipeline ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory2(0 #ifdef _DEBUG | DXGI_CREATE_FACTORY_DEBUG #endif , IID_PPV_ARGS(&factory))); if (warp) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device) )); } // disable auto alt-enter fullscreen switch (does leave an unresponsive window during debug sessions) ThrowIfFailed(factory->MakeWindowAssociation(getHWND(), DXGI_MWA_NO_ALT_ENTER)); //IDXGIFactory4 *parentFactoryPtr = nullptr; //if (SUCCEEDED(swapChain->GetParent(__uuidof(IDXGIFactory4), (void **)&parentFactoryPtr))) { // parentFactoryPtr->MakeWindowAssociation(getHWND(), DXGI_MWA_NO_ALT_ENTER); // parentFactoryPtr->Release(); //} // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue))); commandQueue->SetName(L"commandQueue_xapp"); calcBackbufferSizeAndAspectRatio(); camera.aspectRatio = aspectRatio; if (ovrRendering) { camera.aspectRatio /= 2.0f; } camera.projectionTransform(); // Describe the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = backbufferWidth; swapChainDesc.BufferDesc.Height = backbufferHeight; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = getHWND(); swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain0; // we cannot use create IDXGISwapChain3 directly - create IDXGISwapChain, then call As() to map to IDXGISwapChain3 ThrowIfFailed(factory->CreateSwapChain( commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain0 )); ThrowIfFailed(swapChain0.As(&swapChain)); //swapChain = nullptr; frameIndex = xapp().swapChain->GetCurrentBackBufferIndex(); if (ovrRendering) { vr.initD3D(); } // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap))); rtvHeap->SetName(L"rtvHeap_xapp"); rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(swapChain->GetBuffer(n, IID_PPV_ARGS(&renderTargets[n]))); device->CreateRenderTargetView(renderTargets[n].Get(), nullptr, rtvHandle); wstringstream s; s << L"renderTarget_xapp[" << n << "]"; renderTargets[n]->SetName(s.str().c_str()); rtvHandle.Offset(1, rtvDescriptorSize); //ThrowIfFailed(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocators[n]))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsvHeaps[n]))); } // Create the depth stencil view for each frame for (UINT n = 0; n < FrameCount; n++) { D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {}; depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE; D3D12_CLEAR_VALUE depthOptimizedClearValue = {}; depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT; depthOptimizedClearValue.DepthStencil.Depth = 1.0f; depthOptimizedClearValue.DepthStencil.Stencil = 0; ThrowIfFailed(device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, backbufferWidth, backbufferHeight, 1, 0, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&depthStencils[n]) )); //NAME_D3D12_OBJECT(m_depthStencil); device->CreateDepthStencilView(depthStencils[n].Get(), &depthStencilDesc, dsvHeaps[n]->GetCPUDescriptorHandleForHeapStart()); wstringstream s; s << L"depthStencil_xapp[" << n << "]"; depthStencils[n]->SetName(s.str().c_str()); } } //// Assets // Create an empty root signature. { CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ThrowIfFailed(device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature))); } // 11 on 12 device support UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if defined(_DEBUG) if (disableDX11Debug == false) { d3d11DeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; } #endif ThrowIfFailed(D3D11On12CreateDevice( device.Get(), d3d11DeviceFlags, nullptr, 0, reinterpret_cast<IUnknown**>(commandQueue.GetAddressOf()), 1, 0, &d3d11Device, &d3d11DeviceContext, nullptr )); // Query the 11On12 device from the 11 device. ThrowIfFailed(d3d11Device.As(&d3d11On12Device)); // feature levels: we need DX 10.1 as minimum D3D_FEATURE_LEVEL out_level; array<D3D_FEATURE_LEVEL, 3> levels{ { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 } }; //ID3D11DeviceContext* context = nullptr; UINT flags = disableDX11Debug ? 0 : D3D11_CREATE_DEVICE_DEBUG; ThrowIfFailed(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags, &levels[0], (UINT)levels.size(), D3D11_SDK_VERSION, &reald3d11Device, &out_level, &reald3d11DeviceContext)); // 11 on 12 end camera.ovrCamera = true; if (!ovrRendering) camera.ovrCamera = false; gametime.init(1); // init to real time camera.setSpeed(1.0f); initPakFiles(); app->init(); app->update(); }
HRESULT KGraphicsDevice::Init(int32 window_width, int32 window_height) { HRESULT hr; m_WindowWidth = window_width; m_WindowHeight = window_height; //Setup SDL window HWND handle; if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { shared_context.log->LogText(LogLevel::FATAL_ERROR, "SDL_Init failed: %s", SDL_GetError()); } IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF); m_MainWindow = SDL_CreateWindow("Conservative Clustered Shading DirectX12", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_WindowWidth, m_WindowHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); SDL_SysWMinfo info; //Must init info struct with SDL version info, see documentation for explanation SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(m_MainWindow, &info)) handle = info.info.win.window; else shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to get WMInfo: %s", SDL_GetError()); uint32 flags = 0; #ifdef _DEBUG { ID3D12Debug* debugController; D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)); debugController->EnableDebugLayer(); if (debugController) debugController->Release(); } #endif DXGI_SWAP_CHAIN_DESC descSwapChain; ZeroMemory(&descSwapChain, sizeof(descSwapChain)); descSwapChain.BufferCount = 2; descSwapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; descSwapChain.BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT; descSwapChain.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; descSwapChain.OutputWindow = handle; descSwapChain.SampleDesc.Count = 1; descSwapChain.Windowed = true; hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_Device)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to create D3D12 Device"); D3D12_FEATURE_DATA_D3D12_OPTIONS opts; hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &opts, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to CheckFeatureSupport"); //Print hardware opts PrintHWopts(opts); uint32 node_count = m_Device->GetNodeCount(); shared_context.log->LogText(LogLevel::DEBUG_PRINT, "Device node count: %d", node_count); IDXGIFactory* dxgifactory; hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgifactory)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to create IDXGIFactory"); D3D12_COMMAND_QUEUE_DESC queueDesc; ZeroMemory(&queueDesc, sizeof(queueDesc)); queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; hr = m_Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_CommandQueue)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to create Command Queue"); hr = dxgifactory->CreateSwapChain(m_CommandQueue, &descSwapChain, &m_SwapChain); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to create SwapChain"); dxgifactory->Release(); //Set up descriptor heaps m_DescHeapCBV_SRV.CreateDescriptorHeap(50, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); m_DescHeapDSV.CreateDescriptorHeap(2, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); m_DescHeapRTV.CreateDescriptorHeap(20, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE); m_DescHeapSampler.CreateDescriptorHeap(1, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); m_Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_CommandAllocator)); m_Device->SetStablePowerState(TRUE); hr = m_CommandQueue->GetTimestampFrequency(&m_Freq); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed GetTimestampFrequency"); m_ViewPort = { 0.0f, 0.0f, (float)m_WindowWidth, (float)m_WindowHeight, 0.0f, 1.0f }; m_ScissorRect = { 0, 0, m_WindowWidth, m_WindowHeight }; m_RTDescriptor[0] = m_DescHeapRTV.GetNewCPUHandle(); m_RTDescriptor[1] = m_DescHeapRTV.GetNewCPUHandle(); //Get back buffer and create RTVs m_SwapChain->GetBuffer(0, IID_PPV_ARGS(&m_RenderTarget[0])); m_Device->CreateRenderTargetView(m_RenderTarget[0], nullptr, m_RTDescriptor[0]); m_RenderTarget[0]->SetName(L"RENDER TARGET"); m_SwapChain->GetBuffer(1, IID_PPV_ARGS(&m_RenderTarget[1])); m_Device->CreateRenderTargetView(m_RenderTarget[1], nullptr, m_RTDescriptor[1]); //Create time stamp query heap const uint32 num_time_queries = 24; D3D12_QUERY_HEAP_DESC desc; desc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; desc.Count = num_time_queries; desc.NodeMask = 0; hr = m_Device->CreateQueryHeap(&desc, IID_PPV_ARGS(&m_TimeStampQueryHeap)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to CreateQueryHeap"); m_Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK, 0, 0), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(num_time_queries * sizeof(uint64)), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&m_TimeStampQueryReadBackRes)); if (FAILED(hr)) shared_context.log->LogText(LogLevel::FATAL_ERROR, "Failed to CreateCommittedResource for query readback buffer"); //Create fence m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_Fence)); m_CurrentFence = 1; m_HandleEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); return hr; }
void GraphicsDevice::Init(u32 screenWidth, u32 screenHeight) { #define GRAPHICSINIT_ON_FAILED(failCondition, errorMessage, ...) \ do { \ if(failCondition) \ { \ Assertf(false, errorMessage, __VA_ARGS__); \ return; \ } \ } while(0) HRESULT hr; #if RECON_DEBUG ID3D12Debug* debugInterface; hr = D3D12GetDebugInterface(__uuidof(ID3D12Debug), (void**)&debugInterface); if(Verifyf(SUCCEEDED(hr), "Failed To Create Graphics Debug Interface! Error Code: '%d'", hr)) { debugInterface->EnableDebugLayer(); } #endif // RECON_DEBUG hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&m_pDevice); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create D3D12 Device! Error Code: '%d'", hr); D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; hr = m_pDevice->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&m_pCommandQueue); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create D3D12 Command Queue! Error Code: '%d'", hr); // NOTE: rasterTek does a bunch of extra stuff here before creating the swap chain // to potentially help performance? But the Directx 12 Samples don't do this. // may want to investigate in the future IDXGIFactory4* pFactory = nullptr; hr = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&pFactory); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create DXGI Factory! Error Code: '%d'", hr); HWND hWnd = ((AppWindow_Windows*)AppEntryPoint::GetWindow())->GetWindowHandle(); DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = ms_FrameCount; swapChainDesc.BufferDesc.Width = screenWidth; swapChainDesc.BufferDesc.Height = screenHeight; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = hWnd; swapChainDesc.Windowed = TRUE; // Multisampling swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; // Flags swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; IDXGISwapChain* pSwapChain = nullptr; hr = pFactory->CreateSwapChain(m_pCommandQueue, &swapChainDesc, &pSwapChain); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Swap Chain! Error Code: '%d'", hr); hr = pSwapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&m_pSwapChain); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Swap Chain 3! Error Code: '%d'", hr); // We're done with the factory pFactory->Release(); pFactory = nullptr; m_FrameIndex = m_pSwapChain->GetCurrentBackBufferIndex(); D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = ms_FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; hr = m_pDevice->CreateDescriptorHeap(&rtvHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&m_pRTVHeap); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create RTV Descriptor Heap! Error Code: '%d'", hr); D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_pRTVHeap->GetCPUDescriptorHandleForHeapStart(); u32 rtvHeapIncSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); for(int i = 0; i < ms_FrameCount; ++i) { hr = m_pSwapChain->GetBuffer(i, __uuidof(ID3D12Resource), (void**)&m_pRenderTargets[i]); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Get RTV (%d) From Swap Chain! Error Code: '%d'", i, hr); m_pDevice->CreateRenderTargetView(m_pRenderTargets[i], nullptr, rtvHandle); rtvHandle.ptr += rtvHeapIncSize; hr = m_pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&m_pCommandAllocators[i]); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create GPU Command Allocator! Error Code: '%d'", i, hr); } // Will want to move this to another class once multithreaded rendering is supported hr = m_pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_pCommandAllocators[0], nullptr, __uuidof(ID3D12GraphicsCommandList), (void**)&m_pGraphicsCommandList); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create GPU Command Allocator! Error Code: '%d'", hr); hr = m_pGraphicsCommandList->Close(); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Close Graphics Command List! Error Code: '%d'", hr); hr = m_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&m_pRenderFence); GRAPHICSINIT_ON_FAILED(FAILED(hr), "Failed To Create Render Fence! Error Code: '%d'", hr); m_pRenderFenceEvent = CreateEvent(nullptr, false, false, nullptr); GRAPHICSINIT_ON_FAILED(m_pRenderFenceEvent == nullptr, "Failed To Create Render Fence Event! Error Code: '%d'", GetLastError()); #undef GRAPHICSINIT_ON_FAILED }
// Load the rendering pipeline dependencies. HRESULT VolumetricAnimation::LoadPipeline() { HRESULT hr; // [TODO]: Move to project independent framework #ifdef _DEBUG // Enable the D3D12 debug layer. ComPtr<ID3D12Debug> debugController; if ( SUCCEEDED( D3D12GetDebugInterface( IID_PPV_ARGS( &debugController ) ) ) ) { debugController->EnableDebugLayer(); }else PRINTWARN(L"Unable to enable D3D12 debug validation layer.") #endif ComPtr<IDXGIFactory4> factory; VRET( CreateDXGIFactory1( IID_PPV_ARGS( &factory ) ) ); if ( m_useWarpDevice ) { ComPtr<IDXGIAdapter> warpAdapter; VRET( factory->EnumWarpAdapter( IID_PPV_ARGS( &warpAdapter ) ) ); VRET( D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS( &m_device ) ) ); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter( factory.Get(), &hardwareAdapter ); VRET( D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS( &m_device ) ) ); } // [TODO]: Move to project independent framework // Check Direct3D 12 feature hardware support (more usage refer Direct3D 12 sdk Capability Querying) D3D12_FEATURE_DATA_D3D12_OPTIONS options; m_device->CheckFeatureSupport( D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof( options ) ); switch ( options.ResourceBindingTier ) { case D3D12_RESOURCE_BINDING_TIER_1: PRINTWARN( L"Tier 1 is supported." ); break; case D3D12_RESOURCE_BINDING_TIER_2: PRINTWARN( L"Tier 1 and 2 are supported." ); break; case D3D12_RESOURCE_BINDING_TIER_3: PRINTWARN( L"Tier 1, 2 and 3 are supported." ); break; default: break; } // Describe and create the graphics command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; VRET( m_device->CreateCommandQueue( &queueDesc, IID_PPV_ARGS( &m_graphicCmdQueue ) ) ); DXDebugName( m_graphicCmdQueue ); // Describe and create the compute command queue; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE; VRET( m_device->CreateCommandQueue( &queueDesc, IID_PPV_ARGS( &m_computeCmdQueue ) ) ); DXDebugName( m_computeCmdQueue ); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; // Swap chain needs the queue so that it can force a flush on it. VRET( factory->CreateSwapChain( m_graphicCmdQueue.Get(), &swapChainDesc, &swapChain ) ); VRET( swapChain.As( &m_swapChain ) ); DXDebugName( m_swapChain ); // This sample does not support fullscreen transitions. VRET( factory->MakeWindowAssociation( m_hwnd, DXGI_MWA_NO_ALT_ENTER ) ); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; VRET( m_device->CreateDescriptorHeap( &rtvHeapDesc, IID_PPV_ARGS( &m_rtvHeap ) ) ); DXDebugName( m_rtvHeap ); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ); // Describe and create a shader resource view (SRV) and constant buffer view (CBV) descriptor heap. // Flags indicate that this descriptor heap can be bound to the pipeline // and that descriptors contained in it can be reference by a root table D3D12_DESCRIPTOR_HEAP_DESC cbvsrvuavHeapDesc = {}; cbvsrvuavHeapDesc.NumDescriptors = 3; // One for SRV two for CBV (gfx and compute) cbvsrvuavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; cbvsrvuavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; VRET( m_device->CreateDescriptorHeap( &cbvsrvuavHeapDesc, IID_PPV_ARGS( &m_cbvsrvuavHeap ) ) ); DXDebugName( m_cbvsrvuavHeap ); m_cbvsrvuavDescriptorSize = m_device->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; VRET( m_device->CreateDescriptorHeap( &dsvHeapDesc, IID_PPV_ARGS( &m_dsvHeap ) ) ); DXDebugName( m_dsvHeap ); } VRET( m_device->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS( &m_graphicCmdAllocator ) ) ); DXDebugName( m_graphicCmdAllocator ); VRET( m_device->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_PPV_ARGS( &m_computeCmdAllocator ) ) ); DXDebugName( m_computeCmdAllocator ); return S_OK; }
void dx::initialise() { gDX.viewport.Width = static_cast<float>(platform::ui::width()); gDX.viewport.Height = static_cast<float>(platform::ui::height()); gDX.viewport.MaxDepth = 1.0f; gDX.scissorRect.right = static_cast<LONG>(platform::ui::width()); gDX.scissorRect.bottom = static_cast<LONG>(platform::ui::height()); #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); // Always use WARP for now... static const bool USE_WARP_DEVICE = true; if (USE_WARP_DEVICE) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gDX.device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&gDX.device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(gDX.device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&gDX.commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = gDX.FrameCount; swapChainDesc.BufferDesc.Width = platform::ui::width(); swapChainDesc.BufferDesc.Height = platform::ui::height(); swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = (HWND)platform::ui::hwnd(); swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( gDX.commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&gDX.swapChain)); gDX.frameIndex = gDX.swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = gDX.FrameCount + 128; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; gDX.rtvHeap = new DXHeap(gDX.device.Get(), rtvHeapDesc); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 128; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; gDX.dsvHeap = new DXHeap(gDX.device.Get(), dsvHeapDesc); // Describe and create a constant buffer view (CBV), Shader resource // view (SRV), and unordered access view (UAV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 2048; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; gDX.srvHeap = new DXHeap(gDX.device.Get(), srvHeapDesc); } // Create frame resources. { // Create a RTV for each frame. for (UINT n = 0; n < gDX.FrameCount; n++) { ThrowIfFailed(gDX.swapChain->GetBuffer(n, IID_PPV_ARGS(&gDX.renderTargets[n]))); gDX.scanbufferRtv[n] = gDX.rtvHeap->alloc(); gDX.device->CreateRenderTargetView(gDX.renderTargets[n].Get(), nullptr, *gDX.scanbufferRtv[n]); } } // Create command allocators. { for (UINT n = 0; n < gDX.FrameCount; n++) { ThrowIfFailed(gDX.device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&gDX.commandAllocator[n]))); } } // Create the root signature. { CD3DX12_DESCRIPTOR_RANGE ranges[1]; ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); CD3DX12_ROOT_PARAMETER rootParameters[1]; rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL); D3D12_STATIC_SAMPLER_DESC sampler = {}; sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER; sampler.MipLODBias = 0; sampler.MaxAnisotropy = 0; sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; sampler.MinLOD = 0.0f; sampler.MaxLOD = D3D12_FLOAT32_MAX; sampler.ShaderRegister = 0; sampler.RegisterSpace = 0; sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 1, &sampler, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ComPtr<ID3DBlob> signature; ComPtr<ID3DBlob> error; ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); ThrowIfFailed(gDX.device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&gDX.rootSignature))); } // Create the pipeline state, which includes compiling and loading shaders. { ComPtr<ID3DBlob> vertexShader; ComPtr<ID3DBlob> pixelShader; #ifdef _DEBUG // Enable better shader debugging with the graphics debugging tools. UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #else UINT compileFlags = 0; #endif ThrowIfFailed(D3DCompileFromFile(L"resources/shaders/screendraw.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr)); ThrowIfFailed(D3DCompileFromFile(L"resources/shaders/screendraw.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr)); // Define the vertex input layout. D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; psoDesc.pRootSignature = gDX.rootSignature.Get(); psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() }; psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() }; psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = FALSE; psoDesc.DepthStencilState.StencilEnable = FALSE; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.SampleDesc.Count = 1; ThrowIfFailed(gDX.device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&gDX.emuPipelineState))); } } gDX.pipelineMgr = new DXPipelineMgr(); // Create the command list. gDX.frameIndex = gDX.swapChain->GetCurrentBackBufferIndex(); ThrowIfFailed(gDX.device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, gDX.commandAllocator[gDX.frameIndex].Get(), gDX.emuPipelineState.Get(), IID_PPV_ARGS(&gDX.commandList))); { #define SCREENSPACE(x, y) { -1 + ((x) / (float)platform::ui::width()) * 2, 1 - ((y) / (float)platform::ui::height()) * 2, 0.0f } float tvX = 0; float tvY = 0; float tvWidth = (float)platform::ui::tvWidth(); float tvHeight = (float)platform::ui::tvHeight(); float drcX = ((float)platform::ui::tvWidth() - (float)platform::ui::drcWidth()) / 2; float drcY = (float)platform::ui::tvHeight(); float drcWidth = (float)platform::ui::drcWidth(); float drcHeight = (float)platform::ui::drcHeight(); struct Vertex { XMFLOAT3 pos; XMFLOAT2 uv; } triangleVertices[] = { { SCREENSPACE(tvX, tvY + tvHeight),{ 0.0f, 1.0f } }, { SCREENSPACE(tvX, tvY),{ 0.0f, 0.0f } }, { SCREENSPACE(tvX + tvWidth, tvY + tvHeight),{ 1.0f, 1.0f } }, { SCREENSPACE(tvX + tvWidth, tvY),{ 1.0f, 0.0f } }, { SCREENSPACE(drcX, drcY + drcHeight),{ 0.0f, 1.0f } }, { SCREENSPACE(drcX, drcY),{ 0.0f, 0.0f } }, { SCREENSPACE(drcX + drcWidth, drcY + drcHeight),{ 1.0f, 1.0f } }, { SCREENSPACE(drcX + drcWidth, drcY),{ 1.0f, 0.0f } }, }; #undef SCREENSPACE const UINT vertexBufferSize = sizeof(triangleVertices); // Note: using upload heaps to transfer static data like vert buffers is not // recommended. Every time the GPU needs it, the upload heap will be marshalled // over. Please read up on Default Heap usage. An upload heap is used here for // code simplicity and because there are very few verts to actually transfer. ThrowIfFailed(gDX.device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&gDX.vertexBuffer))); // Copy the triangle data to the vertex buffer. UINT8* pVertexDataBegin; ThrowIfFailed(gDX.vertexBuffer->Map(0, nullptr, reinterpret_cast<void**>(&pVertexDataBegin))); memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices)); gDX.vertexBuffer->Unmap(0, nullptr); // Initialize the vertex buffer view. gDX.vertexBufferView.BufferLocation = gDX.vertexBuffer->GetGPUVirtualAddress(); gDX.vertexBufferView.StrideInBytes = sizeof(Vertex); gDX.vertexBufferView.SizeInBytes = vertexBufferSize; } // 10MB Temporary Vertex Buffer gDX.ppcVertexBuffer = new DXDynBuffer(gDX.device.Get(), 10 * 1024 * 1024); // Close the command list and execute it to begin the initial GPU setup. ThrowIfFailed(gDX.commandList->Close()); ID3D12CommandList* ppCommandLists[] = { gDX.commandList.Get() }; gDX.commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects. { ThrowIfFailed(gDX.device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&gDX.fence))); // Create an event handle to use for frame synchronization. gDX.fenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); if (gDX.fenceEvent == nullptr) { ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); } // Wait for frame completion gDX.swapCount++; const uint64_t fenceValue = gDX.swapCount; ThrowIfFailed(gDX.commandQueue->Signal(gDX.fence.Get(), fenceValue)); if (gDX.fence->GetCompletedValue() < gDX.swapCount) { ThrowIfFailed(gDX.fence->SetEventOnCompletion(gDX.swapCount, gDX.fenceEvent)); WaitForSingleObject(gDX.fenceEvent, INFINITE); } } _beginFrame(); }
// Load the rendering pipeline dependencies. void D3D12Fullscreen::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. // The resolution of the swap chain buffers will match the resolution of the window, enabling the // app to enter iFlip when in fullscreen mode. We will also keep a separate buffer that is not part // of the swap chain as an intermediate render target, whose resolution will control the rendering // resolution of the scene. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; // It is recommended to always use the tearing flag when it is available. swapChainDesc.Flags = m_tearingSupport ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForCoreWindow( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. reinterpret_cast<IUnknown*>(Windows::UI::Core::CoreWindow::GetForCurrentThread()), &swapChainDesc, nullptr, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount + 1; // + 1 for the intermediate render target. rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a constant buffer view (CBV) and shader resource view (SRV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvSrvHeapDesc = {}; cbvSrvHeapDesc.NumDescriptors = FrameCount + 1; // One CBV per frame and one SRV for the intermediate render target. cbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvHeapDesc, IID_PPV_ARGS(&m_cbvSrvHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create command allocators for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_sceneCommandAllocators[n]))); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_postCommandAllocators[n]))); } }
//------------------------------------------------------------------------------------------------- // D3D12の初期化処理です. //------------------------------------------------------------------------------------------------- bool App::InitD3D() { HRESULT hr = S_OK; // ウィンドウ幅を取得. RECT rc; GetClientRect( m_hWnd, &rc ); u32 w = rc.right - rc.left; u32 h = rc.bottom - rc.top; UINT flags = 0; #if defined(DEBUG) || defined(_DEBUG) ID3D12Debug* pDebug; D3D12GetDebugInterface(IID_ID3D12Debug, (void**)&pDebug); if (pDebug) { pDebug->EnableDebugLayer(); pDebug->Release(); } flags |= DXGI_CREATE_FACTORY_DEBUG; #endif hr = CreateDXGIFactory2(flags, IID_IDXGIFactory4, (void**)m_Factory.GetAddress()); if (FAILED(hr)) { ELOG("Error : CreateDXGIFactory() Failed."); return false; } hr = m_Factory->EnumAdapters(0, m_Adapter.GetAddress()); if (FAILED(hr)) { ELOG("Error : IDXGIFactory::EnumAdapters() Failed."); return false; } // デバイス生成. hr = D3D12CreateDevice( m_Adapter.GetPtr(), D3D_FEATURE_LEVEL_11_0, IID_ID3D12Device, (void**)m_Device.GetAddress() ); // 生成チェック. if ( FAILED( hr ) ) { // Warpアダプターで再トライ. m_Adapter.Reset(); m_Device.Reset(); hr = m_Factory->EnumWarpAdapter(IID_PPV_ARGS(m_Adapter.GetAddress())); if (FAILED(hr)) { ELOG("Error : IDXGIFactory::EnumWarpAdapter() Failed."); return false; } // デバイス生成. hr = D3D12CreateDevice( m_Adapter.GetPtr(), D3D_FEATURE_LEVEL_11_0, IID_ID3D12Device, (void**)m_Device.GetAddress()); if (FAILED(hr)) { ELOG("Error: D3D12CreateDevice() Failed."); return false; } } // コマンドアロケータを生成. hr = m_Device->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_ID3D12CommandAllocator, (void**)m_CmdAllocator.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : ID3D12Device::CreateCommandAllocator() Failed." ); return false; } // コマンドキューを生成. { D3D12_COMMAND_QUEUE_DESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; desc.Priority = 0; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; hr = m_Device->CreateCommandQueue( &desc, IID_ID3D12CommandQueue, (void**)m_CmdQueue.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : ID3D12Device::CreateCommandQueue() Failed." ); return false; } } // スワップチェインを生成. { DXGI_SWAP_CHAIN_DESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.BufferCount = m_BufferCount; desc.BufferDesc.Format = m_SwapChainFormat; desc.BufferDesc.Width = w; desc.BufferDesc.Height = h; desc.BufferDesc.RefreshRate.Numerator = 60; desc.BufferDesc.RefreshRate.Denominator = 1; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; desc.OutputWindow = m_hWnd; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Windowed = TRUE; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // アダプター単位の処理にマッチするのは m_Device ではなく m_CmdQueue なので,m_CmdQueue を第一引数として渡す. hr = m_Factory->CreateSwapChain( m_CmdQueue.GetPtr(), &desc, m_SwapChain.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : IDXGIFactory::CreateSwapChain() Failed." ); return false; } } // デスクリプタヒープの生成. { D3D12_DESCRIPTOR_HEAP_DESC desc; ZeroMemory( &desc, sizeof(desc) ); desc.NumDescriptors = 1; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; hr = m_Device->CreateDescriptorHeap( &desc, IID_ID3D12DescriptorHeap, (void**)m_DescriptorHeap.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : ID3D12Device::CreateDescriptorHeap() Failed." ); return false; } } // コマンドリストの生成. { hr = m_Device->CreateCommandList( 1, D3D12_COMMAND_LIST_TYPE_DIRECT, m_CmdAllocator.GetPtr(), nullptr, IID_ID3D12GraphicsCommandList, (void**)m_CmdList.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : ID3D12Device::CreateCommandList() Failed." ); return false; } } // バックバッファからレンダーターゲットを生成. { hr = m_SwapChain->GetBuffer( 0, IID_ID3D12Resource, (void**)m_ColorTarget.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : IDXGISwapChain::GetBuffer() Failed." ); return false; } m_ColorTargetHandle = m_DescriptorHeap->GetCPUDescriptorHandleForHeapStart(); m_Device->CreateRenderTargetView( m_ColorTarget.GetPtr(), nullptr, m_ColorTargetHandle ); } // フェンスの生成. { m_EventHandle = CreateEvent( 0, FALSE, FALSE, 0 ); hr = m_Device->CreateFence( 0, D3D12_FENCE_FLAG_NONE, IID_ID3D12Fence, (void**)m_Fence.GetAddress() ); if ( FAILED( hr ) ) { ELOG( "Error : ID3D12Device::CreateFence() Failed." ); return false; } } // ビューポートの設定. { m_Viewport.TopLeftX = 0; m_Viewport.TopLeftY = 0; m_Viewport.Width = FLOAT(w); m_Viewport.Height = FLOAT(h); m_Viewport.MinDepth = 0.0f; m_Viewport.MaxDepth = 1.0f; } // 正常終了. return true; }
DX12Device::DX12Device(bool debug) { // Debug layer if (debug) { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } ComPtr<IDXGIFactory4> factory; if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { WindowManager::Message("DX12 Initialization Error", "Failed to create the factory"); } // no warp device if (FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device)))) { WindowManager::Message("DX12 Initialization Error", "Failed to create the device"); } // the command queue should have it's own class // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; if (FAILED(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)))) { WindowManager::Message("DX12 Initialization Error", "Failed to create the command queue"); } // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = WindowManager::GetWidth(); swapChainDesc.BufferDesc.Height = WindowManager::GetHeight(); swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = WindowManager::GetHandle(); swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; if (FAILED(factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain ))) { WindowManager::Message("DX12 Initialization Error", "Failed to create the swap chain"); } swapChain.As(&m_swapChain); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV for each frame. for (UINT n = 0; n < FrameCount; n++) { m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); } } m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator)); // Create the command list. if (FAILED(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), nullptr, IID_PPV_ARGS(&m_commandList)))) { WindowManager::Message("DX12 Initialization Error", "Failed to create the command lsit"); } // Command lists are created in the recording state, but there is nothing // to record yet. The main loop expects it to be closed, so close it now. if(FAILED(m_commandList->Close())) { WindowManager::Message("DX12 Initialization Error", "Failed to close the command lsit"); } // Create synchronization objects. { if (FAILED(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)))) { WindowManager::Message("DX12 Initialization Error", "Failed to create fence"); } m_fenceValue = 1; // Create an event handle to use for frame synchronization. m_fenceEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); if (m_fenceEvent == nullptr) { if (FAILED(HRESULT_FROM_WIN32(GetLastError()))) { WindowManager::Message("DX12 Initialization Error", "GENERIC ERROR"); } } } /* // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. (m_commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. (m_commandList->Reset(m_commandAllocator.Get(), m_pipelineState.Get())); // Indicate that the back buffer will be used as a render target. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize); // Record commands. const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f }; m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); // Indicate that the back buffer will now be used to present. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); (m_commandList->Close());*/ }
// Load the rendering pipeline dependencies. void DX12ClothSimulation::LoadPipeline() { #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if ( SUCCEEDED( D3D12GetDebugInterface( IID_PPV_ARGS( &debugController ) ) ) ) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed( CreateDXGIFactory1( IID_PPV_ARGS( &factory ) ) ); if ( m_useWarpDevice ) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed( factory->EnumWarpAdapter( IID_PPV_ARGS( &warpAdapter ) ) ); ThrowIfFailed( D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS( &m_device ) ) ); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter( factory.Get(), &hardwareAdapter ); ThrowIfFailed( D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS( &m_device ) ) ); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed( m_device->CreateCommandQueue( &queueDesc, IID_PPV_ARGS( &m_commandQueue ) ) ); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed( factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain ) ); ThrowIfFailed( swapChain.As( &m_swapChain ) ); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed( m_device->CreateDescriptorHeap( &rtvHeapDesc, IID_PPV_ARGS( &m_rtvHeap ) ) ); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE_RTV ); } // Create a command allocator for each frame. for ( UINT n = 0; n < FrameCount; n++ ) { ThrowIfFailed( m_device->CreateCommandAllocator( D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS( &m_commandAllocators[n] ) ) ); } }
void D3D12Render::init_d3d() { #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))); debugController->EnableDebugLayer(); } #endif ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&m_pFactory))); // Try to create hardware device. HRESULT hardwareResult = D3D12CreateDevice( nullptr, // default adapter D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pD3D12Device)); // Fallback to WARP device. if(FAILED(hardwareResult)) { ComPtr<IDXGIAdapter> pWarpAdapter; ThrowIfFailed(m_pFactory->EnumWarpAdapter(IID_PPV_ARGS(&pWarpAdapter))); ThrowIfFailed(D3D12CreateDevice( pWarpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pD3D12Device))); } ThrowIfFailed(m_pD3D12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_pFence))); m_RtvDescriptorSize = m_pD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_DsvDescriptorSize = m_pD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); m_CbvSrvUavDescriptorSize = m_pD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); // Check 4X MSAA quality support for our back buffer format. // All Direct3D 11 capable devices support 4X MSAA for all render // target formats, so we only need to check quality support. D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels; msQualityLevels.Format = m_BackBufferFormat; msQualityLevels.SampleCount = 4; msQualityLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE; msQualityLevels.NumQualityLevels = 0; ThrowIfFailed(m_pD3D12Device->CheckFeatureSupport( D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msQualityLevels, sizeof(msQualityLevels))); m_4xMsaaQuality = msQualityLevels.NumQualityLevels; assert(m_4xMsaaQuality > 0 && "Unexpected MSAA quality level."); #ifdef _DEBUG LogAdapters(); #endif init_cmd(); init_swapchain(); init_descHeaps(); }
void QD3D12WindowPrivate::initialize() { Q_Q(QD3D12Window); if (initialized) return; swapChainBufferCount = 2; HWND hwnd = reinterpret_cast<HWND>(q->winId()); ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) debugController->EnableDebugLayer(); ComPtr<IDXGIFactory4> factory; if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) { qWarning("Failed to create DXGI"); return; } ComPtr<IDXGIAdapter1> adapter; getHardwareAdapter(factory.Get(), &adapter); bool warp = true; if (adapter) { HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)); if (SUCCEEDED(hr)) warp = false; else qWarning("Failed to create device: 0x%x", hr); } else { qWarning("No usable hardware adapters found"); } if (warp) { qDebug("Using WARP"); ComPtr<IDXGIAdapter> warpAdapter; factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)); HRESULT hr = D3D12CreateDevice(warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)); if (FAILED(hr)) { qWarning("Failed to create WARP device: 0x%x", hr); return; } } D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; if (FAILED(device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue)))) { qWarning("Failed to create command queue"); return; } DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = swapChainBufferCount; swapChainDesc.BufferDesc.Width = q->width() * q->devicePixelRatio(); swapChainDesc.BufferDesc.Height = q->height() * q->devicePixelRatio(); swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // D3D12 requires the flip model swapChainDesc.OutputWindow = hwnd; swapChainDesc.SampleDesc.Count = 1; // Flip does not support MSAA so no choice here swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> baseSwapChain; HRESULT hr = factory->CreateSwapChain(commandQueue.Get(), &swapChainDesc, &baseSwapChain); if (FAILED(hr)) { qWarning("Failed to create swap chain: 0x%x", hr); return; } if (FAILED(baseSwapChain.As(&swapChain))) { qWarning("Failed to cast swap chain"); return; } factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator)))) { qWarning("Failed to create command allocator"); return; } if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&bundleAllocator)))) { qWarning("Failed to create command bundle allocator"); return; } D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = swapChainBufferCount + extraRenderTargetCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; if (FAILED(device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)))) { qWarning("Failed to create render target view descriptor heap"); return; } rtvStride = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1 + extraRenderTargetCount; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; if (FAILED(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsvHeap)))) { qWarning("Failed to create depth stencil heap"); return; } dsvStride = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); setupRenderTargets(); initialized = true; q->initializeD3D(); }
// Load the rendering pipeline dependencies. void D3D12PredicationQueries::LoadPipeline() { #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a constant buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {}; cbvHeapDesc.NumDescriptors = CbvCountPerFrame * FrameCount; cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&m_cbvHeap))); // Describe and create a heap for occlusion queries. D3D12_QUERY_HEAP_DESC queryHeapDesc = {}; queryHeapDesc.Count = 1; queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION; ThrowIfFailed(m_device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } }
// Load the rendering pipeline dependencies. void D3D12nBodyGravity::LoadPipeline() { #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); m_swapChainEvent = m_swapChain->GetFrameLatencyWaitableObject(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a shader resource view (SRV) and unordered // access view (UAV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC srvUavHeapDesc = {}; srvUavHeapDesc.NumDescriptors = DescriptorCount; srvUavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvUavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&srvUavHeapDesc, IID_PPV_ARGS(&m_srvUavHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_srvUavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } }
void RenderSysem::LoadPipeline() { #ifdef _DEBUG //Enable the D3D12 debug layer ComPtr<ID3D12Debug> pDebugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pDebugController)))) { pDebugController->EnableDebugLayer(); } #endif ComPtr<IDXGIFactory4> pFactory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&pFactory))); bool UseWarpDevice = false; if (UseWarpDevice) { ComPtr<IDXGIAdapter> pWarpAdapter; ThrowIfFailed(pFactory->EnumWarpAdapter(IID_PPV_ARGS(&pWarpAdapter))); ThrowIfFailed(D3D12CreateDevice(pWarpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pD3D12Device))); } else { ThrowIfFailed(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_pD3D12Device))); } /////////////////////// //Describe and Create the command queue////////////////////////////////////////////// D3D12_COMMAND_QUEUE_DESC queueDesc ={}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_pD3D12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_pCommandQueue))); //Describe and Create the swap chain DXGI_SWAP_CHAIN_DESC swapChainDesc ={}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_ScreenWidth; swapChainDesc.BufferDesc.Height = m_ScreenHeight; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = GetHwnd(); swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> pSwapChain; ThrowIfFailed(pFactory->CreateSwapChain( m_pCommandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &pSwapChain ) ); ThrowIfFailed(pSwapChain.As(&m_pSwapChain)); m_FrameIndex = m_pSwapChain->GetCurrentBackBufferIndex(); ///////////////////////// Create Decriptor heaps ///////////////////////////////////////////// { D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc ={}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_pD3D12Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_pRTVHeap))); m_RTVDescriptorSize = m_pD3D12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } //Create frame resources { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_pRTVHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_pSwapChain->GetBuffer(n, IID_PPV_ARGS(&m_pRenderTargets[n]))); m_pD3D12Device->CreateRenderTargetView(m_pRenderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_RTVDescriptorSize); } } ThrowIfFailed(m_pD3D12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_pCommandAllocator))); ThrowIfFailed(m_pD3D12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(&m_pBundleAllocator))); }
void DirectX12Render::InitializeDX() { //Initialize the debug layer of DX12 #ifdef _DEBUG ComPtr<ID3D12Debug> Debug; ThrowFail(D3D12GetDebugInterface(IID_PPV_ARGS(&Debug)), TEXT("Failed to get debug interface")); Debug->EnableDebugLayer(); #endif //Make a factory so we can get our device along with an adapter to store ComPtr<IDXGIFactory4> Factory; ThrowFail(CreateDXGIFactory1(IID_PPV_ARGS(&Factory)), TEXT("Failed to create factory")); ComPtr<IDXGIAdapter1> Adapter; ComPtr<IDXGIAdapter1> TempAdapter; //Get our device for (UINT i = 0; DXGI_ERROR_NOT_FOUND != Factory->EnumAdapters1(i, &TempAdapter); ++i) { DXGI_ADAPTER_DESC1 Desc; TempAdapter->GetDesc1(&Desc); if (Desc.Flags == DXGI_ERROR_NOT_FOUND) continue; //Fake Create it to make sure it will actually work if (S_OK == D3D12CreateDevice(TempAdapter.Get(), D3D_FEATURE_LEVEL_12_1, _uuidof(ID3D12Device), NULL)) break; } Adapter = TempAdapter.Detach(); //Create the device for reals ThrowFail(D3D12CreateDevice(Adapter.Get(), D3D_FEATURE_LEVEL_12_1, _uuidof(ID3D12Device), &Device), TEXT("Failed to create DirectX 12 Device")); //Create Command Queue D3D12_COMMAND_QUEUE_DESC QueueDesc = {}; QueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; QueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowFail(Device->CreateCommandQueue(&QueueDesc, IID_PPV_ARGS(&CommandQueue)), TEXT("Failed to create Command Queue")); //Create the swap chain DXGI_SWAP_CHAIN_DESC SwapDesc = {}; SwapDesc.BufferCount = FrameCount; SwapDesc.BufferDesc.Width = CWindow::GetWidth(); SwapDesc.BufferDesc.Height = CWindow::GetHeight(); SwapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; SwapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; SwapDesc.OutputWindow = CWindow::GethWnd(); SwapDesc.SampleDesc.Count = 1; SwapDesc.Windowed = true; //Create a temporary swap chain because CreateSwapChain doesnt support SwapChain3 ComPtr<IDXGISwapChain> FakeSwap; ThrowFail(Factory->CreateSwapChain( CommandQueue.Get(), &SwapDesc, &FakeSwap), TEXT("Fake Swap Chain Failed to create")); //.As() makes its TARGET itself not the otherway around. Causes evil shit if you do it the other way ThrowFail(FakeSwap.As(&SwapChain), TEXT("Real Swap Chain failed to switch")); FenceIndex = SwapChain->GetCurrentBackBufferIndex(); D3D12_DESCRIPTOR_HEAP_DESC RTVDesc = {}; RTVDesc.NumDescriptors = FrameCount; RTVDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; RTVDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowFail(Device->CreateDescriptorHeap(&RTVDesc, IID_PPV_ARGS(&RTVHeap)), TEXT("Descriptor Heap failed to create")); HeapSize = Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); CD3DX12_CPU_DESCRIPTOR_HANDLE RTVHandle( RTVHeap->GetCPUDescriptorHandleForHeapStart()); for (UINT i = 0; i < FrameCount; i++) { ThrowFail(SwapChain->GetBuffer(i, IID_PPV_ARGS(&RenderTargets[i])), TEXT("Failed to Get Buffer")); Device->CreateRenderTargetView(RenderTargets[i].Get(), nullptr, RTVHandle); RTVHandle.Offset(1, HeapSize); } ThrowFail(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&CommandAllocator)), TEXT("Command Allocator Failed to Initialize")); }
// Load the rendering pipeline dependencies. void D3D12SmallResources::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&m_adapter))); ThrowIfFailed(D3D12CreateDevice( m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(hardwareAdapter.As(&m_adapter)); ThrowIfFailed(D3D12CreateDevice( m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the copy queue. queueDesc.Type = D3D12_COMMAND_LIST_TYPE_COPY; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_copyQueue))); NAME_D3D12_OBJECT(m_copyQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForHwnd( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr, &swapChain )); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a constant buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {}; cbvHeapDesc.NumDescriptors = TextureCount; cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&m_srvHeap))); NAME_D3D12_OBJECT(m_srvHeap); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_srvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); NAME_D3D12_OBJECT_INDEXED(m_renderTargets, n); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } } // Create copy queue resources. ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&m_copyCommandAllocator))); }
// Load the rendering pipeline dependencies. void D3D12Multithreading::LoadPipeline() { #ifdef _DEBUG // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ThrowIfFailed(D3D12CreateDevice( nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.BufferDesc.Width = m_width; swapChainDesc.BufferDesc.Height = m_height; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.OutputWindow = m_hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Windowed = TRUE; ComPtr<IDXGISwapChain> swapChain; ThrowIfFailed(factory->CreateSwapChain( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. &swapChainDesc, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. // Each frame has its own depth stencils (to write shadows onto) // and then there is one for the scene itself. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1 + FrameCount * 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a shader resource view (SRV) and constant // buffer view (CBV) descriptor heap. Heap layout: null views, // object diffuse + normal textures views, frame 1's shadow buffer, // frame 1's 2x constant buffer, frame 2's shadow buffer, frame 2's // 2x constant buffers, etc... const UINT nullSrvCount = 2; // Null descriptors are needed for out of bounds behavior reads. const UINT cbvCount = FrameCount * 2; const UINT srvCount = _countof(SampleAssets::Textures) + (FrameCount * 1); D3D12_DESCRIPTOR_HEAP_DESC cbvSrvHeapDesc = {}; cbvSrvHeapDesc.NumDescriptors = nullSrvCount + cbvCount + srvCount; cbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvHeapDesc, IID_PPV_ARGS(&m_cbvSrvHeap))); // Describe and create a sampler descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {}; samplerHeapDesc.NumDescriptors = 2; // One clamp and one wrap sampler. samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&m_samplerHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator))); }
// Load the rendering pipeline dependencies. void D3D12PipelineStateCache::LoadPipeline() { #if defined(_DEBUG) // Enable the D3D12 debug layer. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForHwnd( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr, &swapChain )); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); m_swapChainEvent = m_swapChain->GetFrameLatencyWaitableObject(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount + 1; // A descriptor for each frame + 1 intermediate render target. rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a shader resource view (SRV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 1; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvHeap))); NAME_D3D12_OBJECT(m_srvHeap); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_srvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create RTVs and a command allocator for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); WCHAR name[25]; if (swprintf_s(name, L"m_renderTargets[%u]", n) > 0) { SetName(m_renderTargets[n].Get(), name); } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n]))); } D3D12_RESOURCE_DESC renderTargetDesc = m_renderTargets[0]->GetDesc(); D3D12_CLEAR_VALUE clearValue = {}; memcpy(clearValue.Color, IntermediateClearColor, sizeof(IntermediateClearColor)); clearValue.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // Create an intermediate render target that is the same dimensions as the swap chain. ThrowIfFailed(m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &renderTargetDesc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearValue, IID_PPV_ARGS(&m_intermediateRenderTarget))); NAME_D3D12_OBJECT(m_intermediateRenderTarget); m_device->CreateRenderTargetView(m_intermediateRenderTarget.Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); // Create a SRV of the intermediate render target. D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Format = renderTargetDesc.Format; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = 1; CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(m_srvHeap->GetCPUDescriptorHandleForHeapStart()); m_device->CreateShaderResourceView(m_intermediateRenderTarget.Get(), &srvDesc, srvHandle); } }
//-------------------------------------------------------------------------- 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."); }
// Load the rendering pipeline dependencies. void D3D12DynamicIndexing::LoadPipeline() { UINT dxgiFactoryFlags = 0; #if defined(_DEBUG) // Enable the debug layer (requires the Graphics Tools "optional feature"). // NOTE: Enabling the debug layer after device creation will invalidate the active device. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); // Enable additional debug layers. dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); NAME_D3D12_OBJECT(m_commandQueue); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForHwnd( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. Win32Application::GetHwnd(), &swapChainDesc, nullptr, nullptr, &swapChain )); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); // Describe and create a depth stencil view (DSV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.NumDescriptors = 1; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); // Describe and create a shader resource view (SRV) and constant // buffer view (CBV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC cbvSrvHeapDesc = {}; cbvSrvHeapDesc.NumDescriptors = FrameCount * CityRowCount * CityColumnCount + // FrameCount frames * CityRowCount * CityColumnCount. CityMaterialCount + 1; // CityMaterialCount + 1 for the SRVs. cbvSrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; cbvSrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvHeapDesc, IID_PPV_ARGS(&m_cbvSrvHeap))); NAME_D3D12_OBJECT(m_cbvSrvHeap); // Describe and create a sampler descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {}; samplerHeapDesc.NumDescriptors = 1; samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&m_samplerHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); m_cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator))); }
bool D3DClass::Initialize(int screenHeight, int screenWidth, HWND hwnd, bool vsync, bool fullscreen) { D3D_FEATURE_LEVEL featureLevel; HRESULT result; D3D12_COMMAND_QUEUE_DESC commandQueueDesc; IDXGIFactory4* factory; IDXGIAdapter* adapter; IDXGIOutput* adapterOutput; unsigned int numModes, i, numerator, denominator, renderTargetViewDescriptorSize; unsigned long long stringLength; DXGI_MODE_DESC* displayModeList; DXGI_ADAPTER_DESC adapterDesc; DXGI_SWAP_CHAIN_DESC swapChainDesc; IDXGISwapChain* swapChain; D3D12_DESCRIPTOR_HEAP_DESC renderTargetViewHeapDesc; D3D12_CPU_DESCRIPTOR_HANDLE renderTargetViewHandle; // Store the vsync setting. m_vsync_enabled = vsync; // Set the feature level to DirectX 12.1 to enable using all the DirectX 12 features. // Note: Not all cards support full DirectX 12, this feature level may need to be reduced on some cards to 12.0. featureLevel = D3D_FEATURE_LEVEL_11_0; // Create the Direct3D 12 device. result = D3D12CreateDevice(NULL, featureLevel, __uuidof(ID3D12Device), (void**)&m_device); if (FAILED(result)) { MessageBox(hwnd, L"Could not create a DirectX 12.1 device. The default video card does not support DirectX 12.1.", L"DirectX Device Failure", MB_OK); return false; } // Initialize the description of the command queue. ZeroMemory(&commandQueueDesc, sizeof(commandQueueDesc)); // Set up the description of the command queue. commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; commandQueueDesc.NodeMask = 0; // Create the command queue. m_device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&m_commandQueue); // Create a DirectX graphics interface factory. CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&factory); // Use the factory to create an adapter for the primary graphics interface (video card). factory->EnumAdapters(0, &adapter); // Enumerate the primary adapter output (monitor). adapter->EnumOutputs(0, &adapterOutput); // Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor). adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL); // Create a list to hold all the possible display modes for this monitor/video card combination. displayModeList = new DXGI_MODE_DESC[numModes]; // Now fill the display mode list structures. adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList); // Now go through all the display modes and find the one that matches the screen height and width. // When a match is found store the numerator and denominator of the refresh rate for that monitor. for (i = 0; i<numModes; i++) { if (displayModeList[i].Height == (unsigned int)screenHeight) { if (displayModeList[i].Width == (unsigned int)screenWidth) { numerator = displayModeList[i].RefreshRate.Numerator; denominator = displayModeList[i].RefreshRate.Denominator; } } } // Get the adapter (video card) description. adapter->GetDesc(&adapterDesc); // Store the dedicated video card memory in megabytes. m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024); // Convert the name of the video card to a character array and store it. wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128); // Release the display mode list. delete[] displayModeList; displayModeList = nullptr; // Release the adapter output. adapterOutput->Release(); adapterOutput = nullptr; // Release the adapter. adapter->Release(); adapter = nullptr; // Initialize the swap chain description. ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); // Set the swap chain to use double buffering. swapChainDesc.BufferCount = 2; // Set the height and width of the back buffers in the swap chain. swapChainDesc.BufferDesc.Height = screenHeight; swapChainDesc.BufferDesc.Width = screenWidth; // Set a regular 32-bit surface for the back buffers. swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // Set the usage of the back buffers to be render target outputs. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // Set the swap effect to discard the previous buffer contents after swapping. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // Set the handle for the window to render to. swapChainDesc.OutputWindow = hwnd; // Set to full screen or windowed mode. swapChainDesc.Windowed = !fullscreen; // Set the refresh rate of the back buffer. if (m_vsync_enabled) { swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator; swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator; } else { swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } // Turn multisampling off. swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; // Set the scan line ordering and scaling to unspecified. swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // Don't set the advanced flags. swapChainDesc.Flags = 0; // Finally create the swap chain using the swap chain description. factory->CreateSwapChain(m_commandQueue, &swapChainDesc, &swapChain); // Next upgrade the IDXGISwapChain to a IDXGISwapChain3 interface and store it in a private member variable named m_swapChain. // This will allow us to use the newer functionality such as getting the current back buffer index. swapChain->QueryInterface(__uuidof(IDXGISwapChain3), (void**)&m_swapChain); // Clear pointer to original swap chain interface since we are using version 3 instead (m_swapChain). swapChain = nullptr; // Release the factory now that the swap chain has been created. factory->Release(); factory = nullptr; // Initialize the render target view heap description for the two back buffers. ZeroMemory(&renderTargetViewHeapDesc, sizeof(renderTargetViewHeapDesc)); // Set the number of descriptors to two for our two back buffers. Also set the heap tyupe to render target views. renderTargetViewHeapDesc.NumDescriptors = 2; renderTargetViewHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; renderTargetViewHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; // Create the render target view heap for the back buffers. m_device->CreateDescriptorHeap(&renderTargetViewHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&m_renderTargetViewHeap); // Get a handle to the starting memory location in the render target view heap to identify where the render target views will be located for the two back buffers. renderTargetViewHandle = m_renderTargetViewHeap->GetCPUDescriptorHandleForHeapStart(); // Get the size of the memory location for the render target view descriptors. renderTargetViewDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); // Get a pointer to the first back buffer from the swap chain. m_swapChain->GetBuffer(0, __uuidof(ID3D12Resource), (void**)&m_backBufferRenderTarget[0]); // Create a render target view for the first back buffer. m_device->CreateRenderTargetView(m_backBufferRenderTarget[0], NULL, renderTargetViewHandle); // Increment the view handle to the next descriptor location in the render target view heap. renderTargetViewHandle.ptr += renderTargetViewDescriptorSize; // Get a pointer to the second back buffer from the swap chain. m_swapChain->GetBuffer(1, __uuidof(ID3D12Resource), (void**)&m_backBufferRenderTarget[1]); // Create a render target view for the second back buffer. m_device->CreateRenderTargetView(m_backBufferRenderTarget[1], NULL, renderTargetViewHandle); // Finally get the initial index to which buffer is the current back buffer. m_bufferIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create a command allocator. m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&m_commandAllocator); // Create a fence for GPU synchronization. m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&m_fence); // Create an event object for the fence. m_fenceEvent = CreateEvent(nullptr, false, false, nullptr); // Initialize the starting fence value. m_fenceValue = 1; CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); ID3DBlob* signature; ID3DBlob* error; D3D12SerializeRootSignature( &rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); m_device->CreateRootSignature( 0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)); //Create pipeline state, load and compiler shaders. //Note here to change D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION for debug UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; D3DReadFileToBlob(L"DefaultVS.cso", &m_vertexShader); D3DReadFileToBlob(L"DefaultHS.cso", &m_hullShader); D3DReadFileToBlob(L"DefaultDS.cso", &m_domainShader); D3DReadFileToBlob(L"DefaultPS.cso", &m_pixelShader); std::array<D3D12_INPUT_ELEMENT_DESC, 2> inputElementDescs = { D3D12_INPUT_ELEMENT_DESC{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, D3D12_INPUT_ELEMENT_DESC{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; D3D12_GRAPHICS_PIPELINE_STATE_DESC pipelineDesc = {}; pipelineDesc.InputLayout = { inputElementDescs.data() , (UINT)inputElementDescs.size() }; pipelineDesc.pRootSignature = m_rootSignature; pipelineDesc.VS = { m_vertexShader->GetBufferPointer(), m_vertexShader->GetBufferSize() }; pipelineDesc.PS = { m_pixelShader->GetBufferPointer(), m_pixelShader->GetBufferSize() }; pipelineDesc.HS = { m_hullShader->GetBufferPointer(), m_hullShader->GetBufferSize() }; pipelineDesc.DS = { m_domainShader->GetBufferPointer(), m_domainShader->GetBufferSize() }; pipelineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT_WIREFRAME); pipelineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); pipelineDesc.DepthStencilState.DepthEnable = false; pipelineDesc.DepthStencilState.StencilEnable = false; pipelineDesc.SampleMask = UINT_MAX; pipelineDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; pipelineDesc.NumRenderTargets = 1; pipelineDesc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM; pipelineDesc.SampleDesc.Count = 1; m_device->CreateGraphicsPipelineState(&pipelineDesc, IID_PPV_ARGS(&m_pipelineState)); // Create a basic command list. m_device->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, m_pipelineState, IID_PPV_ARGS(&m_commandList)); // Initially we need to close the command list during initialization as it is created in a recording state. m_commandList->Close(); Vertex triangleVertices[] = { { { 0.0f, 0.5f, 0.f }, { 1.f, 0.f, 0.f, 1.f } }, { { 0.5f, -0.5f, 0.f },{ 0.f, 1.f, 0.f, 1.f } }, { { -0.5f, -0.5f, 0.f },{ 0.f, 0.f, 1.f, 1.f } }, }; const UINT vertexBufferSize = sizeof(triangleVertices); m_device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&m_vertexBuffer)); UINT8* pVertexDataBegin; CD3DX12_RANGE readRange(0, 0); m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)); memcpy(pVertexDataBegin, triangleVertices, vertexBufferSize); m_vertexBuffer->Unmap(0, nullptr); m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress(); m_vertexBufferView.StrideInBytes = sizeof(Vertex); m_vertexBufferView.SizeInBytes = vertexBufferSize; m_viewport.Height = screenHeight; m_viewport.Width = screenWidth; m_viewport.MaxDepth = 1000.f; m_viewport.MinDepth = 0.1f; m_viewport.TopLeftX = 0.f; m_viewport.TopLeftY = 0.f; m_scissorRect.left = 0; m_scissorRect.right = screenWidth; m_scissorRect.top = 0; m_scissorRect.bottom = screenHeight; unsigned long long fenceToWaitFor = m_fenceValue; m_commandQueue->Signal(m_fence, fenceToWaitFor); m_fenceValue++; // Wait until the GPU is done rendering. if (m_fence->GetCompletedValue() < fenceToWaitFor) { m_fence->SetEventOnCompletion(fenceToWaitFor, m_fenceEvent); WaitForSingleObject(m_fenceEvent, INFINITE); } return true; }
// Load the rendering pipeline dependencies. void D3D12HelloWindow::LoadPipeline() { UINT dxgiFactoryFlags = 0; #if defined(_DEBUG) // Enable the debug layer (requires the Graphics Tools "optional feature"). // NOTE: Enabling the debug layer after device creation will invalidate the active device. { ComPtr<ID3D12Debug> debugController; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { debugController->EnableDebugLayer(); // Enable additional debug layers. dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; } } #endif ComPtr<IDXGIFactory4> factory; ThrowIfFailed(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory))); if (m_useWarpDevice) { ComPtr<IDXGIAdapter> warpAdapter; ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter))); ThrowIfFailed(D3D12CreateDevice( warpAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } else { ComPtr<IDXGIAdapter1> hardwareAdapter; GetHardwareAdapter(factory.Get(), &hardwareAdapter); ThrowIfFailed(D3D12CreateDevice( hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device) )); } // Describe and create the command queue. D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue))); // Describe and create the swap chain. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; swapChainDesc.BufferCount = FrameCount; swapChainDesc.Width = m_width; swapChainDesc.Height = m_height; swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.SampleDesc.Count = 1; ComPtr<IDXGISwapChain1> swapChain; ThrowIfFailed(factory->CreateSwapChainForCoreWindow( m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it. reinterpret_cast<IUnknown*>(Windows::UI::Core::CoreWindow::GetForCurrentThread()), &swapChainDesc, nullptr, &swapChain )); ThrowIfFailed(swapChain.As(&m_swapChain)); m_frameIndex = m_swapChain->GetCurrentBackBufferIndex(); // Create descriptor heaps. { // Describe and create a render target view (RTV) descriptor heap. D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; rtvHeapDesc.NumDescriptors = FrameCount; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); } // Create frame resources. { CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart()); // Create a RTV for each frame. for (UINT n = 0; n < FrameCount; n++) { ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n]))); m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle); rtvHandle.Offset(1, m_rtvDescriptorSize); } } ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator))); }
void DeviceManDX12::Create(HWND hWnd) { Destroy(); #ifndef NDEBUG ComPtr<ID3D12Debug> debug; if (S_OK == D3D12GetDebugInterface(IID_PPV_ARGS(&debug))) { debug->EnableDebugLayer(); } #endif ComPtr<IDXGIFactory4> factory; if (S_OK != CreateDXGIFactory1(IID_PPV_ARGS(&factory))) { Destroy(); return; } ComPtr<IDXGIAdapter1> adapter; for (int i = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(i, &adapter); i++) { if (S_OK == D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device))) { break; } } if (!device) { Destroy(); return; } 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 (S_OK != device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue))) { Destroy(); return; } RECT rc; GetClientRect(hWnd, &rc); DXGI_SWAP_CHAIN_DESC sd = {}; sd.BufferCount = numFrameBuffers; sd.BufferDesc.Width = rc.right - rc.left; sd.BufferDesc.Height = rc.bottom - rc.top; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.Windowed = TRUE; ComPtr<IDXGISwapChain> sc; if (S_OK != factory->CreateSwapChain(commandQueue.Get(), &sd, &sc)) { Destroy(); return; } if (S_OK != sc.As(&swapChain)) { Destroy(); return; } const D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = { D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1 }; device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvHeap)); for (int i = 0; i < numFrameBuffers; i++) { FrameResources& res = frameResources[i]; if (S_OK != swapChain->GetBuffer(i, IID_PPV_ARGS(&res.renderTarget))) { Destroy(); return; } device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&res.commandAllocator)); const D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, maxSrvs, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }; device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&res.srvHeap)); res.constantBuffer = afCreateUBO(maxConstantBufferBlocks * 0x100); D3D12_RANGE readRange = {}; HRESULT hr = res.constantBuffer->Map(0, &readRange, (void**)&res.mappedConstantBuffer); assert(hr == S_OK); assert(res.mappedConstantBuffer); } IVec2 size = { (int)sd.BufferDesc.Width, (int)sd.BufferDesc.Height }; depthStencil = afCreateTexture2D(AFDT_DEPTH_STENCIL, size, nullptr, true); const D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = { D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1 }; device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsvHeap)); D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap->GetCPUDescriptorHandleForHeapStart(); device->CreateDepthStencilView(depthStencil.Get(), nullptr, dsvHandle); factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, frameResources[0].commandAllocator.Get(), nullptr, IID_PPV_ARGS(&commandList)); commandList->Close(); if (S_OK != device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))) { Destroy(); return; } BeginScene(); }