private D3D12_CPU_DESCRIPTOR_HANDLE OffsetCpu(int count) => Cpu.Offset(count, IncrementSize);
private unsafe void CreateAssets() { ID3D12Device *d3dDevice = _deviceResources.D3DDevice; Guid iid; { iid = D3D12.IID_ID3D12GraphicsCommandList; ID3D12GraphicsCommandList *commandList; ThrowIfFailed(d3dDevice->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT, _deviceResources.CommandAllocator, _pipelineState.Ptr, &iid, (void **)&commandList)); _commandList = commandList; DX.NameD3D12Object(_commandList.Ptr, nameof(_commandList)); } // Cube vertices. Each vertex has a position and a color. const uint vertexPositionColorCount = 8; VertexPositionColor *cubeVertices = stackalloc VertexPositionColor[(int)vertexPositionColorCount] { new VertexPositionColor { pos = new Vector3(-0.5f, -0.5f, -0.5f), color = new Vector3(0.0f, 0.0f, 0.0f) }, new VertexPositionColor { pos = new Vector3(-0.5f, -0.5f, 0.5f), color = new Vector3(0.0f, 0.0f, 1.0f) }, new VertexPositionColor { pos = new Vector3(-0.5f, 0.5f, -0.5f), color = new Vector3(0.0f, 1.0f, 0.0f) }, new VertexPositionColor { pos = new Vector3(-0.5f, 0.5f, 0.5f), color = new Vector3(0.0f, 1.0f, 1.0f) }, new VertexPositionColor { pos = new Vector3(0.5f, -0.5f, -0.5f), color = new Vector3(1.0f, 0.0f, 0.0f) }, new VertexPositionColor { pos = new Vector3(0.5f, -0.5f, 0.5f), color = new Vector3(1.0f, 0.0f, 1.0f) }, new VertexPositionColor { pos = new Vector3(0.5f, 0.5f, -0.5f), color = new Vector3(1.0f, 1.0f, 0.0f) }, new VertexPositionColor { pos = new Vector3(0.5f, 0.5f, 0.5f), color = new Vector3(1.0f, 1.0f, 1.0f) } }; Debug.Assert(sizeof(VertexPositionColor) == Marshal.SizeOf <VertexPositionColor>()); uint vertexBufferSize = (uint)sizeof(VertexPositionColor) * vertexPositionColorCount; using ComPtr <ID3D12Resource> vertexBufferUpload = default; D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC.Buffer(vertexBufferSize); { iid = D3D12.IID_ID3D12Resource; ID3D12Resource *vertexBuffer; ThrowIfFailed(d3dDevice->CreateCommittedResource( &defaultHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &vertexBufferDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, null, &iid, (void **)&vertexBuffer)); _vertexBuffer = vertexBuffer; } iid = D3D12.IID_ID3D12Resource; D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_UPLOAD); ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &vertexBufferDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ, null, &iid, (void **)vertexBufferUpload.GetAddressOf())); DX.NameD3D12Object(_vertexBuffer.Ptr, nameof(_vertexBuffer)); { D3D12_SUBRESOURCE_DATA vertexData; vertexData.pData = (byte *)cubeVertices; vertexData.RowPitch = (IntPtr)vertexBufferSize; vertexData.SlicePitch = vertexData.RowPitch; Functions.UpdateSubresources( _commandList.Ptr, _vertexBuffer.Ptr, vertexBufferUpload.Ptr, 0, 0, 1, &vertexData); D3D12_RESOURCE_BARRIER vertexBufferResourceBarrier = CD3DX12_RESOURCE_BARRIER.Transition(_vertexBuffer.Ptr, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); _commandList.Ptr->ResourceBarrier(1, &vertexBufferResourceBarrier); } const int cubeIndicesCount = 36; ushort * cubeIndices = stackalloc ushort[cubeIndicesCount] { 0, 2, 1, // -x 1, 2, 3, 4, 5, 6, // +x 5, 7, 6, 0, 1, 5, // -y 0, 5, 4, 2, 6, 7, // +y 2, 7, 3, 0, 4, 6, // -z 0, 6, 2, 1, 3, 7, // +z 1, 7, 5, }; const uint indexBufferSize = sizeof(ushort) * cubeIndicesCount; using var indexBufferUpload = new ComPtr <ID3D12Resource>(); D3D12_RESOURCE_DESC indexBufferDesc = CD3DX12_RESOURCE_DESC.Buffer(indexBufferSize); { iid = D3D12.IID_ID3D12Resource; ID3D12Resource *indexBuffer; ThrowIfFailed(d3dDevice->CreateCommittedResource( &defaultHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &indexBufferDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, null, &iid, (void **)&indexBuffer)); _indexBuffer = indexBuffer; } iid = D3D12.IID_ID3D12Resource; ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &indexBufferDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ, null, &iid, (void **)indexBufferUpload.GetAddressOf())); DX.NameD3D12Object(_indexBuffer.Ptr, nameof(_indexBuffer)); { D3D12_SUBRESOURCE_DATA indexData; indexData.pData = (byte *)cubeIndices; indexData.RowPitch = (IntPtr)indexBufferSize; indexData.SlicePitch = indexData.RowPitch; Functions.UpdateSubresources( _commandList.Ptr, _indexBuffer.Ptr, indexBufferUpload.Ptr, 0, 0, 1, &indexData); D3D12_RESOURCE_BARRIER indexBufferResourceBarrier = CD3DX12_RESOURCE_BARRIER.Transition(_indexBuffer.Ptr, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER); _commandList.Ptr->ResourceBarrier(1, &indexBufferResourceBarrier); } { D3D12_DESCRIPTOR_HEAP_DESC heapDesc; heapDesc.NumDescriptors = DeviceResources.FrameCount; heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAGS.D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; { ID3D12DescriptorHeap *cbvHeap; iid = D3D12.IID_ID3D12DescriptorHeap; ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, &iid, (void **)&cbvHeap)); _cbvHeap = cbvHeap; DX.NameD3D12Object(_cbvHeap.Ptr, nameof(_cbvHeap)); } } D3D12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC.Buffer( DeviceResources.FrameCount * AlignedConstantBufferSize); { iid = D3D12.IID_ID3D12Resource; ID3D12Resource *constantBuffer; ThrowIfFailed(d3dDevice->CreateCommittedResource( &uploadHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &constantBufferDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_GENERIC_READ, null, &iid, (void **)&constantBuffer)); _constantBuffer = constantBuffer; DX.NameD3D12Object(_constantBuffer.Ptr, nameof(_constantBuffer)); } D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = _constantBuffer.Ptr->GetGPUVirtualAddress(); D3D12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle = _cbvHeap.Ptr->GetCPUDescriptorHandleForHeapStart(); _cbvDescriptorSize = d3dDevice->GetDescriptorHandleIncrementSize( D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); for (var i = 0; i < DeviceResources.FrameCount; i++) { D3D12_CONSTANT_BUFFER_VIEW_DESC desc; desc.BufferLocation = cbvGpuAddress; desc.SizeInBytes = AlignedConstantBufferSize; d3dDevice->CreateConstantBufferView(&desc, cbvCpuHandle); cbvGpuAddress += desc.SizeInBytes; cbvCpuHandle.Offset((int)_cbvDescriptorSize); } D3D12_RANGE readRange = CD3DX12_RANGE.Create((UIntPtr)0, (UIntPtr)0); fixed(byte **p = &_mappedConstantBuffer) { ThrowIfFailed(_constantBuffer.Ptr->Map(0, &readRange, (void **)p)); Unsafe.InitBlockUnaligned(_mappedConstantBuffer, 0, DeviceResources.FrameCount * AlignedConstantBufferSize); } ThrowIfFailed(_commandList.Ptr->Close()); const int ppCommandListCount = 1; ID3D12CommandList **ppCommandLists = stackalloc ID3D12CommandList *[ppCommandListCount] { (ID3D12CommandList *)_commandList.Ptr }; _deviceResources.CommandQueue->ExecuteCommandLists(ppCommandListCount, ppCommandLists); _vertexBufferView.BufferLocation = _vertexBuffer.Ptr->GetGPUVirtualAddress(); _vertexBufferView.StrideInBytes = (uint)sizeof(VertexPositionColor); _vertexBufferView.SizeInBytes = vertexBufferSize; _indexBufferView.BufferLocation = _indexBuffer.Ptr->GetGPUVirtualAddress(); _indexBufferView.SizeInBytes = indexBufferSize; _indexBufferView.Format = DXGI_FORMAT.DXGI_FORMAT_R16_UINT; _deviceResources.WaitForGpu(); } #endregion } }
public void CreateWindowSizeDependentResources() { WaitForGpu(); for (int n = 0; n < FrameCount; n++) { DirectXHelper.ReleaseCom(_renderTargets[n]); _renderTargets[n] = null; _fenceValues[n] = _fenceValues[_currentFrame]; } UpdateRenderTargetSize(); DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation(); bool swapDimensions = displayRotation == DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE270; _d3dRenderTargetSize.Width = swapDimensions ? _outputSize.Height : _outputSize.Width; _d3dRenderTargetSize.Height = swapDimensions ? _outputSize.Width : _outputSize.Height; uint backBufferWidth = (uint)Math.Round(_d3dRenderTargetSize.Width, MidpointRounding.AwayFromZero); uint backBufferHeight = (uint)Math.Round(_d3dRenderTargetSize.Height, MidpointRounding.AwayFromZero); if (_swapChain != null) { HRESULT hr = _swapChain.Ptr->ResizeBuffers(FrameCount, backBufferWidth, backBufferHeight, _backBufferFormat, 0); if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { _deviceRemoved = true; return; } else { DirectXHelper.ThrowIfFailed(hr); } } else { DXGI_SCALING scaling = DisplayMetrics.SupportHighResolutions ? DXGI_SCALING.DXGI_SCALING_NONE : DXGI_SCALING.DXGI_SCALING_STRETCH; DXGI_SWAP_CHAIN_DESC1 swapChainDesc; swapChainDesc.Width = backBufferWidth; swapChainDesc.Height = backBufferHeight; swapChainDesc.Format = _backBufferFormat; swapChainDesc.Stereo = 0; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI.DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.BufferCount = FrameCount; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_DISCARD; swapChainDesc.Flags = 0; swapChainDesc.Scaling = scaling; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE; { using ComPtr <IDXGISwapChain1> swapChain = null; IntPtr pWindow = Marshal.GetIUnknownForObject(_window); DirectXHelper.ThrowIfFailed( _dxgiFactory.Ptr->CreateSwapChainForCoreWindow( _commandQueue, (IUnknown *)pWindow, &swapChainDesc, null, swapChain.GetAddressOf())); IDXGISwapChain3 *swapChain3; Guid iid = DXGI.IID_IDXGISwapChain3; DirectXHelper.ThrowIfFailed(swapChain.Ptr->QueryInterface(&iid, (void **)&swapChain3)); _swapChain = swapChain3; } } switch (displayRotation) { case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_IDENTITY: _orientationTransform3D = ScreenRotation.Rotation0; break; case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE90: _orientationTransform3D = ScreenRotation.Rotation270; break; case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE180: _orientationTransform3D = ScreenRotation.Rotation180; break; case DXGI_MODE_ROTATION.DXGI_MODE_ROTATION_ROTATE270: _orientationTransform3D = ScreenRotation.Rotation90; break; } DirectXHelper.ThrowIfFailed(_swapChain.Ptr->SetRotation(displayRotation)); { _currentFrame = (int)_swapChain.Ptr->GetCurrentBackBufferIndex(); D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = _rtvHeap.Ptr->GetCPUDescriptorHandleForHeapStart(); fixed(void *pBuffer = & _renderTargets) { var p = (ID3D12Resource **)pBuffer; Guid iid = D3D12.IID_ID3D12Resource; for (var n = 0; n < FrameCount; n++) { DirectXHelper.ThrowIfFailed(_swapChain.Ptr->GetBuffer((uint)n, &iid, (void **)&p[n])); _d3dDevice.Ptr->CreateRenderTargetView( _renderTargets[n], null, rtvDescriptor); rtvDescriptor.Offset((int)_rtvDescriptorSize); DirectXHelper.NameObject(_renderTargets[n], $"{nameof(_renderTargets)}[{n}]"); // _renderTargets[n] } } } { D3D12_HEAP_PROPERTIES depthHeapProperties = CD3DX12_HEAP_PROPERTIES.Create(D3D12_HEAP_TYPE.D3D12_HEAP_TYPE_DEFAULT); D3D12_RESOURCE_DESC depthResourceDesc = CD3DX12_RESOURCE_DESC.Tex2D(_depthBufferFormat, backBufferWidth, backBufferHeight, 1, 1); depthResourceDesc.Flags |= D3D12_RESOURCE_FLAGS.D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; D3D12_CLEAR_VALUE depthOptimizedClearValue = CD3DX12_CLEAR_VALUE.Create(_depthBufferFormat, 1, 0); fixed(ID3D12Resource **p = _depthStencil) { Guid iid = D3D12.IID_ID3D12Resource; DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateCommittedResource( &depthHeapProperties, D3D12_HEAP_FLAGS.D3D12_HEAP_FLAG_NONE, &depthResourceDesc, D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, &iid, (void **)p )); DirectXHelper.NameObject(_depthStencil, nameof(_depthStencil)); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = default; dsvDesc.Format = _depthBufferFormat; dsvDesc.ViewDimension = D3D12_DSV_DIMENSION.D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.Flags = D3D12_DSV_FLAGS.D3D12_DSV_FLAG_NONE; D3D12_CPU_DESCRIPTOR_HANDLE handle = _dsvHeap.Ptr->GetCPUDescriptorHandleForHeapStart(); _d3dDevice.Ptr->CreateDepthStencilView(_depthStencil.Ptr, &dsvDesc, handle); } } // 0.0f, 0.0f, m_d3dRenderTargetSize.Width, m_d3dRenderTargetSize.Height, 0.0f, 1.0f _screenViewport = new D3D12_VIEWPORT { TopLeftX = 0, TopLeftY = 0, Width = (float)_d3dRenderTargetSize.Width, Height = (float)_d3dRenderTargetSize.Height, MinDepth = 0, MaxDepth = 1 }; }