Beispiel #1
0
        public void ResourceFromTexture3D(Device device, Type bufferType)
        {
            using Texture3D <float> buffer = device.Get().AllocateTexture3D <float>(bufferType, 16, 16, 4);

            using ComPtr <ID3D12Resource> d3D12Resource = default;

            InteropServices.GetID3D12Resource(buffer, FX.__uuidof <ID3D12Resource>(), (void **)d3D12Resource.GetAddressOf());

            Assert.IsTrue(d3D12Resource.Get() != null);
            Assert.AreEqual(d3D12Resource.Get()->GetDesc().Dimension, D3D12_RESOURCE_DIMENSION_TEXTURE3D);

            d3D12Resource.Dispose();

            int hResult = InteropServices.TryGetID3D12Resource(buffer, FX.__uuidof <ID3D12Resource>(), (void **)d3D12Resource.GetAddressOf());

            Assert.AreEqual(hResult, FX.S_OK);
            Assert.IsTrue(d3D12Resource.Get() != null);
            Assert.AreEqual(d3D12Resource.Get()->GetDesc().Dimension, D3D12_RESOURCE_DIMENSION_TEXTURE3D);
        }
        /// <summary>
        /// Applies the actual resize logic that was scheduled from <see cref="OnResize"/>.
        /// </summary>
        private unsafe void ApplyResize()
        {
            this.d3D12CommandQueue.Get()->Signal(this.d3D12Fence.Get(), this.nextD3D12FenceValue);

            // Wait for the fence again to ensure there are no pending operations
            this.d3D12Fence.Get()->SetEventOnCompletion(this.nextD3D12FenceValue, default);

            this.nextD3D12FenceValue++;

            // Dispose the old buffers before resizing the buffer
            this.d3D12Resource0.Dispose();
            this.d3D12Resource1.Dispose();

            // Resize the swap chain buffers
            this.dxgiSwapChain1.Get()->ResizeBuffers(0, 0, 0, DXGI_FORMAT.DXGI_FORMAT_UNKNOWN, 0);

            // Get the index of the initial back buffer
            using (ComPtr <IDXGISwapChain3> dxgiSwapChain3 = default)
            {
                _ = this.dxgiSwapChain1.CopyTo(dxgiSwapChain3.GetAddressOf());

                this.currentBufferIndex = dxgiSwapChain3.Get()->GetCurrentBackBufferIndex();
            }

            // Retrieve the back buffers for the swap chain
            fixed(ID3D12Resource **d3D12Resource0 = this.d3D12Resource0)
            fixed(ID3D12Resource **d3D12Resource1 = this.d3D12Resource1)
            {
                _ = dxgiSwapChain1.Get()->GetBuffer(0, FX.__uuidof <ID3D12Resource>(), (void **)d3D12Resource0);
                _ = dxgiSwapChain1.Get()->GetBuffer(1, FX.__uuidof <ID3D12Resource>(), (void **)d3D12Resource1);
            }

            this.texture?.Dispose();

            D3D12_RESOURCE_DESC d3D12Resource0Description = this.d3D12Resource0.Get()->GetDesc();

            // Create the 2D texture to use to generate frames to display
            this.texture = Gpu.Default.AllocateReadWriteTexture2D <Rgba32, Float4>(
                (int)d3D12Resource0Description.Width,
                (int)d3D12Resource0Description.Height);
        }
        /// <summary>
        /// Creates a new <see cref="ID3D12InfoQueue"/> for a given device.
        /// </summary>
        /// <param name="d3D12Device">The target <see cref="ID3D12Device"/> to use to create the info queue.</param>
        /// <returns>A pointer to the newly created <see cref="ID3D12InfoQueue"/> instance.</returns>
        /// <exception cref="Exception">Thrown when the creation of the info queue fails.</exception>
        public static ComPtr <ID3D12InfoQueue> CreateInfoQueue(this ref ID3D12Device d3D12Device)
        {
            ComPtr <ID3D12InfoQueue> d3D12InfoQueue = default;

            d3D12Device.QueryInterface(FX.__uuidof <ID3D12InfoQueue>(), d3D12InfoQueue.GetVoidAddressOf()).Assert();

            D3D12_MESSAGE_ID *d3D12MessageIds = stackalloc D3D12_MESSAGE_ID[3]
            {
                D3D12_MESSAGE_ID_CREATEDEVICE_DEBUG_LAYER_STARTUP_OPTIONS,
                D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE,
                D3D12_MESSAGE_ID_UNMAP_INVALID_NULLRANGE
            };

            D3D12_INFO_QUEUE_FILTER d3D12InfoQueueFilter = default;

            d3D12InfoQueueFilter.DenyList.NumIDs  = 3;
            d3D12InfoQueueFilter.DenyList.pIDList = d3D12MessageIds;

            d3D12InfoQueue.Get()->PushRetrievalFilter(&d3D12InfoQueueFilter).Assert();

            return(d3D12InfoQueue.Move());
        }
