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