/// <summary> /// Tries to check or create a warp <see cref="ID3D12Device"/> object. /// </summary> /// <param name="d3D12Device">A pointer to the <see cref="ID3D12Device"/> object to create, or <see langword="null"/>.</param> /// <param name="dxgiAdapter">A pointer to the <see cref="IDXGIAdapter"/> object used to create <paramref name="d3D12Device"/>, or <see langword="null"/>.</param> /// <param name="dxgiDescription1">A pointer to the <see cref="DXGI_ADAPTER_DESC1"/> value for the device found.</param> /// <returns>Whether a warp device was created successfully.</returns> private static unsafe bool TryGetWarpDevice(ID3D12Device **d3D12Device, IDXGIAdapter **dxgiAdapter, DXGI_ADAPTER_DESC1 *dxgiDescription1) { using ComPtr <IDXGIFactory4> dxgiFactory4 = default; EnableDebugMode(); FX.CreateDXGIFactory2(IDXGIFactoryCreationFlags, FX.__uuidof <IDXGIFactory4>(), dxgiFactory4.GetVoidAddressOf()).Assert(); using ComPtr <IDXGIAdapter1> dxgiAdapter1 = default; dxgiFactory4.Get()->EnumWarpAdapter(FX.__uuidof <IDXGIAdapter1>(), dxgiAdapter1.GetVoidAddressOf()).Assert(); dxgiAdapter1.Get()->GetDesc1(dxgiDescription1).Assert(); HRESULT createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), (void **)d3D12Device); dxgiAdapter1.CopyTo(dxgiAdapter); return(FX.SUCCEEDED(createDeviceResult)); }
/// <inheritdoc/> public override unsafe void OnInitialize(HWND hwnd) { // Get the underlying ID3D12Device in use fixed(ID3D12Device **d3D12Device = this.d3D12Device) { _ = InteropServices.TryGetID3D12Device(Gpu.Default, FX.__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, FX.__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, FX.__uuidof <ID3D12Fence>(), (void **)d3D12Fence); } // Create the swap chain to display frames fixed(IDXGISwapChain1 **dxgiSwapChain1 = this.dxgiSwapChain1) { using ComPtr <IDXGIFactory2> dxgiFactory2 = default; _ = FX.CreateDXGIFactory2(FX.DXGI_CREATE_FACTORY_DEBUG, FX.__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, FX.__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, FX.__uuidof <ID3D12GraphicsCommandList>(), (void **)d3D12GraphicsCommandList); } // Close the command list to prepare it for future use this.d3D12GraphicsCommandList.Get()->Close(); }
/// <summary> /// Tries to check or create a default <see cref="ID3D12Device"/> object. /// </summary> /// <param name="d3D12Device">A pointer to the <see cref="ID3D12Device"/> object to create, or <see langword="null"/>.</param> /// <param name="dxgiAdapter">A pointer to the <see cref="IDXGIAdapter"/> object used to create <paramref name="d3D12Device"/>, or <see langword="null"/>.</param> /// <param name="dxgiDescription1">A pointer to the <see cref="DXGI_ADAPTER_DESC1"/> value for the device found.</param> /// <returns>Whether a default device was found with the requested feature level.</returns> private static unsafe bool TryGetDefaultDevice(ID3D12Device **d3D12Device, IDXGIAdapter **dxgiAdapter, DXGI_ADAPTER_DESC1 *dxgiDescription1) { using ComPtr <IDXGIFactory4> dxgiFactory4 = default; EnableDebugMode(); FX.CreateDXGIFactory2(IDXGIFactoryCreationFlags, FX.__uuidof <IDXGIFactory4>(), dxgiFactory4.GetVoidAddressOf()).Assert(); uint i = 0; while (true) { using ComPtr <IDXGIAdapter1> dxgiAdapter1 = default; HRESULT enumAdapters1Result = dxgiFactory4.Get()->EnumAdapters1(i++, dxgiAdapter1.GetAddressOf()); if (enumAdapters1Result == FX.DXGI_ERROR_NOT_FOUND) { return(false); } enumAdapters1Result.Assert(); dxgiAdapter1.Get()->GetDesc1(dxgiDescription1).Assert(); if (dxgiDescription1->VendorId == MicrosoftVendorId && dxgiDescription1->DeviceId == WarpDeviceId) { continue; } // Explicit paths for when a device is being retrieved or not, with special handling // for the additional check that is required for the SM6 level. This can't be checked // without creating a device first, so the path for when the target device pointer is // null is useful to do an initial filtering using D3D12CreateDevice to avoid creating // a device for adapters that would've failed at the FL11 check already. if (d3D12Device == null) { HRESULT createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), null); if (FX.SUCCEEDED(createDeviceResult)) { using ComPtr <ID3D12Device> d3D12DeviceCandidate = default; createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), d3D12DeviceCandidate.GetVoidAddressOf()); if (FX.SUCCEEDED(createDeviceResult) && d3D12DeviceCandidate.Get()->IsShaderModelSupported(D3D_SHADER_MODEL_6_0)) { return(true); } } } else { using ComPtr <ID3D12Device> d3D12DeviceCandidate = default; HRESULT createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), d3D12DeviceCandidate.GetVoidAddressOf()); if (FX.SUCCEEDED(createDeviceResult) && d3D12DeviceCandidate.Get()->IsShaderModelSupported(D3D_SHADER_MODEL_6_0)) { d3D12DeviceCandidate.CopyTo(d3D12Device); dxgiAdapter1.CopyTo(dxgiAdapter); return(true); } } } }
/// <inheritdoc/> public bool MoveNext() { if (!this.isInitialized) { this.isInitialized = true; fixed(IDXGIFactory4 **dxgiFactory4 = this.dxgiFactory4) { EnableDebugMode(); FX.CreateDXGIFactory2(IDXGIFactoryCreationFlags, FX.__uuidof <IDXGIFactory4>(), (void **)dxgiFactory4).Assert(); } } if (this.isCompleted) { return(false); } while (true) { using ComPtr <IDXGIAdapter1> dxgiAdapter1 = default; HRESULT enumAdapters1Result = this.dxgiFactory4.Get()->EnumAdapters1(this.index, dxgiAdapter1.GetAddressOf()); if (enumAdapters1Result == FX.DXGI_ERROR_NOT_FOUND) { this.dxgiFactory4.Get()->EnumWarpAdapter(FX.__uuidof <IDXGIAdapter1>(), dxgiAdapter1.GetVoidAddressOf()).Assert(); DXGI_ADAPTER_DESC1 dxgiDescription1; dxgiAdapter1.Get()->GetDesc1(&dxgiDescription1).Assert(); HRESULT createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), null); if (FX.SUCCEEDED(createDeviceResult) && this.predicate(new GraphicsDeviceInfo(&dxgiDescription1))) { using ComPtr <ID3D12Device> d3D12Device = default; FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), d3D12Device.GetVoidAddressOf()).Assert(); this.graphicsDevice = GetOrCreateDevice(d3D12Device.Get(), (IDXGIAdapter *)dxgiAdapter1.Get(), &dxgiDescription1); this.isCompleted = true; return(true); } return(false); } else { enumAdapters1Result.Assert(); this.index++; DXGI_ADAPTER_DESC1 dxgiDescription1; dxgiAdapter1.Get()->GetDesc1(&dxgiDescription1).Assert(); if (dxgiDescription1.VendorId == MicrosoftVendorId && dxgiDescription1.DeviceId == WarpDeviceId) { continue; } HRESULT createDeviceResult = FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), null); if (FX.SUCCEEDED(createDeviceResult) && this.predicate(new GraphicsDeviceInfo(&dxgiDescription1))) { using ComPtr <ID3D12Device> d3D12Device = default; FX.D3D12CreateDevice( dxgiAdapter1.AsIUnknown().Get(), D3D_FEATURE_LEVEL_11_0, FX.__uuidof <ID3D12Device>(), d3D12Device.GetVoidAddressOf()).Assert(); if (d3D12Device.Get()->IsShaderModelSupported(D3D_SHADER_MODEL_6_0)) { this.graphicsDevice = GetOrCreateDevice(d3D12Device.Get(), (IDXGIAdapter *)dxgiAdapter1.Get(), &dxgiDescription1); return(true); } } } } }