Beispiel #4
0
        /// <summary>
        /// Creates a new <see cref="ShaderCompiler"/> instance.
        /// </summary>
        private ShaderCompiler()
        {
            lock (this)
            {
                InitializeDxcLibrariesLoading();
            }

            using ComPtr <IDxcCompiler> dxcCompiler             = default;
            using ComPtr <IDxcLibrary> dxcLibrary               = default;
            using ComPtr <IDxcIncludeHandler> dxcIncludeHandler = default;

            Guid dxcCompilerCLGuid = FX.CLSID_DxcCompiler;
            Guid dxcLibraryCLGuid  = FX.CLSID_DxcLibrary;

            FX.DxcCreateInstance(&dxcCompilerCLGuid, FX.__uuidof <IDxcCompiler>(), dxcCompiler.GetVoidAddressOf()).Assert();
            FX.DxcCreateInstance(&dxcLibraryCLGuid, FX.__uuidof <IDxcLibrary>(), dxcLibrary.GetVoidAddressOf()).Assert();

            dxcLibrary.Get()->CreateIncludeHandler(dxcIncludeHandler.GetAddressOf()).Assert();

            DxcCompiler       = dxcCompiler.Move();
            DxcLibrary        = dxcLibrary.Move();
            DxcIncludeHandler = dxcIncludeHandler.Move();
        }
Beispiel #5
0
        public void GetDevice(Device device)
        {
            using ComPtr <ID3D12Device> d3D12Device = default;

            InteropServices.GetID3D12Device(device.Get(), FX.__uuidof <ID3D12Device>(), (void **)d3D12Device.GetAddressOf());

            Assert.IsTrue(d3D12Device.Get() != null);

            LUID luid = d3D12Device.Get()->GetAdapterLuid();

            Assert.IsTrue(*(ulong *)&luid != 0);

            d3D12Device.Dispose();

            int hResult = InteropServices.TryGetID3D12Device(device.Get(), FX.__uuidof <ID3D12Device>(), (void **)d3D12Device.GetAddressOf());

            Assert.AreEqual(hResult, FX.S_OK);
            Assert.IsTrue(d3D12Device.Get() != null);

            luid = d3D12Device.Get()->GetAdapterLuid();

            Assert.IsTrue(*(ulong *)&luid != 0);
        }
