public ID3D11Texture2D GetBackbuffer(ID3D11Device device, IntPtr hWnd)
        {
            if (!m_swapChain)
            {
                using (var dxgiDevice = new IDXGIDevice2())
                {
                    device.QueryInterface(ref IDXGIDevice2.IID, out dxgiDevice.PtrForNew).ThrowIfFailed();

                    dxgiDevice.GetAdapter(out IDXGIAdapter dxgiAdapter).ThrowIfFailed();
                    using (dxgiAdapter)
                    {
                        using (var dxgiFactory = new IDXGIFactory2())
                        {
                            dxgiAdapter.GetParent(ref IDXGIFactory2.IID, out dxgiFactory.PtrForNew).ThrowIfFailed();

                            var desc = new DXGI_SWAP_CHAIN_DESC1
                            {
                                Format      = DXGI_FORMAT._B8G8R8A8_UNORM,
                                AlphaMode   = DXGI_ALPHA_MODE._UNSPECIFIED,
                                BufferUsage = DXGI_USAGE._RENDER_TARGET_OUTPUT,
                                Scaling     = DXGI_SCALING._NONE,
                                BufferCount = 2,
                                SwapEffect  = DXGI_SWAP_EFFECT._FLIP_SEQUENTIAL,
                                SampleDesc  = new DXGI_SAMPLE_DESC
                                {
                                    Count   = 1,
                                    Quality = 0,
                                },
                            };

                            var fs_desc = new DXGI_SWAP_CHAIN_FULLSCREEN_DESC
                            {
                                Windowed = 1,
                            };

                            var hr = dxgiFactory.CreateSwapChainForHwnd(device, hWnd, ref desc, ref fs_desc, null, out m_swapChain);
                            hr.ThrowIfFailed();
                        }
                    }
                }
            }

            var texture = new ID3D11Texture2D();

            m_swapChain.GetBuffer(0, ref ID3D11Texture2D.IID, out texture.PtrForNew).ThrowIfFailed();
            return(texture);
        }
Example #2
0
        private IntPtr CreateSwapChain()
        {
            IDXGISwapChain3 *swapChain;

            var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                Width      = (uint)_graphicsSurface.Width,
                Height     = (uint)_graphicsSurface.Height,
                Format     = DXGI_FORMAT_R8G8B8A8_UNORM,
                Stereo     = FALSE,
                SampleDesc = new DXGI_SAMPLE_DESC {
                    Count   = 1,
                    Quality = 0,
                },
                BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                BufferCount = (uint)_graphicsSurface.BufferCount,
                Scaling     = DXGI_SCALING_NONE,
                SwapEffect  = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                AlphaMode   = DXGI_ALPHA_MODE_UNSPECIFIED,
                Flags       = 0
            };

            var graphicsProvider = (GraphicsProvider)_graphicsAdapter.GraphicsProvider;
            var iid = IID_IDXGISwapChain3;

            switch (_graphicsSurface.Kind)
            {
            case GraphicsSurfaceKind.Win32:
            {
                ThrowExternalExceptionIfFailed(nameof(IDXGIFactory2.CreateSwapChainForHwnd), graphicsProvider.Factory->CreateSwapChainForHwnd((IUnknown *)CommandQueue, _graphicsSurface.WindowHandle, &swapChainDesc, pFullscreenDesc: null, pRestrictToOutput: null, (IDXGISwapChain1 **)&swapChain));
                break;
            }

            default:
            {
                ThrowInvalidOperationException(nameof(_graphicsSurface), _graphicsSurface);
                swapChain = null;
                break;
            }
            }

            // Fullscreen transitions are not currently supported
            ThrowExternalExceptionIfFailed(nameof(IDXGIFactory.MakeWindowAssociation), graphicsProvider.Factory->MakeWindowAssociation(_graphicsSurface.WindowHandle, DXGI_MWA_NO_ALT_ENTER));

            return((IntPtr)swapChain);
        }
