예제 #1
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(&rtvDescriptor);

                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(&handle);
                    _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
            };
        }
예제 #2
0
        private void CreateDeviceResources()
        {
            Guid iid;

#if DEBUG
            {
                using ComPtr <ID3D12Debug> debugController = null;

                iid = D3D12.IID_ID3D12Debug;
                if (SUCCEEDED(D3D12.D3D12GetDebugInterface(&iid, (void **)debugController.GetAddressOf())))
                {
                    debugController.Ptr->EnableDebugLayer();
                }
            }
#endif
            iid = DXGI.IID_IDXGIFactory4;
            IDXGIFactory4 *dxgiFactory;
            DirectXHelper.ThrowIfFailed(DXGI.CreateDXGIFactory1(&iid, (void **)&dxgiFactory));
            _dxgiFactory = dxgiFactory;

            using ComPtr <IDXGIAdapter1> adapter = null;
            GetHardwareAdapter(adapter.ReleaseGetAddressOf());

            ID3D12Device *d3dDevice;
            iid = D3D12.IID_ID3D12Device;
            HRESULT hr;
            {
                hr = D3D12.D3D12CreateDevice(
                    adapter,
                    D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_0,
                    &iid,
                    (void **)&d3dDevice
                    );

#if DEBUG
                if (FAILED(hr))
                {
                    using ComPtr <IDXGIAdapter> warpAdapter = null;

                    iid = DXGI.IID_IDXGIAdapter;
                    DirectXHelper.ThrowIfFailed(_dxgiFactory.Ptr->EnumWarpAdapter(&iid, (void **)warpAdapter.GetAddressOf()));

                    iid = D3D12.IID_ID3D12Device1;
                    hr  = D3D12.D3D12CreateDevice(
                        warpAdapter,
                        D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_0,
                        &iid,
                        (void **)&d3dDevice
                        );
                }
#endif
            }
            _d3dDevice = d3dDevice;

            DirectXHelper.ThrowIfFailed(hr);

            D3D12_COMMAND_QUEUE_DESC queueDesc;
            queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE;
            queueDesc.Type  = D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT;

            ID3D12CommandQueue *commandQueue;
            {
                iid = D3D12.IID_ID3D12CommandQueue;
                DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateCommandQueue(&queueDesc, &iid, (void **)&commandQueue));
            }
            _commandQueue = commandQueue;
            DirectXHelper.NameObject(_commandQueue, nameof(_commandQueue));

            D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
            rtvHeapDesc.NumDescriptors = FrameCount;
            rtvHeapDesc.Type           = D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
            rtvHeapDesc.Flags          = D3D12_DESCRIPTOR_HEAP_FLAGS.D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

            ID3D12DescriptorHeap *rtvHeap;
            {
                iid = D3D12.IID_ID3D12DescriptorHeap;
                DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateDescriptorHeap(&rtvHeapDesc, &iid, (void **)&rtvHeap));
            }
            _rtvHeap = rtvHeap;
            DirectXHelper.NameObject(_rtvHeap, nameof(_rtvHeap));

            _rtvDescriptorSize =
                _d3dDevice.Ptr->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE
                                                                 .D3D12_DESCRIPTOR_HEAP_TYPE_RTV);



            D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
            dsvHeapDesc.NumDescriptors = 1;
            dsvHeapDesc.Type           = D3D12_DESCRIPTOR_HEAP_TYPE.D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
            dsvHeapDesc.Flags          = D3D12_DESCRIPTOR_HEAP_FLAGS.D3D12_DESCRIPTOR_HEAP_FLAG_NONE;

            ID3D12DescriptorHeap *dsvHeap;
            {
                iid = D3D12.IID_ID3D12DescriptorHeap;
                DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateDescriptorHeap(&dsvHeapDesc, &iid, (void **)&dsvHeap));
            }

            _dsvHeap = dsvHeap;
            DirectXHelper.NameObject(_dsvHeap, nameof(_dsvHeap));

            fixed(CommandAllocators_e__FixedBuffer *pBuffer = &_commandAllocators)
            {
                var p = (ID3D12CommandAllocator **)pBuffer;

                iid = D3D12.IID_ID3D12CommandAllocator;
                for (var n = 0; n < FrameCount; n++)
                {
                    DirectXHelper.ThrowIfFailed(_d3dDevice.Ptr->CreateCommandAllocator(
                                                    D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                                                    &iid,
                                                    (void **)(p + n)));
                }
            }

            ID3D12Fence *fence;
            {
                iid = D3D12.IID_ID3D12Fence;
                DirectXHelper.ThrowIfFailed(
                    _d3dDevice.Ptr->CreateFence(_fenceValues[_currentFrame],
                                                D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE,
                                                &iid,
                                                (void **)&fence));
                _fenceValues[_currentFrame]++;
            }
            _fence = fence;
            DirectXHelper.NameObject(_fence, nameof(_fence));

            _fenceEvent = Kernel32.CreateEvent(null, FALSE, FALSE, null);
            if (_fenceEvent == IntPtr.Zero)
            {
                DirectXHelper.ThrowIfFailed(Marshal.GetLastWin32Error());
            }
        }