Beispiel #6
0
        /// <summary>
        /// Tries to check or create a warp <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 warp device was created successfully.</returns>
        private static unsafe bool TryGetWarpDevice(ID3D12Device **d3D12Device, IDXGIAdapter **dxgiAdapter, DXGI_ADAPTER_DESC1 *dxgiDescription1)
        {
            using ComPtr <IDXGIFactory4> dxgiFactory4 = default;

            EnableDebugMode();

            FX.CreateDXGIFactory2(IDXGIFactoryCreationFlags, FX.__uuidof <IDXGIFactory4>(), dxgiFactory4.GetVoidAddressOf()).Assert();

            using ComPtr <IDXGIAdapter1> dxgiAdapter1 = default;

            dxgiFactory4.Get()->EnumWarpAdapter(FX.__uuidof <IDXGIAdapter1>(), dxgiAdapter1.GetVoidAddressOf()).Assert();

            dxgiAdapter1.Get()->GetDesc1(dxgiDescription1).Assert();

            HRESULT createDeviceResult = FX.D3D12CreateDevice(
                dxgiAdapter1.AsIUnknown().Get(),
                D3D_FEATURE_LEVEL_11_0,
                FX.__uuidof <ID3D12Device>(),
                (void **)d3D12Device);

            dxgiAdapter1.CopyTo(dxgiAdapter);

            return(FX.SUCCEEDED(createDeviceResult));
        }
        /// <inheritdoc/>
        public override unsafe void OnInitialize(HWND hwnd)
        {
            // Get the underlying ID3D12Device in use
            fixed(ID3D12Device **d3D12Device = this.d3D12Device)
            {
                _ = InteropServices.TryGetID3D12Device(Gpu.Default, FX.__uuidof <ID3D12Device>(), (void **)d3D12Device);
            }

            // Create the direct command queue to use
            fixed(ID3D12CommandQueue **d3D12CommandQueue = this.d3D12CommandQueue)
            {
                D3D12_COMMAND_QUEUE_DESC d3D12CommandQueueDesc;

                d3D12CommandQueueDesc.Type     = D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT;
                d3D12CommandQueueDesc.Priority = (int)D3D12_COMMAND_QUEUE_PRIORITY.D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
                d3D12CommandQueueDesc.Flags    = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE;
                d3D12CommandQueueDesc.NodeMask = 0;

                _ = d3D12Device.Get()->CreateCommandQueue(
                    &d3D12CommandQueueDesc,
                    FX.__uuidof <ID3D12CommandQueue>(),
                    (void **)d3D12CommandQueue);
            }

            // Create the direct fence
            fixed(ID3D12Fence **d3D12Fence = this.d3D12Fence)
            {
                _ = this.d3D12Device.Get()->CreateFence(
                    0,
                    D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE,
                    FX.__uuidof <ID3D12Fence>(),
                    (void **)d3D12Fence);
            }

            // Create the swap chain to display frames
            fixed(IDXGISwapChain1 **dxgiSwapChain1 = this.dxgiSwapChain1)
            {
                using ComPtr <IDXGIFactory2> dxgiFactory2 = default;

                _ = FX.CreateDXGIFactory2(FX.DXGI_CREATE_FACTORY_DEBUG, FX.__uuidof <IDXGIFactory2>(), (void **)dxgiFactory2.GetAddressOf());

                DXGI_SWAP_CHAIN_DESC1 dxgiSwapChainDesc1 = default;

                dxgiSwapChainDesc1.AlphaMode   = DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE;
                dxgiSwapChainDesc1.BufferCount = 2;
                dxgiSwapChainDesc1.Flags       = 0;
                dxgiSwapChainDesc1.Format      = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
                dxgiSwapChainDesc1.Width       = 0;
                dxgiSwapChainDesc1.Height      = 0;
                dxgiSwapChainDesc1.SampleDesc  = new DXGI_SAMPLE_DESC(count: 1, quality: 0);
                dxgiSwapChainDesc1.Scaling     = DXGI_SCALING.DXGI_SCALING_STRETCH;
                dxgiSwapChainDesc1.Stereo      = 0;
                dxgiSwapChainDesc1.SwapEffect  = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;

                _ = dxgiFactory2.Get()->CreateSwapChainForHwnd(
                    (IUnknown *)d3D12CommandQueue.Get(),
                    hwnd,
                    &dxgiSwapChainDesc1,
                    null,
                    null,
                    dxgiSwapChain1);
            }

            // Create the command allocator to use
            fixed(ID3D12CommandAllocator **d3D12CommandAllocator = this.d3D12CommandAllocator)
            {
                this.d3D12Device.Get()->CreateCommandAllocator(
                    D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                    FX.__uuidof <ID3D12CommandAllocator>(),
                    (void **)d3D12CommandAllocator);
            }

            // Create the reusable command list to copy data to the back buffers
            fixed(ID3D12GraphicsCommandList **d3D12GraphicsCommandList = this.d3D12GraphicsCommandList)
            {
                this.d3D12Device.Get()->CreateCommandList(
                    0,
                    D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
                    d3D12CommandAllocator,
                    null,
                    FX.__uuidof <ID3D12GraphicsCommandList>(),
                    (void **)d3D12GraphicsCommandList);
            }

            // Close the command list to prepare it for future use
            this.d3D12GraphicsCommandList.Get()->Close();
        }
        /// <inheritdoc/>
        public override unsafe void OnUpdate(TimeSpan time)
        {
            if (this.isResizePending)
            {
                ApplyResize();

                this.isResizePending = false;
            }

            // Generate the new frame
            Gpu.Default.For(this.texture !.Width, this.texture.Height, this.shaderFactory(this.texture, time));

            using ComPtr <ID3D12Resource> d3D12Resource = default;

            // Get the underlying ID3D12Resource pointer for the texture
            _ = InteropServices.TryGetID3D12Resource(this.texture, FX.__uuidof <ID3D12Resource>(), (void **)d3D12Resource.GetAddressOf());

            // Get the target back buffer to update
            ID3D12Resource *d3D12ResourceBackBuffer = this.currentBufferIndex switch
            {
                0 => this.d3D12Resource0.Get(),
                1 => this.d3D12Resource1.Get(),
                _ => null
            };

            this.currentBufferIndex ^= 1;

            // Reset the command list and command allocator
            this.d3D12CommandAllocator.Get()->Reset();
            this.d3D12GraphicsCommandList.Get()->Reset(this.d3D12CommandAllocator.Get(), null);

            D3D12_RESOURCE_BARRIER *d3D12ResourceBarriers = stackalloc D3D12_RESOURCE_BARRIER[]
            {
                D3D12_RESOURCE_BARRIER.InitTransition(
                    d3D12Resource.Get(),
                    D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
                    D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE),
                D3D12_RESOURCE_BARRIER.InitTransition(
                    d3D12ResourceBackBuffer,
                    D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON,
                    D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST)
            };

            // Transition the resources to COPY_DEST and COPY_SOURCE respectively
            d3D12GraphicsCommandList.Get()->ResourceBarrier(2, d3D12ResourceBarriers);

            // Copy the generated frame to the target back buffer
            d3D12GraphicsCommandList.Get()->CopyResource(d3D12ResourceBackBuffer, d3D12Resource.Get());

            d3D12ResourceBarriers[0] = D3D12_RESOURCE_BARRIER.InitTransition(
                d3D12Resource.Get(),
                D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE,
                D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS);

            d3D12ResourceBarriers[1] = D3D12_RESOURCE_BARRIER.InitTransition(
                d3D12ResourceBackBuffer,
                D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
                D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON);

            // Transition the resources back to COMMON and UNORDERED_ACCESS respectively
            d3D12GraphicsCommandList.Get()->ResourceBarrier(2, d3D12ResourceBarriers);

            d3D12GraphicsCommandList.Get()->Close();

            // Execute the command list to perform the copy
            this.d3D12CommandQueue.Get()->ExecuteCommandLists(1, (ID3D12CommandList **)d3D12GraphicsCommandList.GetAddressOf());
            this.d3D12CommandQueue.Get()->Signal(this.d3D12Fence.Get(), this.nextD3D12FenceValue);

            // Present the new frame
            this.dxgiSwapChain1.Get()->Present(0, 0);

            if (this.nextD3D12FenceValue > this.d3D12Fence.Get()->GetCompletedValue())
            {
                this.d3D12Fence.Get()->SetEventOnCompletion(this.nextD3D12FenceValue, default);
            }

            this.nextD3D12FenceValue++;
        }
    }
}
Beispiel #9
0
        /// <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);
                    }
                }
            }
        }