Example #3
0
        private void Init()
        {
            // this code is ported from https://gist.github.com/d7samurai/261c69490cce0620d0bfc93003cd1052
            var fac   = DXGIFunctions.CreateDXGIFactory2();
            var flags = D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT;

#if DEBUG
            flags |= D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_DEBUG;
#endif

            var d3D11Device = D3D11Functions.D3D11CreateDevice(null, D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE, flags, out _deviceContext);

            var mt = d3D11Device.As <ID3D11Multithread>();
            mt?.SetMultithreadProtected(true);

            var desc = new DXGI_SWAP_CHAIN_DESC1();
            desc.Format           = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
            desc.SampleDesc.Count = 1;
            desc.BufferUsage      = Constants.DXGI_USAGE_RENDER_TARGET_OUTPUT;
            desc.BufferCount      = 2;

            // note: this causes a warning in debug
            // DXGI WARNING: IDXGIFactory::CreateSwapChain: Blt-model swap effects (DXGI_SWAP_EFFECT_DISCARD and DXGI_SWAP_EFFECT_SEQUENTIAL) are legacy swap effects that are predominantly superceded by their flip-model counterparts (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD). Please consider updating your application to leverage flip-model swap effects to benefit from modern presentation enhancements. More information is available at http://aka.ms/dxgiflipmodel. [ MISCELLANEOUS WARNING #294: ]
            _swapChain = fac.CreateSwapChainForHwnd <IDXGISwapChain1>(d3D11Device, Handle, desc);
            var frameBuffer = _swapChain.GetBuffer <ID3D11Texture2D>(0);
            _renderTargetView = d3D11Device.CreateRenderTargetView(frameBuffer);

            frameBuffer.Object.GetDesc(out var depthBufferDesc);
            _width  = depthBufferDesc.Width;
            _height = depthBufferDesc.Height;

            depthBufferDesc.Format    = DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT;
            depthBufferDesc.BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_DEPTH_STENCIL;
            var depthBuffer = d3D11Device.CreateTexture2D <ID3D11Texture2D>(depthBufferDesc);

            _depthBufferView = d3D11Device.CreateDepthStencilView(depthBuffer);

            var vsBlob = D3D11Functions.D3DCompileFromFile("shaders.hlsl", "vs_main", "vs_5_0");
            _vertexShader = d3D11Device.CreateVertexShader(vsBlob);

            var inputElements = new D3D11_INPUT_ELEMENT_DESC[] {
                new D3D11_INPUT_ELEMENT_DESC {
                    SemanticName = "POS", Format = DXGI_FORMAT.DXGI_FORMAT_R32G32B32_FLOAT
                },
                new D3D11_INPUT_ELEMENT_DESC {
                    SemanticName = "NOR", Format = DXGI_FORMAT.DXGI_FORMAT_R32G32B32_FLOAT, AlignedByteOffset = unchecked ((uint)Constants.D3D11_APPEND_ALIGNED_ELEMENT)
                },
                new D3D11_INPUT_ELEMENT_DESC {
                    SemanticName = "TEX", Format = DXGI_FORMAT.DXGI_FORMAT_R32G32_FLOAT, AlignedByteOffset = unchecked ((uint)Constants.D3D11_APPEND_ALIGNED_ELEMENT)
                },
                new D3D11_INPUT_ELEMENT_DESC {
                    SemanticName = "COL", Format = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT, AlignedByteOffset = unchecked ((uint)Constants.D3D11_APPEND_ALIGNED_ELEMENT)
                },
            };
            _inputLayout = d3D11Device.CreateInputLayout(inputElements, vsBlob);

            var psBlob = D3D11Functions.D3DCompileFromFile("shaders.hlsl", "ps_main", "ps_5_0");
            _pixelShader = d3D11Device.CreatePixelShader(psBlob);

            var rasterizerDesc = new D3D11_RASTERIZER_DESC();
            rasterizerDesc.FillMode = D3D11_FILL_MODE.D3D11_FILL_SOLID;
            rasterizerDesc.CullMode = D3D11_CULL_MODE.D3D11_CULL_BACK;
            _rasterizerState        = d3D11Device.CreateRasterizerState(rasterizerDesc);

            var samplerDesc = new D3D11_SAMPLER_DESC();
            samplerDesc.Filter         = D3D11_FILTER.D3D11_FILTER_MIN_MAG_MIP_POINT;
            samplerDesc.AddressU       = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_BORDER;
            samplerDesc.AddressV       = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_BORDER;
            samplerDesc.AddressW       = D3D11_TEXTURE_ADDRESS_MODE.D3D11_TEXTURE_ADDRESS_BORDER;
            samplerDesc.BorderColor    = new float[4];
            samplerDesc.BorderColor[0] = 1;
            samplerDesc.BorderColor[1] = 1;
            samplerDesc.BorderColor[2] = 1;
            samplerDesc.BorderColor[3] = 1;
            samplerDesc.ComparisonFunc = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_NEVER;
            _samplerState = d3D11Device.CreateSamplerState(samplerDesc);

            var depthStencilDesc = new D3D11_DEPTH_STENCIL_DESC();
            depthStencilDesc.DepthEnable    = true;
            depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK.D3D11_DEPTH_WRITE_MASK_ALL;
            depthStencilDesc.DepthFunc      = D3D11_COMPARISON_FUNC.D3D11_COMPARISON_LESS;
            _depthStencilState = d3D11Device.CreateDepthStencilState(depthStencilDesc);

            var blendDesc = new D3D11_BLEND_DESC();
            blendDesc.RenderTarget = new D3D11_RENDER_TARGET_BLEND_DESC[8];
            blendDesc.RenderTarget[0].BlendEnable           = true;
            blendDesc.RenderTarget[0].SrcBlend              = D3D11_BLEND.D3D11_BLEND_SRC_ALPHA;
            blendDesc.RenderTarget[0].DestBlend             = D3D11_BLEND.D3D11_BLEND_INV_SRC_ALPHA;
            blendDesc.RenderTarget[0].BlendOp               = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD;
            blendDesc.RenderTarget[0].SrcBlendAlpha         = D3D11_BLEND.D3D11_BLEND_ZERO;
            blendDesc.RenderTarget[0].DestBlendAlpha        = D3D11_BLEND.D3D11_BLEND_ZERO;
            blendDesc.RenderTarget[0].BlendOpAlpha          = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD;
            blendDesc.RenderTarget[0].RenderTargetWriteMask = (byte)(D3D11_COLOR_WRITE_ENABLE.D3D11_COLOR_WRITE_ENABLE_ALL);
            _blendState = d3D11Device.CreateBlendState(blendDesc);

            var constantBufferDesc = new D3D11_BUFFER_DESC();
            constantBufferDesc.ByteWidth      = (uint)Marshal.SizeOf <VS_CONSTANT_BUFFER>();
            constantBufferDesc.Usage          = D3D11_USAGE.D3D11_USAGE_DYNAMIC;
            constantBufferDesc.BindFlags      = (uint)D3D11_BIND_FLAG.D3D11_BIND_CONSTANT_BUFFER;
            constantBufferDesc.CPUAccessFlags = (uint)D3D11_CPU_ACCESS_FLAG.D3D11_CPU_ACCESS_WRITE;
            if ((constantBufferDesc.ByteWidth % 16) != 0)
            {
                throw new InvalidOperationException("Constant buffer size must be a multiple of 16.");
            }

            _constantBuffer = d3D11Device.CreateBuffer(constantBufferDesc);

            var vertexBufferDesc = new D3D11_BUFFER_DESC();
            var gc = GCHandle.Alloc(Data.VertexData, GCHandleType.Pinned);
            vertexBufferDesc.ByteWidth = (uint)Data.VertexData.SizeOf();
            vertexBufferDesc.Usage     = D3D11_USAGE.D3D11_USAGE_IMMUTABLE;
            vertexBufferDesc.BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_VERTEX_BUFFER;

            var vertexData = new D3D11_SUBRESOURCE_DATA();
            vertexData.pSysMem = gc.AddrOfPinnedObject();
            _vertexBuffer      = d3D11Device.CreateBuffer(vertexBufferDesc, vertexData);
            gc.Free();

            var indexBufferDesc = new D3D11_BUFFER_DESC();
            gc = GCHandle.Alloc(Data.IndexData, GCHandleType.Pinned);
            indexBufferDesc.ByteWidth = (uint)Data.IndexData.SizeOf();
            indexBufferDesc.Usage     = D3D11_USAGE.D3D11_USAGE_IMMUTABLE;
            indexBufferDesc.BindFlags = (uint)D3D11_BIND_FLAG.D3D11_BIND_INDEX_BUFFER;

            var indexData = new D3D11_SUBRESOURCE_DATA();
            indexData.pSysMem = gc.AddrOfPinnedObject();
            _indexBuffer      = d3D11Device.CreateBuffer(indexBufferDesc, indexData);
            gc.Free();

            var textureDesc = new D3D11_TEXTURE2D_DESC();
            textureDesc.Width            = 20;
            textureDesc.Height           = 20;
            textureDesc.MipLevels        = 1;
            textureDesc.ArraySize        = 1;
            textureDesc.Format           = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
            textureDesc.SampleDesc.Count = 1;
            textureDesc.Usage            = D3D11_USAGE.D3D11_USAGE_IMMUTABLE;
            textureDesc.BindFlags        = (uint)D3D11_BIND_FLAG.D3D11_BIND_SHADER_RESOURCE;

            gc = GCHandle.Alloc(Data.TextureData, GCHandleType.Pinned);
            var textureData = new D3D11_SUBRESOURCE_DATA();
            textureData.pSysMem     = gc.AddrOfPinnedObject();
            textureData.SysMemPitch = 20 * 4; // 4 bytes per pixel
            gc.Free();

            var texture = d3D11Device.CreateTexture2D <ID3D11Texture2D>(textureDesc, textureData);
            _shaderResourceView = d3D11Device.CreateShaderResourceView(texture);
        }
