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
    }
}
Esempio n. 2
0
        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
            };
        }