public static IDXGIAdapter1 *GetLatestDxgiAdapter(IDXGIAdapter1 *dxgiAdapter, out uint dxgiAdapterVersion) { IDXGIAdapter1 *result; if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter4>(), (void **)&result).SUCCEEDED) { dxgiAdapterVersion = 4; _ = dxgiAdapter->Release(); } else if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter3>(), (void **)&result).SUCCEEDED) { dxgiAdapterVersion = 3; _ = dxgiAdapter->Release(); } else if (dxgiAdapter->QueryInterface(__uuidof <IDXGIAdapter2>(), (void **)&result).SUCCEEDED) { dxgiAdapterVersion = 2; _ = dxgiAdapter->Release(); } else { dxgiAdapterVersion = 1; result = dxgiAdapter; } return(result); }
protected override void CreateDeviceDependentResources() { _dxgiFactory = CreateDxgiFactory(); _dxgiAdapter = GetDxgiAdapter(); _d3dDevice = CreateD3DDevice(out _immediateContext); CreateAssets(); ID3D11Device *CreateD3DDevice(out ID3D11DeviceContext *pImmediateContext) { ID3D11Device * d3dDevice; ID3D11DeviceContext *immediateContext; var featureLevel = D3D_FEATURE_LEVEL_11_0; ThrowIfFailed(D3D11CreateDevice((IDXGIAdapter *)DxgiAdapter, D3D_DRIVER_TYPE_HARDWARE, Software: HMODULE.NULL, Flags: 0, &featureLevel, FeatureLevels: 1, D3D11_SDK_VERSION, &d3dDevice, pFeatureLevel: null, &immediateContext)); pImmediateContext = immediateContext; return(d3dDevice); } IDXGIFactory1 *CreateDxgiFactory() { IDXGIFactory1 *dxgiFactory; ThrowIfFailed(CreateDXGIFactory1(__uuidof <IDXGIFactory1>(), (void **)&dxgiFactory)); return(dxgiFactory); } IDXGIAdapter1 *GetDxgiAdapter() { return(UseWarpDevice ? throw new NotImplementedException("WARP Device not supported for D3D11.") : GetHardwareAdapter(_dxgiFactory)); } }
ValueList <GraphicsAdapter> GetAdapters(IDXGIFactory3 *dxgiFactory) { IDXGIAdapter1 *dxgiAdapter1 = null; var adapters = new ValueList <GraphicsAdapter>(); var index = 0u; do { var result = dxgiFactory->EnumAdapters1(index, &dxgiAdapter1); if (result.FAILED) { if (result != DXGI_ERROR_NOT_FOUND) { ReleaseIfNotNull(dxgiAdapter1); ExceptionUtilities.ThrowExternalException(nameof(IDXGIFactory1.EnumAdapters1), result); } index = 0; } else { var adapter = new GraphicsAdapter(this, dxgiAdapter1); adapters.Add(adapter); index++; dxgiAdapter1 = null; } }while (index != 0); return(adapters); }
internal D3D12GraphicsAdapter(D3D12GraphicsProvider provider, IDXGIAdapter1 *dxgiAdapter) : base(provider) { ThrowIfNull(dxgiAdapter, nameof(dxgiAdapter)); _dxgiAdapter = dxgiAdapter; _dxgiAdapterDesc = new ValueLazy <DXGI_ADAPTER_DESC1>(GetDxgiAdapterDesc); _name = new ValueLazy <string>(GetName); _ = _state.Transition(to: Initialized); }
protected override void DestroyDeviceDependentResources() { DestroyAssets(); DestroyImmediateContext(); DestroyD3DDevice(); DestroyDxgiAdapter(); DestroyDxgiFactory(); void DestroyD3DDevice() { var d3dDevice = _d3dDevice; if (d3dDevice != null) { _d3dDevice = null; _ = d3dDevice->Release(); } } void DestroyDxgiAdapter() { var dxgiAdapter = _dxgiAdapter; if (dxgiAdapter != null) { _dxgiAdapter = null; _ = dxgiAdapter->Release(); } } void DestroyDxgiFactory() { var dxgiFactory = _dxgiFactory; if (dxgiFactory != null) { _dxgiFactory = null; _ = dxgiFactory->Release(); } } void DestroyImmediateContext() { var immediateContext = _immediateContext; if (immediateContext != null) { _immediateContext = null; _ = immediateContext->Release(); } } }
/// <summary>Initializes a new instance of the <see cref="GraphicsAdapter" /> class.</summary> /// <param name="graphicsProvider">The <see cref="GraphicsProvider" /> for the instance.</param> /// <param name="adapter">The <see cref="IDXGIAdapter1" /> for the instance.</param> /// <exception cref="ExternalException">The call to <see cref="IDXGIAdapter1.GetDesc1(DXGI_ADAPTER_DESC1*)" /> failed.</exception> internal GraphicsAdapter(GraphicsProvider graphicsProvider, IDXGIAdapter1 *adapter) { _graphicsProvider = graphicsProvider; _adapter = adapter; DXGI_ADAPTER_DESC1 desc; ThrowExternalExceptionIfFailed(nameof(IDXGIAdapter1.GetDesc1), adapter->GetDesc1(&desc)); _deviceName = Marshal.PtrToStringUni((IntPtr)desc.Description); _vendorId = desc.VendorId; _deviceId = desc.DeviceId; _state.Transition(to: Initialized); }
internal GraphicsAdapter(GraphicsService service, IDXGIAdapter1 *dxgiAdapter) : base(service) { dxgiAdapter = GetLatestDxgiAdapter(dxgiAdapter, out _dxgiAdapterVersion); _dxgiAdapter.Attach(dxgiAdapter); DXGI_ADAPTER_DESC1 dxgiAdapterDesc; ThrowExternalExceptionIfFailed(dxgiAdapter->GetDesc1(&dxgiAdapterDesc)); _description = GetUtf16Span(dxgiAdapterDesc.Description, 128).GetString() ?? string.Empty; _pciDeviceId = dxgiAdapterDesc.DeviceId; _pciVendorId = dxgiAdapterDesc.VendorId; SetName(_description); _devices = new ValueList <GraphicsDevice>(); _devicesMutex = new ValueMutex(); }
private ImmutableArray <GraphicsAdapter> GetGraphicsAdapters() { IDXGIAdapter1 *adapter = null; var graphicsAdapters = ImmutableArray.CreateBuilder <GraphicsAdapter>(); try { var index = 0u; while (true) { var hr = Factory->EnumAdapters1(index, &adapter); if (FAILED(hr)) { if (hr == DXGI_ERROR_NOT_FOUND) { break; } ThrowExternalException(nameof(IDXGIFactory1.EnumAdapters1), hr); } var graphicsAdapter = new GraphicsAdapter(this, adapter); graphicsAdapters.Add(graphicsAdapter); adapter = null; index++; } } finally { // We explicitly set adapter to null in the enumeration above so that we only // release in the case of an exception being thrown. if (adapter != null) { _ = adapter->Release(); } } return(graphicsAdapters.ToImmutable()); }
protected abstract bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter);
protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter) { var iid = IID_ID3D12Device; return(SUCCEEDED(D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &iid, null))); }
protected override void DestroyDeviceDependentResources() { DestroyAssets(); DestroyGraphicsCommandLists(); DestroyPipelineState(); DestroyRootSignature(); DestroyFenceEvent(); DestroyFence(); DestroyCommandAllocators(); DestroyDescriptorHeaps(); DestroyCommandQueue(); DestroyD3DDevice(); DestroyDxgiAdapter(); DestroyDxgiFactory(); void DestroyCommandAllocators() { for (var i = 0; i < _commandAllocators.Length; i++) { var commandAllocator = _commandAllocators[i]; if (commandAllocator != null) { _commandAllocators[i] = null; _ = commandAllocator->Release(); } } } void DestroyCommandQueue() { var commandQueue = _commandQueue; if (commandQueue != null) { _commandQueue = null; _ = commandQueue->Release(); } } void DestroyD3DDevice() { var d3dDevice = _d3dDevice; if (d3dDevice != null) { _d3dDevice = null; _ = d3dDevice->Release(); } } void DestroyDxgiAdapter() { var dxgiAdapter = _dxgiAdapter; if (dxgiAdapter != null) { _dxgiAdapter = null; _ = dxgiAdapter->Release(); } } void DestroyDxgiFactory() { var dxgiFactory = _dxgiFactory; if (dxgiFactory != null) { _dxgiFactory = null; _ = dxgiFactory->Release(); } } void DestroyFence() { var fence = _fence; if (fence != null) { _fence = null; _ = fence->Release(); } } void DestroyFenceEvent() { var fenceEvent = _fenceEvent; if (fenceEvent != IntPtr.Zero) { _fenceEvent = IntPtr.Zero; _ = CloseHandle(_fenceEvent); } } void DestroyGraphicsCommandLists() { for (var i = 0; i < _graphicsCommandLists.Length; i++) { var graphicsCommandList = _graphicsCommandLists[i]; if (graphicsCommandList != null) { _graphicsCommandLists[i] = null; _ = graphicsCommandList->Release(); } } } void DestroyPipelineState() { var pipelineState = _pipelineState; if (pipelineState != null) { _pipelineState = null; _ = pipelineState->Release(); } } void DestroyRootSignature() { var rootSignature = _rootSignature; if (rootSignature != null) { _rootSignature = null; _ = rootSignature->Release(); } } }
protected override void CreateDeviceDependentResources() { _dxgiFactory = CreateDxgiFactory(); _dxgiAdapter = GetDxgiAdapter(); _d3dDevice = CreateD3DDevice(); _commandQueue = CreateCommandQueue(); CreateDescriptorHeaps(); for (int i = 0; i < FrameCount; i++) { _commandAllocators[i] = CreateCommandAllocator(); } _fence = CreateFence(); _fenceValues = CreateFenceValues(); _fenceEvent = CreateFenceEvent(); _rootSignature = CreateRootSignature(); _pipelineState = CreatePipelineState(); _graphicsCommandLists = CreateGraphicsCommandLists(); ThrowIfFailed(nameof(ID3D12CommandAllocator.Reset), CommandAllocator->Reset()); ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Reset), GraphicsCommandList->Reset(CommandAllocator, PipelineState)); CreateAssets(); ID3D12CommandAllocator *CreateCommandAllocator() { ID3D12CommandAllocator *commandAllocator; var iid = IID_ID3D12CommandAllocator; ThrowIfFailed(nameof(ID3D12Device.CreateCommandAllocator), D3DDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, &iid, (void **)&commandAllocator)); return(commandAllocator); } ID3D12CommandQueue *CreateCommandQueue() { var queueDesc = new D3D12_COMMAND_QUEUE_DESC(); ID3D12CommandQueue *commandQueue; var iid = IID_ID3D12CommandQueue; ThrowIfFailed(nameof(ID3D12Device.CreateCommandQueue), D3DDevice->CreateCommandQueue(&queueDesc, &iid, (void **)&commandQueue)); return(commandQueue); } ID3D12Device *CreateD3DDevice() { ID3D12Device *d3dDevice; var iid = IID_ID3D12Device; ThrowIfFailed(nameof(D3D12CreateDevice), D3D12CreateDevice((IUnknown *)_dxgiAdapter, D3D_FEATURE_LEVEL_11_0, &iid, (void **)&d3dDevice)); return(d3dDevice); } IDXGIFactory4 *CreateDxgiFactory() { var dxgiFactoryFlags = TryEnableDebugLayer() ? DXGI_CREATE_FACTORY_DEBUG : 0u; IDXGIFactory4 *dxgiFactory; var iid = IID_IDXGIFactory4; ThrowIfFailed(nameof(CreateDXGIFactory2), CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&dxgiFactory)); return(dxgiFactory); } ID3D12Fence *CreateFence() { ID3D12Fence *fence; var iid = IID_ID3D12Fence; ThrowIfFailed(nameof(ID3D12Device.CreateFence), D3DDevice->CreateFence(InitialValue: 0, D3D12_FENCE_FLAG_NONE, &iid, (void **)&fence)); return(fence); } IntPtr CreateFenceEvent() { var fenceEvent = CreateEventW(lpEventAttributes: null, bManualReset: FALSE, bInitialState: FALSE, lpName: null); if (fenceEvent == IntPtr.Zero) { var hr = Marshal.GetHRForLastWin32Error(); Marshal.ThrowExceptionForHR(hr); } return(fenceEvent); } ulong[] CreateFenceValues() { var fenceValues = new ulong[FrameCount]; fenceValues[0] = 1; return(fenceValues); } ID3D12GraphicsCommandList *[] CreateGraphicsCommandLists() { var graphicsCommandLists = new ID3D12GraphicsCommandList *[FrameCount]; for (uint i = 0u; i < FrameCount; i++) { ID3D12GraphicsCommandList *graphicsCommandList; var iid = IID_ID3D12GraphicsCommandList; ThrowIfFailed(nameof(ID3D12Device.CreateCommandList), D3DDevice->CreateCommandList(nodeMask: 0, D3D12_COMMAND_LIST_TYPE_DIRECT, _commandAllocators[i], PipelineState, &iid, (void **)&graphicsCommandList)); ThrowIfFailed(nameof(ID3D12GraphicsCommandList.Close), graphicsCommandList->Close()); graphicsCommandLists[i] = graphicsCommandList; } return(graphicsCommandLists); } IDXGIAdapter1 *GetDxgiAdapter() { if (UseWarpDevice) { IDXGIAdapter1 *adapter; var iid = IID_IDXGIAdapter; ThrowIfFailed(nameof(IDXGIFactory4.EnumWarpAdapter), _dxgiFactory->EnumWarpAdapter(&iid, (void **)&adapter)); return(adapter); } else { return(GetHardwareAdapter((IDXGIFactory1 *)_dxgiFactory)); } } bool TryEnableDebugLayer() { #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. using ComPtr <ID3D12Debug> debugController = null; var iid = IID_ID3D12Debug; if (SUCCEEDED(D3D12GetDebugInterface(&iid, (void **)&debugController))) { debugController.Get()->EnableDebugLayer(); return(true); } #endif return(false); } }
protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter) { var featureLevel = D3D_FEATURE_LEVEL_11_0; return(SUCCEEDED(D3D11CreateDevice((IDXGIAdapter *)adapter, D3D_DRIVER_TYPE_HARDWARE, Software: IntPtr.Zero, Flags: 0, &featureLevel, FeatureLevels: 1, D3D11_SDK_VERSION, ppDevice: null, pFeatureLevel: null, ppImmediateContext: null))); }
protected override unsafe bool SupportsRequiredDirect3DVersion(IDXGIAdapter1 *adapter) { return(D3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, __uuidof <ID3D12Device>(), null).SUCCEEDED); }
public static SystemParameters Create() { var(width, height, _) = GetDisplays().First(d => d.IsPrimary); /*using var f = new SharpDX.DXGI.Factory1(); * var video_memory = f.Adapters1.Select(a => * Math.Max(a.Description.DedicatedSystemMemory, (long)a.Description.DedicatedVideoMemory)).Max();*/ var dxgiMemory = 0UL; unsafe { using var api = DXGI.GetApi(); IDXGIFactory1 *factory1 = default; try { //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-createdxgifactory1 SilkMarshal.ThrowHResult(api.CreateDXGIFactory1(SilkMarshal.GuidPtrOf <IDXGIFactory1>(), (void **)&factory1)); uint i = 0u; while (true) { IDXGIAdapter1 *adapter1 = default; //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgifactory1-enumadapters1 var res = factory1->EnumAdapters1(i, &adapter1); var exception = Marshal.GetExceptionForHR(res); if (exception != null) { break; } AdapterDesc1 adapterDesc = default; //https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiadapter1-getdesc1 SilkMarshal.ThrowHResult(adapter1->GetDesc1(&adapterDesc)); var systemMemory = (ulong)adapterDesc.DedicatedSystemMemory; var videoMemory = (ulong)adapterDesc.DedicatedVideoMemory; var maxMemory = Math.Max(systemMemory, videoMemory); if (maxMemory > dxgiMemory) { dxgiMemory = maxMemory; } adapter1->Release(); i++; } } catch (Exception e) { Utils.ErrorThrow(e); } finally { if (factory1->LpVtbl != (void **)IntPtr.Zero) { factory1->Release(); } } } var memory = Utils.GetMemoryStatus(); return(new SystemParameters { ScreenWidth = width, ScreenHeight = height, VideoMemorySize = (long)dxgiMemory, SystemMemorySize = (long)memory.ullTotalPhys, SystemPageSize = (long)memory.ullTotalPageFile - (long)memory.ullTotalPhys }); }
protected override void CreateDeviceDependentResources() { _dxgiFactory = CreateDxgiFactory(); _dxgiAdapter = GetDxgiAdapter(); _d3dDevice = CreateD3DDevice(); StartInfoPump(); _commandQueue = CreateCommandQueue(); CreateDescriptorHeaps(); for (int i = 0; i < FrameCount; i++) { _commandAllocators[i] = CreateCommandAllocator(); } _fence = CreateFence(); _fenceValues = CreateFenceValues(); _fenceEvent = CreateFenceEvent(); _rootSignature = CreateRootSignature(); _pipelineState = CreatePipelineState(); _graphicsCommandLists = CreateGraphicsCommandLists(); SilkMarshal.ThrowHResult(CommandAllocator->Reset()); SilkMarshal.ThrowHResult(GraphicsCommandList->Reset(CommandAllocator, PipelineState)); CreateAssets(); ID3D12CommandAllocator *CreateCommandAllocator() { ID3D12CommandAllocator *commandAllocator; var iid = ID3D12CommandAllocator.Guid; SilkMarshal.ThrowHResult ( D3DDevice->CreateCommandAllocator (CommandListType.CommandListTypeDirect, &iid, (void **)&commandAllocator) ); return(commandAllocator); } ID3D12CommandQueue *CreateCommandQueue() { var queueDesc = new CommandQueueDesc(); ID3D12CommandQueue *commandQueue; var iid = ID3D12CommandQueue.Guid; SilkMarshal.ThrowHResult(D3DDevice->CreateCommandQueue(&queueDesc, &iid, (void **)&commandQueue)); return(commandQueue); } ID3D12Device *CreateD3DDevice() { ID3D12Device *d3dDevice; var iid = ID3D12Device.Guid; SilkMarshal.ThrowHResult ( D3D12.CreateDevice ((IUnknown *)_dxgiAdapter, D3DFeatureLevel.D3DFeatureLevel110, &iid, (void **)&d3dDevice) ); return(d3dDevice); } IDXGIFactory4 *CreateDxgiFactory() { var dxgiFactoryFlags = TryEnableDebugLayer() ? 0x01 : 0u; IDXGIFactory4 *dxgiFactory; var iid = IDXGIFactory4.Guid; SilkMarshal.ThrowHResult(Dxgi.CreateDXGIFactory2(dxgiFactoryFlags, &iid, (void **)&dxgiFactory)); return(dxgiFactory); } ID3D12Fence *CreateFence() { ID3D12Fence *fence; var iid = ID3D12Fence.Guid; SilkMarshal.ThrowHResult (D3DDevice->CreateFence(InitialValue: 0, FenceFlags.FenceFlagNone, &iid, (void **)&fence)); return(fence); } IntPtr CreateFenceEvent() { var fenceEvent = SilkMarshal.CreateWindowsEvent(null, false, false, null); if (fenceEvent == IntPtr.Zero) { var hr = Marshal.GetHRForLastWin32Error(); Marshal.ThrowExceptionForHR(hr); } return(fenceEvent); } ulong[] CreateFenceValues() { var fenceValues = new ulong[FrameCount]; fenceValues[0] = 1; return(fenceValues); } ID3D12GraphicsCommandList *[] CreateGraphicsCommandLists() { var graphicsCommandLists = new ID3D12GraphicsCommandList *[FrameCount]; for (uint i = 0u; i < FrameCount; i++) { ID3D12GraphicsCommandList *graphicsCommandList; var iid = ID3D12GraphicsCommandList.Guid; SilkMarshal.ThrowHResult ( D3DDevice->CreateCommandList ( nodeMask: 0, CommandListType.CommandListTypeDirect, _commandAllocators[i], PipelineState, &iid, (void **)&graphicsCommandList ) ); SilkMarshal.ThrowHResult(graphicsCommandList->Close()); graphicsCommandLists[i] = graphicsCommandList; } return(graphicsCommandLists); } IDXGIAdapter1 *GetDxgiAdapter() { if (UseWarpDevice) { IDXGIAdapter1 *adapter; var iid = IDXGIAdapter.Guid; SilkMarshal.ThrowHResult(_dxgiFactory->EnumWarpAdapter(&iid, (void **)&adapter)); return(adapter); } else { return(GetHardwareAdapter((IDXGIFactory1 *)_dxgiFactory)); } } bool TryEnableDebugLayer() { #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. using ComPtr <ID3D12Debug> debugController = null; var iid = ID3D12Debug.Guid; var hr = D3D12.GetDebugInterface(&iid, (void **)&debugController); if (HResult.IndicatesSuccess(hr)) { debugController.Get().EnableDebugLayer(); Log.LogInformation("Debug layer enabled"); return(_debug = true); } else { Log.LogWarning ( Marshal.GetExceptionForHR(hr), $"Failed to enable debug layer, failed with result {hr} (0x{hr:x8})" ); } #endif return(false); } void StartInfoPump() { #if DEBUG if (!_debug) { Log.LogInformation("Skipped creation of info pump due to the debug layer not being enabled."); return; } var iid = ID3D12InfoQueue.Guid; fixed(ID3D12InfoQueue ** @out = &_infoQueue) { SilkMarshal.ThrowHResult(D3DDevice->QueryInterface(&iid, (void **)@out)); } _infoPumpCancellationToken = new(); _infoPump = Task.Run ( () => { Log.LogInformation("Info queue pump started"); while (!_infoPumpCancellationToken.Token.IsCancellationRequested) { var numMessages = _infoQueue->GetNumStoredMessages(); if (numMessages == 0) { continue; } for (var i = 0ul; i < numMessages; i++) { nuint msgByteLength; SilkMarshal.ThrowHResult(_infoQueue->GetMessageA(i, null, &msgByteLength)); using var memory = GlobalMemory.Allocate((int)msgByteLength); SilkMarshal.ThrowHResult ( _infoQueue->GetMessageA(i, memory.AsPtr <Message>(), &msgByteLength) ); ref var msg = ref memory.AsRef <Message>(); var descBytes = new Span <byte>(msg.PDescription, (int)msg.DescriptionByteLength); var desc = Encoding.UTF8.GetString(descBytes[..^ 1]); var eid = new EventId((int)msg.ID, msg.ID.ToString()["MessageID".Length..]);