Example #4
0
        // Load the rendering pipeline dependencies.
        private void LoadPipeline()
        {
            Guid             iid;
            ID3D12Debug *    debugController = null;
            IDXGIFactory4 *  factory         = null;
            IDXGIAdapter *   adapter         = null;
            IDXGISwapChain1 *swapChain       = null;

            try
            {
                var dxgiFactoryFlags = 0u;

#if DEBUG
                // Enable the debug layer (requires the Graphics Tools "optional feature").
                // NOTE: Enabling the debug layer after device creation will invalidate the active device.
                {
                    iid = IID_ID3D12Debug;
                    if (SUCCEEDED(D3D12GetDebugInterface(&iid, (void **)&debugController)))
                    {
                        debugController->EnableDebugLayer();

                        // Enable additional debug layers.
                        dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
                    }
                }
#endif

                iid = IID_IDXGIFactory4;
                ThrowIfFailed(nameof(CreateDXGIFactory2), CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&factory));

                if (UseWarpDevice)
                {
                    iid = IID_IDXGIAdapter;
                    ThrowIfFailed(nameof(IDXGIFactory4.EnumWarpAdapter), factory->EnumWarpAdapter(&iid, (void **)&adapter));
                }
                else
                {
                    adapter = GetHardwareAdapter((IDXGIFactory1 *)factory);
                }

                fixed(ID3D12Device **device = &_device)
                {
                    iid = IID_ID3D12Device;
                    ThrowIfFailed(nameof(D3D12CreateDevice), D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &iid, (void **)device));
                }

                // Describe and create the command queue.
                var queueDesc = new D3D12_COMMAND_QUEUE_DESC();

                fixed(ID3D12CommandQueue **commandQueue = &_commandQueue)
                {
                    iid = IID_ID3D12CommandQueue;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandQueue), _device->CreateCommandQueue(&queueDesc, &iid, (void **)commandQueue));
                }

                // Describe and create the swap chain.
                var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                    BufferCount = FrameCount,
                    Width       = Width,
                    Height      = Height,
                    Format      = DXGI_FORMAT_R8G8B8A8_UNORM,
                    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                    SwapEffect  = DXGI_SWAP_EFFECT_FLIP_DISCARD,
                    SampleDesc  = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                };

                ThrowIfFailed(nameof(IDXGIFactory4.CreateSwapChainForHwnd), factory->CreateSwapChainForHwnd(
                                  (IUnknown *)_commandQueue, // Swap chain needs the queue so that it can force a flush on it.
                                  Win32Application.Hwnd,
                                  &swapChainDesc,
                                  pFullscreenDesc: null,
                                  pRestrictToOutput: null,
                                  &swapChain
                                  ));

                // This sample does not support fullscreen transitions.
                ThrowIfFailed(nameof(IDXGIFactory4.MakeWindowAssociation), factory->MakeWindowAssociation(Win32Application.Hwnd, DXGI_MWA_NO_ALT_ENTER));

                fixed(IDXGISwapChain3 **swapChain3 = &_swapChain)
                {
                    iid = IID_IDXGISwapChain3;
                    ThrowIfFailed(nameof(IDXGISwapChain1.QueryInterface), swapChain->QueryInterface(&iid, (void **)swapChain3));
                    _frameIndex = _swapChain->GetCurrentBackBufferIndex();
                }

                // Create descriptor heaps.
                {
                    // Describe and create a render target view (RTV) descriptor heap.
                    var rtvHeapDesc = new D3D12_DESCRIPTOR_HEAP_DESC {
                        NumDescriptors = FrameCount,
                        Type           = D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
                    };

                    fixed(ID3D12DescriptorHeap **rtvHeap = &_rtvHeap)
                    {
                        iid = IID_ID3D12DescriptorHeap;
                        ThrowIfFailed(nameof(ID3D12Device.CreateDescriptorHeap), _device->CreateDescriptorHeap(&rtvHeapDesc, &iid, (void **)rtvHeap));
                    }

                    _rtvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
                }

                // Create frame resources.
                {
                    var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart();

                    // Create a RTV for each frame.
                    iid = IID_ID3D12Resource;

                    for (var n = 0u; n < FrameCount; n++)
                    {
                        ID3D12Resource *renderTarget;
                        {
                            ThrowIfFailed(nameof(IDXGISwapChain3.GetBuffer), _swapChain->GetBuffer(n, &iid, (void **)&renderTarget));
                            _device->CreateRenderTargetView(renderTarget, pDesc: null, rtvHandle);
                            rtvHandle.Offset(1, _rtvDescriptorSize);
                        }
                        _renderTargets[unchecked ((int)n)] = renderTarget;
                    }
                }

                fixed(ID3D12CommandAllocator **commandAllocator = &_commandAllocator)
                {
                    iid = IID_ID3D12CommandAllocator;
                    ThrowIfFailed(nameof(ID3D12Device.CreateRenderTargetView), _device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, &iid, (void **)commandAllocator));
                }

                fixed(ID3D12CommandAllocator **bundleAllocator = &_bundleAllocator)
                {
                    iid = IID_ID3D12CommandAllocator;
                    ThrowIfFailed(nameof(ID3D12Device.CreateRenderTargetView), _device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_BUNDLE, &iid, (void **)bundleAllocator));
                }
            }
            finally
            {
                if (debugController != null)
                {
                    debugController->Release();
                }

                if (factory != null)
                {
                    factory->Release();
                }

                if (adapter != null)
                {
                    adapter->Release();
                }

                if (swapChain != null)
                {
                    swapChain->Release();
                }
            }
        }
