Beispiel #1
0
        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
                       ));
        }
Beispiel #2
0
        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)");
            }
        }
Beispiel #3
0
        /// <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();
                }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        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();
        }
Beispiel #6
0
 internal IndirectCommand(UniqueComPtr <ID3D12CommandSignature> value, RootSignature?rootSignature, uint commandSizeInBytes, ReadOnlyMemory <IndirectArgument> indirectArguments)
 {
     _value             = value;
     RootSignature      = rootSignature;
     CommandSizeInBytes = commandSizeInBytes;
     IndirectArguments  = indirectArguments;
 }
Beispiel #7
0
 /// <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;
 }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #10
0
        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
            }
Beispiel #11
0
        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));
        }
Beispiel #12
0
        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()));
            });
        }
Beispiel #13
0
        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());
        }
Beispiel #14
0
 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;
 }
Beispiel #15
0
 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;
 }
Beispiel #16
0
        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());
        }
Beispiel #17
0
        /// <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));
            }
        }
Beispiel #18
0
        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();
        }
Beispiel #19
0
        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());
        }
Beispiel #20
0
        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;
        }
Beispiel #21
0
        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));
        }
Beispiel #22
0
        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;
 }
Beispiel #24
0
 internal PipelineStateObject(UniqueComPtr <ID3D12Object> pso)
 {
     Pointer = pso.Move();
 }
Beispiel #25
0
 protected override void ManageReturn(ref UniqueComPtr <ID3D12CommandAllocator> state)
 => _device.ThrowIfFailed(state.Ptr->Reset());
Beispiel #26
0
 protected override void ManageRent(ref UniqueComPtr <ID3D12GraphicsCommandList> value, ListCreationParams state)
 {
     _device.ThrowIfFailed(value.Ptr->Reset(state.Allocator, state.Pso));
 }
Beispiel #27
0
 internal MeshPipelineStateObject(UniqueComPtr <ID3D12PipelineState> pso, in MeshPipelineDesc desc) : base(pso.As <ID3D12Object>())
Beispiel #28
0
 internal Fence(UniqueComPtr <ID3D12Fence> fence)
 {
     _fence = fence.Move();
 }
Beispiel #29
0
 protected override void ManageReturn(ref UniqueComPtr <ID3D12GraphicsCommandList> value)
 {
 }
Beispiel #30
0
 protected override void ManageRent(ref UniqueComPtr <ID3D12CommandAllocator> value, ExecutionContext context)
 {
 }