Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Skyline.Gpu/WindowSurface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ public void Configure(int pixelWidth, int pixelHeight)
$"Supported: {string.Join(", ", Capabilities.AlphaModes.ToArray())}. Use Auto or a supported mode.");
}

// An unsupported format aborts wgpu the same way, so reject a
// wide-gamut or HDR format the surface cannot present with a managed
// error. Pick one safely with Capabilities.ChooseFormat.
if (!Capabilities.Supports(_options.Format))
{
throw new InvalidOperationException(
$"surface format {_options.Format} is not supported by this surface. " +
$"Supported: {string.Join(", ", Capabilities.Formats.ToArray())}. Use Capabilities.ChooseFormat(...).");
}

var w = Math.Max(1, pixelWidth);
var h = Math.Max(1, pixelHeight);
var config = new SurfaceConfiguration
Expand Down
33 changes: 33 additions & 0 deletions src/Skyline.Gpu/WindowSurfaceCapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ internal WindowSurfaceCapabilities(TextureFormat[] formats, PresentMode[] presen

public ReadOnlySpan<CompositeAlphaMode> AlphaModes => _alphaModes;

public bool Supports(TextureFormat format)
{
foreach (var f in _formats)
{
if (f == format)
{
return true;
}
}

return false;
}

public bool Supports(PresentMode mode)
{
// At most four entries — a scan beats any lookup structure.
Expand Down Expand Up @@ -72,4 +85,24 @@ public PresentMode ChoosePresentMode(params ReadOnlySpan<PresentMode> preferred)

return PresentMode.Fifo;
}

/// <summary>
/// The first of <paramref name="preferred"/> this surface supports, or the
/// surface's own preferred format (<see cref="Formats"/>[0]) when none
/// match. Use it to ask for a wide-gamut or high-dynamic-range format —
/// such as Rgba16Float — with a safe fallback, then pass the result as
/// <see cref="WindowSurfaceOptions.Format"/>.
/// </summary>
public TextureFormat ChooseFormat(params ReadOnlySpan<TextureFormat> preferred)
{
foreach (var format in preferred)
{
if (Supports(format))
{
return format;
}
}

return _formats[0];
}
}
22 changes: 22 additions & 0 deletions tests/Skyline.WindowedTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,28 @@ void Check(bool condition, string what)
Check(alphaOkGpu.Surface.PixelSize.Width > 0, "Configure accepts a supported alpha mode");
}

// Surface format selection: report support, choose with a fallback, and
// reject an unsupported format with a managed error instead of a wgpu abort.
Check(caps.Supports(surface.Format), "the configured surface format is supported");
var chosenFormat = caps.ChooseFormat(TextureFormat.Rgba16float, caps.Formats[0]);
Check(caps.Supports(chosenFormat), "ChooseFormat returns a supported format");
Check(caps.ChooseFormat((TextureFormat)0x6FFFFFFF) == caps.Formats[0], "ChooseFormat falls back to the preferred format");

var unsupportedFormat = TextureFormat.R8Unorm;
var foundUnsupportedFormat = false;
foreach (var f in new[] { TextureFormat.R8Unorm, TextureFormat.RG8Unorm, TextureFormat.R16float, TextureFormat.R32float })
{
if (!caps.Supports(f)) { unsupportedFormat = f; foundUnsupportedFormat = true; break; }
}
Check(foundUnsupportedFormat && !caps.Supports(unsupportedFormat), "the surface rejects at least one single-channel format");
using (var fmtGpu = GpuContext.Create(win.Surface!, surfaceOptions: new WindowSurfaceOptions { Format = unsupportedFormat }))
{
var fmtThrew = false;
try { fmtGpu.Surface!.Configure(frame.PixelWidth, frame.PixelHeight); }
catch (InvalidOperationException) { fmtThrew = true; }
Check(fmtThrew, "Configure throws on an unsupported format");
}

surface.PresentMode = caps.ChoosePresentMode(PresentMode.Fifo);
Check(surface.PresentMode == PresentMode.Fifo, "PresentMode property holds the choice");
Check(surface.Format == TextureFormat.Bgra8Unorm, "Format reflects options");
Expand Down