Skip to content

Commit

Permalink
#5 - Cleanup Games and implement WIP SDL2 and Windows (Forms) applica…
Browse files Browse the repository at this point in the history
…tion.
  • Loading branch information
amerkoleci committed Nov 2, 2021
1 parent 975e71f commit d13c50e
Show file tree
Hide file tree
Showing 27 changed files with 278 additions and 195 deletions.
14 changes: 8 additions & 6 deletions Vortice.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice", "src\Vortice\Vort
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice.Games", "src\Vortice.Games\Vortice.Games.csproj", "{C6CEA688-2A93-4E16-9CCF-62EC48F91589}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{32D5F8C0-9BC8-4231-AA60-50C7310BFE4B}"
ProjectSection(SolutionItems) = preProject
src\targets\Vortice.MultiTargeting.targets = src\targets\Vortice.MultiTargeting.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D8EC0278-B4F9-4EF5-A4BE-FE2284C6ECED}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Graphics", "Graphics", "{4E0EA7FF-529D-4F30-977E-A5C7F3D83835}"
Expand All @@ -49,10 +44,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice.Audio.XAudio2", "sr
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{6F4EDC2F-EFFA-45BD-8C4F-76D52CD41A1C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice.WPF", "src\Platforms\Vortice.WPF\Vortice.WPF.csproj", "{FD2D8DBB-FD8B-4DA0-A251-3C88AF1CE9F7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice.Windows", "src\Platforms\Vortice.Windows\Vortice.Windows.csproj", "{FD2D8DBB-FD8B-4DA0-A251-3C88AF1CE9F7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vortice.SDL2", "src\Platforms\Vortice.SDL2\Vortice.SDL2.csproj", "{E7888A66-50C2-427D-9B47-5A924EB3A1DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrawTriangle.SDL2", "src\samples\Graphics\DrawTriangle.SDL2\DrawTriangle.SDL2.csproj", "{75D7E79F-6D04-431B-A268-7BB61925B75B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -103,6 +100,10 @@ Global
{E7888A66-50C2-427D-9B47-5A924EB3A1DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7888A66-50C2-427D-9B47-5A924EB3A1DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7888A66-50C2-427D-9B47-5A924EB3A1DB}.Release|Any CPU.Build.0 = Release|Any CPU
{75D7E79F-6D04-431B-A268-7BB61925B75B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75D7E79F-6D04-431B-A268-7BB61925B75B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75D7E79F-6D04-431B-A268-7BB61925B75B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75D7E79F-6D04-431B-A268-7BB61925B75B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -117,6 +118,7 @@ Global
{43FB232A-784D-4BE7-916C-022D7CAD8C7E} = {F0193F7C-734B-48E9-BDA2-5ECD97AC37EC}
{FD2D8DBB-FD8B-4DA0-A251-3C88AF1CE9F7} = {6F4EDC2F-EFFA-45BD-8C4F-76D52CD41A1C}
{E7888A66-50C2-427D-9B47-5A924EB3A1DB} = {6F4EDC2F-EFFA-45BD-8C4F-76D52CD41A1C}
{75D7E79F-6D04-431B-A268-7BB61925B75B} = {4E0EA7FF-529D-4F30-977E-A5C7F3D83835}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85020CE7-9EF6-4502-94F6-98643E762B78}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Vortice.Audio</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down
13 changes: 11 additions & 2 deletions src/Graphics/Vortice.Graphics/D3D12/D3D12GraphicsDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ internal D3D12GraphicsDevice(D3D12GraphicsAdapter adapter, string? name = null)
_queues[(int)CommandQueueType.Compute] = new D3D12Queue(this, CommandQueueType.Compute);

// Init capabilites.
var featureDataOptions1 = NativeDevice->CheckFeatureSupport<D3D12_FEATURE_DATA_D3D12_OPTIONS1>(D3D12_FEATURE_D3D12_OPTIONS1);
var featureDataOptions5 = NativeDevice->CheckFeatureSupport<D3D12_FEATURE_DATA_D3D12_OPTIONS5>(D3D12_FEATURE_D3D12_OPTIONS5);
D3D12_FEATURE_DATA_D3D12_OPTIONS1 featureDataOptions1 = NativeDevice->CheckFeatureSupport<D3D12_FEATURE_DATA_D3D12_OPTIONS1>(D3D12_FEATURE_D3D12_OPTIONS1);
D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureDataOptions5 = NativeDevice->CheckFeatureSupport<D3D12_FEATURE_DATA_D3D12_OPTIONS5>(D3D12_FEATURE_D3D12_OPTIONS5);

SupportsRenderPass = false;
if (featureDataOptions5.RenderPassesTier > D3D12_RENDER_PASS_TIER_0
Expand Down Expand Up @@ -191,6 +191,15 @@ protected override void Dispose(bool disposing)
}
}

/// <inheritdoc />
public override void WaitIdle()
{
for (int i = 0; i < (int)CommandQueueType.Count; i++)
{
_queues[i]?.WaitIdle();
}
}

/// <inheritdoc />
protected override SwapChain CreateSwapChainCore(in GraphicsSurface surface, in SwapChainDescriptor descriptor) => new D3D12SwapChain(this, surface, descriptor);

Expand Down
56 changes: 56 additions & 0 deletions src/Graphics/Vortice.Graphics/D3D12/D3D12Queue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@
using static Vortice.Graphics.D3D12.D3D12Utils;
using static TerraFX.Interop.D3D12_COMMAND_QUEUE_FLAGS;
using static TerraFX.Interop.D3D12_COMMAND_QUEUE_PRIORITY;
using static TerraFX.Interop.D3D12_FENCE_FLAGS;
using System;

namespace Vortice.Graphics.D3D12
{
internal unsafe class D3D12Queue
{
private readonly ComPtr<ID3D12CommandQueue> _handle;
private readonly ComPtr<ID3D12Fence> _fence;
private readonly HANDLE _fenceEventHandle;
private ulong _nextFenceValue = 0;
private ulong _lastCompletedFenceValue = 0;

public D3D12Queue(D3D12GraphicsDevice device, CommandQueueType type)
{
Expand All @@ -27,14 +33,64 @@ public D3D12Queue(D3D12GraphicsDevice device, CommandQueueType type)
_handle.GetVoidAddressOf()).Assert();

_handle.Get()->SetName($"{type} Command Queue");

device.NativeDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof<ID3D12Fence>(), _fence.GetVoidAddressOf()).Assert();
_fenceEventHandle = CreateEventExW(lpEventAttributes: null, lpName: null, dwFlags: 0, dwDesiredAccess: EVENT_MODIFY_STATE | SYNCHRONIZE);
if (_fenceEventHandle == HANDLE.NULL)
{
//ThrowForLastError(nameof(CreateEventW));
}
}

public ID3D12CommandQueue* Handle => _handle;

/// <inheritdoc />
public void Dispose()
{
CloseHandle(_fenceEventHandle);
_fence.Dispose();
_handle.Dispose();
}

public ulong Signal()
{
//std::lock_guard<std::mutex> LockGuard(m_FenceMutex);
_handle.Get()->Signal(_fence.Get(), _nextFenceValue);
return _nextFenceValue++;
}

public void WaitForFence(ulong fenceValue)
{
if (IsFenceComplete(fenceValue))
{
return;
}

{
//std::lock_guard<std::mutex> LockGuard(m_EventMutex);

_fence.Get()->SetEventOnCompletion(fenceValue, _fenceEventHandle);
WaitForSingleObject(_fenceEventHandle, INFINITE);
_lastCompletedFenceValue = fenceValue;
}
}

public void WaitIdle()
{
WaitForFence(Signal());
}

public bool IsFenceComplete(ulong fenceValue)
{
// Avoid querying the fence value by testing against the last one seen.
// The max() is to protect against an unlikely race condition that could cause the last
// completed fence value to regress.
if (fenceValue > _lastCompletedFenceValue)
{
_lastCompletedFenceValue = Math.Max(_lastCompletedFenceValue, _fence.Get()->GetCompletedValue());
}

return fenceValue <= _lastCompletedFenceValue;
}
}
}
5 changes: 5 additions & 0 deletions src/Graphics/Vortice.Graphics/GraphicsDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public void Dispose()
/// </param>
protected abstract void Dispose(bool disposing);

/// <summary>
/// Wait for device to finish pending GPU operations.
/// </summary>
public abstract void WaitIdle();

public SwapChain CreateSwapChain(in GraphicsSurface surface, in SwapChainDescriptor descriptor)
{
Guard.IsNotNull(surface, nameof(surface));
Expand Down
71 changes: 71 additions & 0 deletions src/Platforms/Vortice.SDL2/SDL2GameContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.

using System;
using Microsoft.Extensions.DependencyInjection;
using static SDL2.SDL;
using static SDL2.SDL.SDL_EventType;

namespace Vortice
{
public sealed class SDL2GameContext : GameContext
{
private const int _eventsPerPeep = 64;
private readonly SDL_Event[] _events = new SDL_Event[_eventsPerPeep];

private bool _exiting = false;

public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);

// Init SDL2
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0)
{
SDL_Log($"Unable to initialize SDL: {SDL_GetError()}");
return;
}

services.AddSingleton<GameView>(new SDL2GameView());
}

public override void RunMainLoop(Action init, Action callback)
{
init();

while (!_exiting)
{
PollSDLEvents();
callback();
}

SDL_Quit();
}

private void PollSDLEvents()
{
SDL_PumpEvents();
int eventsRead;

do
{
eventsRead = SDL_PeepEvents(_events, _eventsPerPeep, SDL_eventaction.SDL_GETEVENT, SDL_EventType.SDL_FIRSTEVENT, SDL_EventType.SDL_LASTEVENT);
for (int i = 0; i < eventsRead; i++)
{
handleSDLEvent(_events[i]);
}
} while (eventsRead == _eventsPerPeep);
}

private void handleSDLEvent(SDL_Event e)
{
switch (e.type)
{
case SDL_QUIT:
case SDL_APP_TERMINATING:
_exiting = true;
break;
}
}
}
}
81 changes: 81 additions & 0 deletions src/Platforms/Vortice.SDL2/SDL2GameView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Amer Koleci and contributors.
// Distributed under the MIT license. See the LICENSE file in the project root for more information.