Beispiel #10
0
                /// <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);
                                }
                            }
                        }
                    }
                }
Beispiel #11
0
        /// <summary>
        /// Runs a specified application and starts the main loop to update its state.
        /// This is the entry point for a given application of type <typeparamref name="T"/>, and it should be
        /// called as soon as the process is launched, excluding any other additional initialization needed.
        /// <para>To launch an application, simply add this line to the project being used:</para>
        /// <c>Win32ApplicationRunner.Run&lt;MyApplication>();</c>
        /// </summary>
        /// <typeparam name="T">The type of application being launched.</typeparam>
        /// <returns>The exit code for the application.</returns>
        public static int Run(Win32Application application)
        {
            Win32ApplicationRunner.application = application;

            IntPtr hInstance = FX.GetModuleHandleW(null);

            fixed(char *name = Assembly.GetExecutingAssembly().FullName)
            fixed(char *windowTitle = application.GetType().ToString())
            {
                // Initialize the window class
                WNDCLASSEXW windowClassEx = new()
                {
                    cbSize        = (uint)sizeof(WNDCLASSEXW),
                    style         = FX.CS_HREDRAW | FX.CS_VREDRAW,
                    lpfnWndProc   = &WindowProc,
                    hInstance     = hInstance,
                    hCursor       = FX.LoadCursorW(IntPtr.Zero, FX.MAKEINTRESOURCE(32512)),
                    lpszClassName = (ushort *)name
                };

                // Register the window class
                _ = FX.RegisterClassExW(&windowClassEx);

                Rectangle windowRect = new(0, 0, 1280, 720);

                // Set the target window size
                _ = FX.AdjustWindowRect((RECT *)&windowRect, FX.WS_OVERLAPPEDWINDOW, FX.FALSE);

                uint
                    height = (uint)(windowRect.Bottom - windowRect.Top),
                    width  = (uint)(windowRect.Right - windowRect.Left);

                // Create the window and store a handle to it
                hwnd = FX.CreateWindowExW(
                    0,
                    windowClassEx.lpszClassName,
                    (ushort *)windowTitle,
                    FX.WS_OVERLAPPEDWINDOW,
                    FX.CW_USEDEFAULT,
                    FX.CW_USEDEFAULT,
                    (int)width,
                    (int)height,
                    HWND.NULL,
                    HMENU.NULL,
                    hInstance,
                    (void *)GCHandle.ToIntPtr(GCHandle.Alloc(application))
                    );

                MARGINS margins = default;

                margins.cxLeftWidth    = -1;
                margins.cxRightWidth   = -1;
                margins.cyTopHeight    = -1;
                margins.cyBottomHeight = -1;

                _ = FX.DwmExtendFrameIntoClientArea(hwnd, &margins);
            }

            // Initialize the application
            application.OnInitialize(hwnd);

            // Display the window
            _ = FX.ShowWindow(hwnd, FX.SW_SHOWDEFAULT);

            MSG msg = default;

            // Setup the render thread that enables smooth resizing of the window
            renderThread = new Thread(static args =>