/// <summary> /// Creates and initializes a new <see cref="IDXGIFactory4As6Backcompat"/> instance. /// </summary> /// <param name="dxgiFactory4">The <see cref="IDXGIFactory4"/> instance to wrap.</param> /// <param name="dxgiFactory6">The resulting <see cref="IDXGIFactory6"/> instance.</param> public static void Create(IDXGIFactory4 *dxgiFactory4, IDXGIFactory6 **dxgiFactory6) { IDXGIFactory4As6Backcompat * @this = (IDXGIFactory4As6Backcompat *)NativeMemory.Alloc((nuint)sizeof(IDXGIFactory4As6Backcompat)); @this->lpVtbl = Vtbl; @this->dxgiFactory4 = dxgiFactory4; _ = dxgiFactory4->AddRef(); *dxgiFactory6 = (IDXGIFactory6 *)@this; }
// 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 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); } }
// 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(); } } }
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..]);