using System;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Vortice.Graphics;
using static SDL2.SDL;
using static SDL2.SDL.SDL_WindowFlags;

namespace Vortice
{
internal class SDL2GameView : GameView
{
private readonly IntPtr _window;

public SDL2GameView()
{
SDL_WindowFlags flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;

_window = SDL_CreateWindow("Vortice", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1200, 800, flags);

SDL_GetWindowSize(_window, out int width, out int height);
ClientSize = new Size(width, height);

// Native handle
var wmInfo = new SDL_SysWMinfo();
SDL_GetWindowWMInfo(_window, ref wmInfo);

// Window handle is selected per subsystem as defined at:
// https://wiki.libsdl.org/SDL_SysWMinfo
switch (wmInfo.subsystem)
{
case SDL_SYSWM_TYPE.SDL_SYSWM_WINDOWS:
Source = SurfaceSource.CreateWin32(
wmInfo.info.win.hinstance,
wmInfo.info.win.window
);
break;

case SDL_SYSWM_TYPE.SDL_SYSWM_X11:
//return wmInfo.info.x11.window;
break;

case SDL_SYSWM_TYPE.SDL_SYSWM_COCOA:
//return wmInfo.info.cocoa.window;
break;

case SDL_SYSWM_TYPE.SDL_SYSWM_UIKIT:
//return wmInfo.info.uikit.window;
break;

case SDL_SYSWM_TYPE.SDL_SYSWM_WAYLAND:
//return wmInfo.info.wl.shell_surface;
break;

case SDL_SYSWM_TYPE.SDL_SYSWM_ANDROID:
//return wmInfo.info.android.window;
break;

default:
break;
}

SDL_ShowWindow(_window);
}

/// <inheritdoc />
public override Size ClientSize { get; }

/// <inheritdoc />
public override SurfaceSource Source { get; }

private void OnControlClientSizeChanged(object? sender, EventArgs e)
{
OnSizeChanged();
}
}
}
1 change: 1 addition & 0 deletions src/Platforms/Vortice.SDL2/Vortice.SDL2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Vortice</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down
10 changes: 6 additions & 4 deletions src/Vortice.Games/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Vortice
public abstract class Game : IGame, IDisposable
{
private readonly GameContext _context;
private readonly GamePlatform _platform;
//private readonly GamePlatform _platform;
private readonly ServiceProvider _serviceProvider;
private readonly object _tickLock = new();
private readonly Stopwatch _stopwatch = new();
Expand All @@ -23,9 +23,9 @@ public abstract class Game : IGame, IDisposable
protected Game(GameContext context)
{
_context = context;
_platform = GamePlatform.Create(this);
_platform.Activated += GamePlatform_Activated;
_platform.Deactivated += GamePlatform_Deactivated;
//_platform = GamePlatform.Create(this);
//_platform.Activated += GamePlatform_Activated;
//_platform.Deactivated += GamePlatform_Deactivated;

ServiceCollection services = new();
context.ConfigureServices(services);
Expand Down Expand Up @@ -90,6 +90,8 @@ protected virtual void Dispose(bool dispose)
{
if (dispose && !IsDisposed)
{
GraphicsDevice.WaitIdle();

View.SwapChain?.Dispose();
GraphicsDevice.Dispose();
GraphicsDeviceFactory.Dispose();
Expand Down
8 changes: 0 additions & 8 deletions src/Vortice.Games/Platform/Standard/AppContext.Standard.cs

This file was deleted.

21 changes: 0 additions & 21 deletions src/Vortice.Games/Platform/Standard/SDL2GamePlatform.cs

This file was deleted.

Loading

0 comments on commit d13c50e

Please sign in to comment.