private static Adapter CreateAdapter(UniqueComPtr <IDXGIAdapter1> dxgiAdapter) { var p = dxgiAdapter.Ptr; DXGI_ADAPTER_DESC1 desc; Guard.ThrowIfFailed(p->GetDesc1(&desc)); LARGE_INTEGER driverVersion; Guid iid = IID_IDXGIDevice; Guard.ThrowIfFailed(dxgiAdapter.Ptr->CheckInterfaceSupport(&iid, &driverVersion)); var descText = new string((char *)desc.Description); return(new Adapter( dxgiAdapter.AsIUnknown(), descText, (AdapterVendor)desc.VendorId, desc.DeviceId, desc.SubSysId, desc.Revision, desc.DedicatedVideoMemory, desc.DedicatedSystemMemory, desc.SharedSystemMemory, desc.AdapterLuid, (ulong)driverVersion.QuadPart, (desc.Flags & (int)DXGI_ADAPTER_FLAG.DXGI_ADAPTER_FLAG_SOFTWARE) != 0, DeviceType.GraphicsAndCompute // DXGI doesn't support enumerating non-graphics adapters )); }
private static ulong StartingFenceForContext(ExecutionContext context) => 0; // context switch //{ // // we do this to prevent conflicts when comparing markers // ExecutionContext.Copy => ulong.MaxValue / 4 * 0, // ExecutionContext.Compute => ulong.MaxValue / 4 * 1, // ExecutionContext.Graphics => ulong.MaxValue / 4 * 2, // _ => 0xFFFFFFFFFFFFFFFF //}; public CommandQueue( ComputeDevice device, ExecutionContext context, bool enableTdr ) { Debug.Assert(device is object); Type = context; _device = device; _queue = device.CreateQueue(context, enableTdr ? D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE : D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT); _fence = device.CreateFence(StartingFenceForContext(context)); _lastFence = _fence.Ptr->GetCompletedValue(); var name = GetListTypeName(context); this.SetName(name + " Queue"); DebugHelpers.SetName(_fence.Ptr, name + " Fence"); ulong frequency; int hr = _queue.Ptr->GetTimestampFrequency(&frequency); // E_FAIL is returned when the queue doesn't support timestamps if (SUCCEEDED(hr) || hr == E_FAIL) { Frequency = hr == E_FAIL ? 0 : frequency; } else { Frequency = 0; _device.ThrowIfFailed(hr, "_queue.Ptr->GetTimestampFrequency(&frequency)"); } }
/// <summary> /// Creates a new <see cref="PipelineManager"/> for a device /// </summary> /// <param name="device">The <see cref="ComputeDevice"/> to create the manager for</param> public PipelineManager(ComputeDevice device) { _device = device; if (device.QueryFeatureSupport <D3D12_FEATURE_DATA_SHADER_CACHE>(D3D12_FEATURE.D3D12_FEATURE_SHADER_CACHE) .SupportFlags.HasFlag(D3D12_SHADER_CACHE_SUPPORT_FLAGS.D3D12_SHADER_CACHE_SUPPORT_LIBRARY)) { return; } Span <byte> cache = GetCache(); fixed(byte *pCache = cache) { using UniqueComPtr <ID3D12PipelineLibrary1> psoLibrary = default; int hr = E_FAIL; try { hr = _device.As <ID3D12Device2>()->CreatePipelineLibrary(pCache, (uint)cache.Length, psoLibrary.Iid, (void **)&psoLibrary); } // Debug layer may throw catch (SEHException) { } if (hr is E_INVALIDARG or D3D12_ERROR_DRIVER_VERSION_MISMATCH or D3D12_ERROR_ADAPTER_NOT_FOUND) { // cache invalidated Guard.ThrowIfFailed(_device.As <ID3D12Device2>()->CreatePipelineLibrary(null, 0, psoLibrary.Iid, (void **)&psoLibrary)); DeleteCache(); }
internal override bool TryGetAdapterByIndex(uint index, out Adapter adapter) { while (true) { using UniqueComPtr <IDXCoreAdapter> dxcoreAdapter = default; // Reached end of list if (_list.Ptr->GetAdapterCount() - (index + _hardwareAdapterSkip) == 0) { adapter = default; return(false); } Guard.ThrowIfFailed(_list.Ptr->GetAdapter(index, dxcoreAdapter.Iid, (void **)&dxcoreAdapter)); if (_softwareOnly) { bool isSoftware; Guard.ThrowIfFailed(dxcoreAdapter.Ptr->GetProperty(DXCoreAdapterProperty.IsHardware, sizeof(bool), &isSoftware)); if (!isSoftware) { _hardwareAdapterSkip++; continue; } } adapter = CreateAdapter(dxcoreAdapter.Move()); return(true); } }
public DxCoreDeviceFactory(DeviceType types = DeviceType.GraphicsAndCompute) { using UniqueComPtr <IDXCoreAdapterFactory> factory = default; using UniqueComPtr <IDXCoreAdapterList> list = default; Guard.ThrowIfFailed(DXCoreCreateAdapterFactory(factory.Iid, (void **)&factory)); const int MaxNumFilterAttributes = 2; Guid * filterAttributes = stackalloc Guid[MaxNumFilterAttributes]; uint i = 0; if (types.HasFlag(DeviceType.ComputeOnly)) { filterAttributes[i++] = DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE; } if (types.HasFlag(DeviceType.GraphicsAndCompute)) { filterAttributes[i++] = DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS; } Guard.ThrowIfFailed(factory.Ptr->CreateAdapterList(i, filterAttributes, list.Iid, (void **)&list)); _factory = factory.Move(); _list = list.Move(); }
internal IndirectCommand(UniqueComPtr <ID3D12CommandSignature> value, RootSignature?rootSignature, uint commandSizeInBytes, ReadOnlyMemory <IndirectArgument> indirectArguments) { _value = value; RootSignature = rootSignature; CommandSizeInBytes = commandSizeInBytes; IndirectArguments = indirectArguments; }
/// <summary> /// Create a new instance of <see cref="Adapter"/> /// </summary> internal unsafe Adapter( UniqueComPtr <IUnknown> adapter, string description, AdapterVendor vendorId, uint deviceId, uint subSysId, uint revision, ulong dedicatedVideoMemory, ulong dedicatedSystemMemory, ulong sharedSystemMemory, LUID adapterLuid, ulong driverVersion, bool isSoftware, DeviceType type ) { _adapter = adapter; Description = description; VendorId = vendorId; DeviceId = deviceId; SubSysId = subSysId; Revision = revision; DedicatedVideoMemory = dedicatedVideoMemory; DedicatedSystemMemory = dedicatedSystemMemory; SharedSystemMemory = sharedSystemMemory; AdapterLuid = adapterLuid.LowPart | ((uint)adapterLuid.HighPart << 32); DriverVersion = driverVersion; IsSoftware = isSoftware; Type = type; }
internal override bool TryGetAdapterByIndex(uint index, out Adapter adapter) { // We only set this to true in TryOrderByPreference which checks we have IDXGIFactory6 so we can hard cast _factory if (_enumByPreference) { while (true) { using UniqueComPtr <IDXGIAdapter1> dxgiAdapter = default; Guard.ThrowIfFailed( _factory.Ptr->EnumAdapterByGpuPreference( index + _skipAdapterOffset, // DXGI preference doesn't allow preferring hardware/software adapters, so we do that manually after filtering out the other hardware types // We remove the hardware and software flag so DXGI doesn't complain (DXGI_GPU_PREFERENCE)(_preference & ~(DevicePreference.Hardware | DevicePreference.Software)), dxgiAdapter.Iid, (void **)&dxgiAdapter ) ); // null adapter means we have reached end of list if (!dxgiAdapter.Exists) { adapter = default; return(false); } // if it only supports hardware of software, we have to filter them out. If both or neither are set, we allow all adapters through if (_preference.HasFlag(DevicePreference.Hardware) != _preference.HasFlag(DevicePreference.Software)) { DXGI_ADAPTER_DESC1 desc; Guard.ThrowIfFailed(dxgiAdapter.Ptr->GetDesc1(&desc)); bool isHardware = (desc.Flags & (int)DXGI_ADAPTER_FLAG.DXGI_ADAPTER_FLAG_SOFTWARE) == 0; // If they want hardware but we don't have it, or they want software and we don't have it, skip this adapter if (_preference.HasFlag(DevicePreference.Hardware) != isHardware) { _skipAdapterOffset++; continue; } } adapter = CreateAdapter(dxgiAdapter.Move()); return(true); } } else { using UniqueComPtr <IDXGIAdapter1> dxgiAdapter = default; Guard.ThrowIfFailed(_factory.Ptr->EnumAdapters1(index, ComPtr.GetAddressOf(&dxgiAdapter))); adapter = CreateAdapter(dxgiAdapter.Move()); return(true); } }
/// <summary> /// Try and cast <typeparamref name="T"/> to <typeparamref name="TInterface"/> /// </summary> /// <param name="ptr"></param> /// <param name="result">A <see cref="UniqueComPtr{T}"/> that encapsulates the casted pointer, if succeeded</param> /// <typeparam name="T">The type of the underlying COM object</typeparam> /// <typeparam name="TInterface">The type to cast to</typeparam> /// <returns><code>true</code> if the cast succeeded, else <code>false</code></returns> public static bool TryQueryInterface <T, TInterface>(T *ptr, out TInterface *result) where T : unmanaged where TInterface : unmanaged { var success = new UniqueComPtr <T>(ptr).TryQueryInterface <TInterface>(out var comPtr); result = comPtr.Ptr; return(success); }
internal SwapChainOutput(GraphicsDevice device, Size size, IOutputOwner owner, OutputConfiguration desc) : base(device, desc) { _device = device; var swapChainDesc = CreateDesc(desc, size); if (UseSeperatePresentQueue()) { _presentQueue = new CommandQueue(device, ExecutionContext.Graphics, enableTdr: true); _presentQueueIsSeperate = true; } else { _presentQueue = device.GraphicsQueue; } using var factory = CreateFactory(); using UniqueComPtr <IDXGISwapChain1> swapChain = default; var pQueue = (IUnknown *)_presentQueue.GetQueue(); var ppChain = (IDXGISwapChain1 **)&swapChain; IDXGIOutput *pRestrict = null; Guard.ThrowIfFailed( owner.Type switch { OutputType.Hwnd => factory.Ptr->CreateSwapChainForHwnd( pQueue, owner.GetOutput(), &swapChainDesc, null, pRestrict, ppChain ), OutputType.ICoreWindow => factory.Ptr->CreateSwapChainForCoreWindow( pQueue, (IUnknown *)owner.GetOutput(), &swapChainDesc, pRestrict, ppChain ), OutputType.SwapChainPanel => factory.Ptr->CreateSwapChainForComposition( pQueue, &swapChainDesc, pRestrict, ppChain ), _ => E_INVALIDARG, // this way we fail if weird enum arg provided }
public static UniqueComPtr <TUp> UpCast <T, TUp>(UniqueComPtr <T> comPtr) where T : unmanaged where TUp : unmanaged { // if this is hit, your cast is invalid. either use TryQueryInterface or, preferrably, have a valid type #if DEBUG Debug.Assert(comPtr.TryQueryInterface(out UniqueComPtr <TUp> assertion)); assertion.Dispose(); #endif return(new UniqueComPtr <TUp>((TUp *)comPtr.Ptr)); }
public DxgiDeviceFactory() { using UniqueComPtr <IDXGIFactory6> factory = default; Guard.ThrowIfFailed(CreateDXGIFactory2(0, factory.Iid, (void **)&factory)); _factory = factory.Move(); _softwareAdapter = new(() => { using UniqueComPtr <IDXGIAdapter1> adapter = default; Guard.ThrowIfFailed(_factory.Ptr->EnumWarpAdapter(adapter.Iid, (void **)&adapter)); return(CreateAdapter(adapter.Move())); }); }
protected override UniqueComPtr <ID3D12CommandAllocator> Create(ExecutionContext context) { using UniqueComPtr <ID3D12CommandAllocator> allocator = default; _device.ThrowIfFailed(_device.DevicePointer->CreateCommandAllocator( (D3D12_COMMAND_LIST_TYPE)context, allocator.Iid, (void **)&allocator )); LogHelper.LogDebug($"New command allocator allocated (this is the #{_allocatorCount++} allocator)"); DebugHelpers.SetName(allocator.Ptr, $"Pooled allocator #{_allocatorCount}"); return(allocator.Move()); }
internal GpuResource( ComputeDevice device, UniqueComPtr <ID3D12Resource> resource, InternalAllocDesc *desc, ComputeAllocator?allocator, int heapIndex = -1 /* no relevant heap block */, HeapBlock block = default ) { _device = device; _value = resource.Move(); Desc = *desc; HeapIndex = heapIndex; Block = block; _allocator = allocator; }
public ContextParams( ComputeDevice device, UniqueComPtr <ID3D12GraphicsCommandList6> list, UniqueComPtr <ID3D12CommandAllocator> allocator, PipelineStateObject?pipelineStateObject, ExecutionContext context, ContextFlags flags ) { Device = device; List = list; Allocator = allocator; PipelineStateObject = pipelineStateObject; Context = context; Flags = flags; }
private protected static UniqueComPtr <IDXGIFactory2> CreateFactory() { using UniqueComPtr <IDXGIFactory2> factory = default; int hr = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, factory.Iid, (void **)&factory); if (hr == E_NOINTERFACE) { // we don't actually *need* IDXGIFactory2, we just need to do CreateSwapChain (rather than CreateSwapChainForHwnd etc) without it which is currently not implemented ThrowHelper.ThrowPlatformNotSupportedException("Platform does not support IDXGIFactory2, which is required"); } Guard.ThrowIfFailed(hr, "CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, factory.Iid, (void**)&factory)"); return(factory.Move()); }
/// <summary> /// Creates a new <see cref="RootSignature"/> from a <see cref="CompiledShader"/> /// </summary> /// <param name="device">The <see cref="ComputeDevice"/> used to create the root signature</param> /// <param name="rootSignatureShader"></param> /// <param name="deserialize"></param> /// <returns>A new <see cref="RootSignature"/></returns> internal static RootSignature Create(ComputeDevice device, CompiledShader rootSignatureShader, bool deserialize = false) { fixed(byte *pSignature = rootSignatureShader) { using UniqueComPtr <ID3D12RootSignature> rootSig = device.CreateRootSignature( 0 /* TODO: MULTI-GPU */, pSignature, (uint)rootSignatureShader.Length ); if (deserialize) { RootSignatureDeserializer.DeserializeSignature(device, pSignature, (int)rootSignatureShader.Length); } return(new RootSignature(rootSig.Move(), null, null)); } }
static unsafe ShaderManager() { UniqueComPtr <IDxcCompiler3> compiler = default; UniqueComPtr <IDxcUtils> utils = default; Guid clsid = CLSID_DxcCompiler; Guard.ThrowIfFailed(DxcCreateInstance(&clsid, compiler.Iid, (void **)&compiler)); clsid = CLSID_DxcLibrary; Guard.ThrowIfFailed(DxcCreateInstance(&clsid, utils.Iid, (void **)&utils)); Compiler = compiler.Move(); Utils = utils.Move(); DefaultDxcIncludeHandler = new DxcIncludeHandler(); DefaultDxcIncludeHandler.Init(Utils.Copy()); DefaultFxcIncludeHandler = new LegacyFxcIncludeHandler(); DefaultFxcIncludeHandler.Init(); }
protected override UniqueComPtr <ID3D12GraphicsCommandList> Create(ListCreationParams state) { using UniqueComPtr <ID3D12GraphicsCommandList> list = default; _device.ThrowIfFailed(_device.DevicePointer->CreateCommandList( 0, // TODO: MULTI-GPU state.Type, state.Allocator, state.Pso, list.Iid, (void **)&list )); LogHelper.LogDebug($"New command list allocated (this is the #{_listCount++} list)"); DebugHelpers.SetName(list.Ptr, $"Pooled list #{_listCount}"); // 'ManageRent' expects closed list _device.ThrowIfFailed(list.Ptr->Close()); return(list.Move()); }
internal QueryHeap(ComputeDevice device, QueryHeapType type, int numQueries) { _device = device; _nextQuery = 0; if (type == QueryHeapType.CopyTimestamp && _device.QueryFeatureSupport <D3D12_FEATURE_DATA_D3D12_OPTIONS3>(D3D12_FEATURE.D3D12_FEATURE_D3D12_OPTIONS3).CopyQueueTimestampQueriesSupported != TRUE) { ThrowHelper.ThrowNotSupportedException("Device does not support copy queue timestamps"); } var desc = new D3D12_QUERY_HEAP_DESC { Count = (uint)numQueries, Type = (D3D12_QUERY_HEAP_TYPE)type, NodeMask = 0, // TODO: MULTI-GPU }; _queryHeap = device.CreateQueryHeap(desc); _numQueries = (uint)numQueries; }
public unsafe Win7Output(GraphicsDevice device, IntPtr hwnd, OutputConfiguration desc) : base(device, desc) { _allocator = device.CreateAllocator(ExecutionContext.Graphics); _presentContext = device.CreateList(ExecutionContext.Graphics, _allocator.Ptr, null).As <ID3D12GraphicsCommandList>(); _presentFlags = desc.SyncInterval > 0 ? D3D12_DOWNLEVEL_PRESENT_FLAGS.D3D12_DOWNLEVEL_PRESENT_FLAG_WAIT_FOR_VBLANK : 0; _hwnd = hwnd; _presentQueue = device.GraphicsQueue; if (!ComPtr.TryQueryInterface(_presentQueue.GetQueue(), out ID3D12CommandQueueDownlevel * pDownlevel)) { ThrowHelper.ThrowPlatformNotSupportedException("Not on windows7"); } _queue = new(pDownlevel); RECT window; _ = Windows.GetClientRect(hwnd, &window); InternalResize(new Size(width: window.right - window.left, height: window.bottom - window.top)); }
private static void Reflect(CompiledShader shader) { var buffer = new DxcBuffer { Encoding = 0, Ptr = shader.Pointer, Size = shader.Length }; using UniqueComPtr <ID3D12ShaderReflection> reflection = default; Guard.ThrowIfFailed(Utils.Ptr->CreateReflection(&buffer, reflection.Iid, (void **)&reflection)); D3D12_SHADER_DESC desc; Guard.ThrowIfFailed(reflection.Ptr->GetDesc(&desc)); for (var i = 0u; i < desc.BoundResources; i++) { D3D12_SHADER_INPUT_BIND_DESC bindDesc; Guard.ThrowIfFailed(reflection.Ptr->GetResourceBindingDesc(i, &bindDesc)); } }
internal RaytracingPipelineStateObject(UniqueComPtr <ID3D12StateObject> pso, RaytracingPipelineDesc desc) : base(pso.As <ID3D12Object>()) { Desc = desc; }
internal PipelineStateObject(UniqueComPtr <ID3D12Object> pso) { Pointer = pso.Move(); }
protected override void ManageReturn(ref UniqueComPtr <ID3D12CommandAllocator> state) => _device.ThrowIfFailed(state.Ptr->Reset());
protected override void ManageRent(ref UniqueComPtr <ID3D12GraphicsCommandList> value, ListCreationParams state) { _device.ThrowIfFailed(value.Ptr->Reset(state.Allocator, state.Pso)); }
internal MeshPipelineStateObject(UniqueComPtr <ID3D12PipelineState> pso, in MeshPipelineDesc desc) : base(pso.As <ID3D12Object>())
internal Fence(UniqueComPtr <ID3D12Fence> fence) { _fence = fence.Move(); }
protected override void ManageReturn(ref UniqueComPtr <ID3D12GraphicsCommandList> value) { }
protected override void ManageRent(ref UniqueComPtr <ID3D12CommandAllocator> value, ExecutionContext context) { }