Example #5
0
        protected override void CreateWindowSizeDependentResources()
        {
            // Wait until all previous GPU work is complete.
            WaitForGpu(moveToNextFrame: false);

            // Clear the previous window size specific content and update the tracked fence values.
            for (var i = 0u; i < FrameCount; i++)
            {
                _renderTargets[i] = null;
                _fenceValues[i]   = _fenceValues[FrameIndex];
            }

            if (_swapChain != null)
            {
                ThrowIfFailed(nameof(IDXGISwapChain3.ResizeBuffers), _swapChain->ResizeBuffers(FrameCount, (uint)Size.Width, (uint)Size.Height, BackBufferFormat, 0));
            }
            else
            {
                _swapChain = CreateSwapChain();
            }

            CreateResourceViews();

            _viewport = new D3D12_VIEWPORT {
                TopLeftX = 0,
                TopLeftY = 0,
                Width    = Size.Width,
                Height   = Size.Height,
                MinDepth = D3D12_MIN_DEPTH,
                MaxDepth = D3D12_MAX_DEPTH
            };

            _scissorRect = new RECT {
                left   = 0,
                top    = 0,
                right  = Size.Width,
                bottom = Size.Height
            };

            IDXGISwapChain3 *CreateSwapChain()
            {
                using ComPtr <IDXGISwapChain1> swapChain = null;

                var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                    BufferCount = FrameCount,
                    Width       = (uint)Size.Width,
                    Height      = (uint)Size.Height,
                    Format      = BackBufferFormat,
                    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                    SwapEffect  = DXGI_SWAP_EFFECT_FLIP_DISCARD,
                    SampleDesc  = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                };

                ThrowIfFailed(nameof(IDXGIFactory4.CreateSwapChainForHwnd), DxgiFactory->CreateSwapChainForHwnd(
                                  (IUnknown *)_commandQueue, // Swap chain needs the queue so that it can force a flush on it.
                                  Hwnd,
                                  &swapChainDesc,
                                  pFullscreenDesc: null,
                                  pRestrictToOutput: null,
                                  swapChain.GetAddressOf()
                                  ));

                IDXGISwapChain3 *swapChain3;

                var iid = IID_IDXGISwapChain3;

                ThrowIfFailed(nameof(IDXGISwapChain1.QueryInterface), swapChain.Get()->QueryInterface(&iid, (void **)&swapChain3));

                return(swapChain3);
            }
        }
    /// <inheritdoc/>
    public override unsafe void OnInitialize(HWND hwnd)
    {
        // Get the underlying ID3D12Device in use
        fixed(ID3D12Device **d3D12Device = this.d3D12Device)
        {
            _ = InteropServices.TryGetID3D12Device(GraphicsDevice.Default, Windows.__uuidof <ID3D12Device>(), (void **)d3D12Device);
        }

        // Create the direct command queue to use
        fixed(ID3D12CommandQueue **d3D12CommandQueue = this.d3D12CommandQueue)
        {
            D3D12_COMMAND_QUEUE_DESC d3D12CommandQueueDesc;

            d3D12CommandQueueDesc.Type     = D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT;
            d3D12CommandQueueDesc.Priority = (int)D3D12_COMMAND_QUEUE_PRIORITY.D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
            d3D12CommandQueueDesc.Flags    = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE;
            d3D12CommandQueueDesc.NodeMask = 0;

            _ = d3D12Device.Get()->CreateCommandQueue(
                &d3D12CommandQueueDesc,
                Windows.__uuidof <ID3D12CommandQueue>(),
                (void **)d3D12CommandQueue);
        }

        // Create the direct fence
        fixed(ID3D12Fence **d3D12Fence = this.d3D12Fence)
        {
            _ = this.d3D12Device.Get()->CreateFence(
                0,
                D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE,
                Windows.__uuidof <ID3D12Fence>(),
                (void **)d3D12Fence);
        }

        // Create the swap chain to display frames
        fixed(IDXGISwapChain1 **dxgiSwapChain1 = this.dxgiSwapChain1)
        {
            using ComPtr <IDXGIFactory2> dxgiFactory2 = default;

            _ = DirectX.CreateDXGIFactory2(DXGI.DXGI_CREATE_FACTORY_DEBUG, Windows.__uuidof <IDXGIFactory2>(), (void **)dxgiFactory2.GetAddressOf());

            DXGI_SWAP_CHAIN_DESC1 dxgiSwapChainDesc1 = default;

            dxgiSwapChainDesc1.AlphaMode   = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE;
            dxgiSwapChainDesc1.BufferCount = 2;
            dxgiSwapChainDesc1.Flags       = 0;
            dxgiSwapChainDesc1.Format      = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
            dxgiSwapChainDesc1.Width       = 0;
            dxgiSwapChainDesc1.Height      = 0;
            dxgiSwapChainDesc1.SampleDesc  = new DXGI_SAMPLE_DESC(count: 1, quality: 0);
            dxgiSwapChainDesc1.Scaling     = DXGI_SCALING.DXGI_SCALING_STRETCH;
            dxgiSwapChainDesc1.Stereo      = 0;
            dxgiSwapChainDesc1.SwapEffect  = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;

            _ = dxgiFactory2.Get()->CreateSwapChainForHwnd(
                (IUnknown *)d3D12CommandQueue.Get(),
                hwnd,
                &dxgiSwapChainDesc1,
                null,
                null,
                dxgiSwapChain1);
        }

        // Create the command allocator to use
        fixed(ID3D12CommandAllocator **d3D12CommandAllocator = this.d3D12CommandAllocator)
        {
            this.d3D12Device.Get()->CreateCommandAllocator(
                D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                Windows.__uuidof <ID3D12CommandAllocator>(),
                (void **)d3D12CommandAllocator);
        }

        // Create the reusable command list to copy data to the back buffers
        fixed(ID3D12GraphicsCommandList **d3D12GraphicsCommandList = this.d3D12GraphicsCommandList)
        {
            this.d3D12Device.Get()->CreateCommandList(
                0,
                D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                d3D12CommandAllocator,
                null,
                Windows.__uuidof <ID3D12GraphicsCommandList>(),
                (void **)d3D12GraphicsCommandList);
        }

        // Close the command list to prepare it for future use
        this.d3D12GraphicsCommandList.Get()->Close();
    }
        // Load the rendering pipeline dependencies.
        private void LoadPipeline()
        {
            Guid             iid;
            ID3D12Debug *    debugController = null;
            IDXGIFactory4 *  factory         = null;
            IDXGIAdapter *   adapter         = null;
            IDXGISwapChain1 *swapChain       = null;

            try
            {
                var dxgiFactoryFlags = 0u;

#if DEBUG
                // Enable the debug layer (requires the Graphics Tools "optional feature").
                // NOTE: Enabling the debug layer after device creation will invalidate the active device.
                {
                    iid = IID_ID3D12Debug;
                    if (SUCCEEDED(D3D12GetDebugInterface(&iid, (void **)&debugController)))
                    {
                        debugController->EnableDebugLayer();

                        // Enable additional debug layers.
                        dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
                    }
                }
#endif

                iid = IID_IDXGIFactory4;
                ThrowIfFailed(nameof(CreateDXGIFactory2), CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&factory));

                if (UseWarpDevice)
                {
                    iid = IID_IDXGIAdapter;
                    ThrowIfFailed(nameof(IDXGIFactory4.EnumWarpAdapter), factory->EnumWarpAdapter(&iid, (void **)&adapter));
                }
                else
                {
                    adapter = GetHardwareAdapter((IDXGIFactory1 *)factory);
                }

                fixed(ID3D12Device **device = &_device)
                {
                    iid = IID_ID3D12Device;
                    ThrowIfFailed(nameof(D3D12CreateDevice), D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &iid, (void **)device));
                }

                // Describe and create the command queue.
                var queueDesc = new D3D12_COMMAND_QUEUE_DESC();

                fixed(ID3D12CommandQueue **commandQueue = &_commandQueue)
                {
                    iid = IID_ID3D12CommandQueue;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommandQueue), _device->CreateCommandQueue(&queueDesc, &iid, (void **)commandQueue));
                }

                // Describe and create the swap chain.
                var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1 {
                    BufferCount = FrameCount,
                    Width       = Width,
                    Height      = Height,
                    Format      = DXGI_FORMAT_B8G8R8A8_UNORM,
                    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
                    SwapEffect  = DXGI_SWAP_EFFECT_FLIP_DISCARD,

                    // The swap chain could do multisampling for you in older versions of Direct3D
                    // You might see this in tutorials for D3D11
                    // This is no longer supported, so the swapchain has no multisampling itself
                    SampleDesc = new DXGI_SAMPLE_DESC(count: 1, quality: 0),
                };

                ThrowIfFailed(nameof(IDXGIFactory4.CreateSwapChainForHwnd), factory->CreateSwapChainForHwnd(
                                  (IUnknown *)_commandQueue, // Swap chain needs the queue so that it can force a flush on it.
                                  Win32Application.Hwnd,
                                  &swapChainDesc,
                                  pFullscreenDesc: null,
                                  pRestrictToOutput: null,
                                  &swapChain
                                  ));

                // This sample does not support fullscreen transitions.
                ThrowIfFailed(nameof(IDXGIFactory4.MakeWindowAssociation), factory->MakeWindowAssociation(Win32Application.Hwnd, DXGI_MWA_NO_ALT_ENTER));

                fixed(IDXGISwapChain3 **swapChain3 = &_swapChain)
                {
                    iid = IID_IDXGISwapChain3;
                    ThrowIfFailed(nameof(IDXGISwapChain1.QueryInterface), swapChain->QueryInterface(&iid, (void **)swapChain3));
                    _frameIndex = _swapChain->GetCurrentBackBufferIndex();
                }

                // Check MSAA support
                CheckMultiSamplingSupport();

                // Create descriptor heaps.
                {
                    // Describe and create a render target view (RTV) descriptor heap.
                    var rtvHeapDesc = new D3D12_DESCRIPTOR_HEAP_DESC {
                        NumDescriptors = 1, // We only have 1 render target
                        Type           = D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
                    };

                    fixed(ID3D12DescriptorHeap **rtvHeap = &_rtvHeap)
                    {
                        iid = IID_ID3D12DescriptorHeap;
                        ThrowIfFailed(nameof(ID3D12Device.CreateDescriptorHeap), _device->CreateDescriptorHeap(&rtvHeapDesc, &iid, (void **)rtvHeap));
                    }

                    _rtvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
                }

                // Create the render target
                // We do not use the back buffer as that cannot be multisampled
                {
                    var desc = new D3D12_RESOURCE_DESC {
                        Height           = Height,
                        Width            = Width,
                        DepthOrArraySize = 1,
                        Alignment        = 0,
                        SampleDesc       = _msaaDesc,
                        Dimension        = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
                        Flags            = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
                        Format           = DXGI_FORMAT_B8G8R8A8_UNORM,
                        Layout           = D3D12_TEXTURE_LAYOUT_UNKNOWN,
                        MipLevels        = 1
                    };

                    var heapProperties = new D3D12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

                    var clearColor = stackalloc float[4] {
                        0.0f, 0.2f, 0.4f, 1.0f
                    };
                    var clearVal = new D3D12_CLEAR_VALUE(DXGI_FORMAT_B8G8R8A8_UNORM, clearColor);

                    ID3D12Resource *multisampledRenderTarget;
                    iid = IID_ID3D12Resource;
                    ThrowIfFailed(nameof(ID3D12Device.CreateCommittedResource), _device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clearVal, &iid, (void **)&multisampledRenderTarget));
                    _multiSampledRenderTarget = multisampledRenderTarget;
                }

                // Create the render target for the multisampled render target
                {
                    var rtvHandle = _rtvHeap->GetCPUDescriptorHandleForHeapStart();
                    _device->CreateRenderTargetView(_multiSampledRenderTarget, pDesc: null, rtvHandle);
                }

                // Create frame resources.
                {
                    iid = IID_ID3D12Resource;

                    for (var n = 0u; n < FrameCount; n++)
                    {
                        ID3D12Resource *renderTarget;
                        {
                            ThrowIfFailed(nameof(IDXGISwapChain3.GetBuffer), _swapChain->GetBuffer(n, &iid, (void **)&renderTarget));
                        }
                        _renderTargets[unchecked ((int)n)] = renderTarget;
                    }
                }

                fixed(ID3D12CommandAllocator **commandAllocator = &_commandAllocator)
                {
                    iid = IID_ID3D12CommandAllocator;
                    ThrowIfFailed(nameof(ID3D12Device.CreateRenderTargetView), _device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, &iid, (void **)commandAllocator));
                }
            }
            finally
            {
                if (debugController != null)
                {
                    debugController->Release();
                }

                if (factory != null)
                {
                    factory->Release();
                }

                if (adapter != null)
                {
                    adapter->Release();
                }

                if (swapChain != null)
                {
                    swapChain->Release();
                }
            }
        }
