// Load the rendering pipeline dependencies. void D3D1211on12::LoadPipeline() { UINT d3d11DeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; D2D1_FACTORY_OPTIONS d2dFactoryOptions = {}; #ifdef _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 { ThrowIfFailed(D3D12CreateDevice( nullptr, 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))); // Describe 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 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); // 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]))); } } }
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 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))); }
// 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. 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))); 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]))); } }
// Load the rendering pipeline dependencies. void D3D12HelloConstBuffers::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))); // 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 = Win32Application::GetHwnd(); 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)); // This sample does not support fullscreen transitions. ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), 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; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); // Describe and create a 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 referenced by a root table. D3D12_DESCRIPTOR_HEAP_DESC cbvHeapDesc = {}; cbvHeapDesc.NumDescriptors = 1; cbvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; cbvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvHeapDesc, IID_PPV_ARGS(&m_cbvHeap))); } // 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))); }
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 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) )); } #if defined(_DEBUG) // Filter a debug error coming from the 11on12 layer. ComPtr<ID3D12InfoQueue> infoQueue; if (SUCCEEDED(m_d3d12Device->QueryInterface(IID_PPV_ARGS(&infoQueue)))) { // Suppress whole categories of messages. //D3D12_MESSAGE_CATEGORY categories[] = {}; // Suppress messages based on their severity level. D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO, }; // Suppress individual messages by their ID. D3D12_MESSAGE_ID denyIds[] = { // This occurs when there are uninitialized descriptors in a descriptor table, even when a // shader does not access the missing descriptors. D3D12_MESSAGE_ID_INVALID_DESCRIPTOR_HANDLE, }; D3D12_INFO_QUEUE_FILTER filter = {}; //filter.DenyList.NumCategories = _countof(categories); //filter.DenyList.pCategoryList = categories; filter.DenyList.NumSeverities = _countof(severities); filter.DenyList.pSeverityList = severities; filter.DenyList.NumIDs = _countof(denyIds); filter.DenyList.pIDList = denyIds; ThrowIfFailed(infoQueue->PushStorageFilter(&filter)); } #endif // 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->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 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); NAME_D3D12_OBJECT_INDEXED(m_renderTargets, n); // 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 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]))); } } }
// Load the rendering pipeline dependencies. void D3D12HelloTexture::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))); // Describe and create a shader resource view (SRV) heap for the texture. 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))); 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 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 D3D12Bundles::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. + 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 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(); }
// Load the rendering pipeline dependencies. void D3D12PredicationQueries::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 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))); NAME_D3D12_OBJECT(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); NAME_D3D12_OBJECT_INDEXED(m_renderTargets, n); ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[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; }
// 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]))); } }
// Load the rendering pipeline dependencies. void D3D12Multithreading::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->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. // 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))); NAME_D3D12_OBJECT(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))); NAME_D3D12_OBJECT(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))); }
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")); }
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(); }