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); }
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); }
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); }
// 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(); } } }
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(); } } }
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(); } } }
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(); }