Example #8
0
        void InitSwapChain()
        {
            var    panelUnknown            = Marshal.GetIUnknownForObject(SwapChain);
            IntPtr swapChainPanelNativePtr = IntPtr.Zero;

            try
            {
                var guid = Guid.Parse("63aad0b8-7c24-40ff-85a8-640d944cc325");
                Marshal.ThrowExceptionForHR(Marshal.QueryInterface(panelUnknown, ref guid, out swapChainPanelNativePtr));
            }
            finally
            {
                Marshal.Release(panelUnknown);
            }

            if (swapChainPanelNativePtr != IntPtr.Zero)
            {
                m_swapChainNative = (ISwapChainPanelNative *)swapChainPanelNativePtr;

                try
                {
                    #region Init SwapChain
                    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = new DXGI_SWAP_CHAIN_DESC1
                    {
                        Width       = (uint)SwapChain.ActualWidth,
                        Height      = (uint)SwapChain.ActualHeight,
                        Format      = colorFormat,   // This is the most common swapchain format.
                        Stereo      = 0,
                        BufferUsage = (uint)(1L << (1 + 4)),
                        BufferCount = 2,
                        Scaling     = DXGI_SCALING.DXGI_SCALING_STRETCH,
                        SwapEffect  = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                        Flags       = 0
                    };
                    swapChainDesc.SampleDesc.Count   = 1;                        // Don't use multi-sampling.
                    swapChainDesc.SampleDesc.Quality = 0;

                    // Get D3DDevice
                    // This flag adds support for surfaces with a different color channel
                    // ordering than the API default. It is required for compatibility with Direct2D.
                    D3D11_CREATE_DEVICE_FLAG creationFlags = D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT;

                    #if DEBUG
                    // If the project is in a debug build, enable debugging via SDK Layers.
                    creationFlags |= D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_DEBUG;
                    #endif

                    // This example only uses feature level 9.1.
                    D3D_FEATURE_LEVEL[] featureLevels =
                    {
                        D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_9_1
                    };
                    var pFeatureLevel = D3D_FEATURE_LEVEL.D3D_FEATURE_LEVEL_11_1;

                    // Create the Direct3D 11 API device object and a corresponding context.
                    D3D11CreateDevice(
                        (IDXGIAdapter *)IntPtr.Zero.ToPointer(), // Specify nullptr to use the default adapter.
                        D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE,
                        IntPtr.Zero,
                        (uint)creationFlags,
                        InteropUtilities.AsPointer(featureLevels.AsSpan()),
                        (uint)featureLevels.Length,
                        D3D11_SDK_VERSION,          // UWP apps must set this to D3D11_SDK_VERSION.
                        m_d3dDevice.GetAddressOf(), // Returns the Direct3D device created.
                        InteropUtilities.AsPointer(ref pFeatureLevel),
                        m_d3dContext.GetAddressOf() // Returns the device immediate context.
                        );

                    // QI for DXGI device
                    m_d3dDevice.As(ref m_dxgiDevice);

                    // Get the DXGI adapter.
                    IDXGIAdapter *dxgiAdapter;
                    m_dxgiDevice.Get()->GetAdapter(&dxgiAdapter);

                    // Get the DXGI factory.
                    IDXGIFactory2 *dxgiFactory;
                    var            dxgiFactoryGuid = typeof(IDXGIFactory2).GUID;
                    dxgiAdapter->GetParent(InteropUtilities.AsPointer(ref dxgiFactoryGuid), (void **)&dxgiFactory);

                    // Create a swap chain by calling CreateSwapChainForComposition.
                    dxgiFactory->CreateSwapChainForComposition(
                        (IUnknown *)(ID3D11Device *)m_d3dDevice,
                        &swapChainDesc,
                        null,        // Allow on any display.
                        m_swapChain.GetAddressOf()
                        );

                    m_swapChainNative.Get()->SetSwapChain((IDXGISwapChain *)m_swapChain.Get());
                    #endregion

                    InitPipeline();
                    InitGraphics();

                    int hr = m_swapChain.Get()->Present(1, 0);
                    Marshal.ThrowExceptionForHR(hr);

                    SwapChain.SizeChanged += SwapChain_SizeChanged;
                }
                finally
                {
                    m_swapChainNative.Get()->Release();
                }
            }
        }
Example #9
0
        void EnsureDevice(IntPtr hWnd)
        {
            if (m_device)
            {
                return;
            }

            // D3D
            Span <D3D_FEATURE_LEVEL> levels = stackalloc D3D_FEATURE_LEVEL[]
            {
                D3D_FEATURE_LEVEL._11_1,
                D3D_FEATURE_LEVEL._11_0,
                D3D_FEATURE_LEVEL._10_1,
                D3D_FEATURE_LEVEL._10_0,
                D3D_FEATURE_LEVEL._9_3,
                D3D_FEATURE_LEVEL._9_2,
                D3D_FEATURE_LEVEL._9_1
            };
            var flags =
                D3D11_CREATE_DEVICE_FLAG._DEBUG |
                D3D11_CREATE_DEVICE_FLAG._BGRA_SUPPORT;
            var level = default(D3D_FEATURE_LEVEL);

            d3d11.D3D11CreateDevice(
                null,
                D3D_DRIVER_TYPE._HARDWARE,
                IntPtr.Zero,
                (uint)flags,
                ref MemoryMarshal.GetReference(levels),
                (uint)levels.Length,
                Constants.D3D11_SDK_VERSION,
                out m_device,
                out level,
                out m_context).ThrowIfFailed();

            // D2D
            using (var dxgiDevice = new IDXGIDevice())
            {
                m_device.QueryInterface(ref IDXGIDevice.IID, out dxgiDevice.PtrForNew).ThrowIfFailed();

                using (var d2dFactory = new ID2D1Factory1())
                {
                    var factory_opt = new D2D1_FACTORY_OPTIONS
                    {
                    };
                    d2d1.D2D1CreateFactory(D2D1_FACTORY_TYPE._SINGLE_THREADED,
                                           ref ID2D1Factory1.IID, ref factory_opt, out d2dFactory.PtrForNew).ThrowIfFailed();

                    d2dFactory.GetDesktopDpi(out float x, out float y);

                    // using (var d2dDevice = new ())
                    {
                        var prop = new D2D1_CREATION_PROPERTIES
                        {
                        };
                        d2dFactory.CreateDevice(dxgiDevice, out ID2D1Device d2dDevice).ThrowIfFailed();
                        using (d2dDevice)
                            d2dDevice.CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS._NONE, out m_d2dContext).ThrowIfFailed();
                    }
                }

                // SWAPChain
                // using (var adapter = new ())
                {
                    dxgiDevice.GetAdapter(out IDXGIAdapter adapter).ThrowIfFailed();
                    using (adapter)
                        using (var dxgiFactory = new IDXGIFactory2())
                        {
                            adapter.GetParent(ref IDXGIFactory2.IID, out dxgiFactory.PtrForNew).ThrowIfFailed();

                            var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1
                            {
                                Width  = 0,
                                Height = 0,
                                Format = DXGI_FORMAT._B8G8R8A8_UNORM,
                                Stereo = 0
                            };
                            swapChainDesc.SampleDesc.Count   = 1;
                            swapChainDesc.SampleDesc.Quality = 0;
                            swapChainDesc.BufferUsage        = DXGI_USAGE._RENDER_TARGET_OUTPUT;
                            swapChainDesc.BufferCount        = 2;
                            //swapChainDesc.Scaling = DXGI_SCALING_NONE;
                            swapChainDesc.Scaling = DXGI_SCALING._STRETCH;
                            //swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
                            swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT._DISCARD;
                            swapChainDesc.AlphaMode  = DXGI_ALPHA_MODE._UNSPECIFIED;

                            var fs = new DXGI_SWAP_CHAIN_FULLSCREEN_DESC
                            {
                                Windowed = 1,
                            };
                            dxgiFactory.CreateSwapChainForHwnd(
                                dxgiDevice,
                                hWnd,
                                ref swapChainDesc,
                                ref fs,
                                null,
                                out m_swapchain).ThrowIfFailed();

                            Console.Write("CreateSwapchain");
                        }
                }
            }

            // Dwrite
            dwrite.DWriteCreateFactory(DWRITE_FACTORY_TYPE._SHARED, ref IDWriteFactory.IID, out m_dwriteFactory.PtrForNew).ThrowIfFailed();
        }