mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
WebGPU renders again
This commit is contained in:
@@ -7,7 +7,7 @@ struct UniformConstants {
|
||||
|
||||
// Group 1: parameters that change infrequently in a draw pass.
|
||||
struct UniformView {
|
||||
projViewMatrix: mat3x2f,
|
||||
projViewMatrix: mat2x3f,
|
||||
screenPixelSize: vec2f
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ struct VertexOutput {
|
||||
|
||||
@vertex
|
||||
fn vs_main(input: VertexInput) -> VertexOutput {
|
||||
var transformed = View.projViewMatrix * vec3(input.position, 1.0);
|
||||
var transformed = vec3(input.position, 1.0) * View.projViewMatrix;
|
||||
|
||||
transformed += 1.0;
|
||||
transformed /= View.screenPixelSize * 2.0;
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract partial class RhiBase
|
||||
/// </summary>
|
||||
internal abstract void WindowRecreateSwapchain(RhiWebGpu.WindowData reg, Vector2i size);
|
||||
|
||||
internal abstract RhiTexture CreateTextureViewForWindow(RhiWebGpu.WindowData reg);
|
||||
internal abstract RhiTexture GetSurfaceTextureForWindow(RhiWebGpu.WindowData reg);
|
||||
internal abstract void WindowPresent(RhiWebGpu.WindowData reg);
|
||||
|
||||
//
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Client.Graphics.Rhi;
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to a WGSL <c>mat3x2f</c>.
|
||||
/// Equivalent to a WGSL <c>mat2x3f</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This matrix is columnar and 3 columns, 2 rows. This is different from the rest of the engine and .NET.
|
||||
/// This matrix is columnar and 2 columns, 3 rows. This is equivalent to .NET's <see cref="Matrix3x2"/>!
|
||||
/// </remarks>
|
||||
public struct ShaderMat3x2F
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct ShaderMat2x3F
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public float M11;
|
||||
public float M12;
|
||||
[FieldOffset(4)]
|
||||
public float M21;
|
||||
public float M22;
|
||||
[FieldOffset(8)]
|
||||
public float M31;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public float M12;
|
||||
[FieldOffset(20)]
|
||||
public float M22;
|
||||
[FieldOffset(24)]
|
||||
public float M32;
|
||||
|
||||
public static ShaderMat3x2F Transpose(in Matrix3x2 matrix)
|
||||
public static ShaderMat2x3F FromMatrix(in Matrix3x2 matrix)
|
||||
{
|
||||
var ret = default(ShaderMat3x2F);
|
||||
var ret = default(ShaderMat2x3F);
|
||||
ret.M11 = matrix.M11;
|
||||
ret.M12 = matrix.M12;
|
||||
ret.M21 = matrix.M21;
|
||||
|
||||
@@ -589,37 +589,47 @@ public record struct RhiVertexAttribute(RhiVertexFormat Format, ulong Offset, ui
|
||||
|
||||
public enum RhiVertexFormat : byte
|
||||
{
|
||||
Undefined = 0x00000000,
|
||||
Uint8x2 = 0x00000001,
|
||||
Uint8x4 = 0x00000002,
|
||||
Sint8x2 = 0x00000003,
|
||||
Sint8x4 = 0x00000004,
|
||||
Unorm8x2 = 0x00000005,
|
||||
Unorm8x4 = 0x00000006,
|
||||
Snorm8x2 = 0x00000007,
|
||||
Snorm8x4 = 0x00000008,
|
||||
Uint16x2 = 0x00000009,
|
||||
Uint16x4 = 0x0000000A,
|
||||
Sint16x2 = 0x0000000B,
|
||||
Sint16x4 = 0x0000000C,
|
||||
Unorm16x2 = 0x0000000D,
|
||||
Unorm16x4 = 0x0000000E,
|
||||
Snorm16x2 = 0x0000000F,
|
||||
Snorm16x4 = 0x00000010,
|
||||
Float16x2 = 0x00000011,
|
||||
Float16x4 = 0x00000012,
|
||||
Float32 = 0x00000013,
|
||||
Float32x2 = 0x00000014,
|
||||
Float32x3 = 0x00000015,
|
||||
Float32x4 = 0x00000016,
|
||||
Uint32 = 0x00000017,
|
||||
Uint32x2 = 0x00000018,
|
||||
Uint32x3 = 0x00000019,
|
||||
Uint32x4 = 0x0000001A,
|
||||
Sint32 = 0x0000001B,
|
||||
Sint32x2 = 0x0000001C,
|
||||
Sint32x3 = 0x0000001D,
|
||||
Sint32x4 = 0x0000001E,
|
||||
Uint8 = 0x00000001,
|
||||
Uint8x2 = 0x00000002,
|
||||
Uint8x4 = 0x00000003,
|
||||
Sint8 = 0x00000004,
|
||||
Sint8x2 = 0x00000005,
|
||||
Sint8x4 = 0x00000006,
|
||||
Unorm8 = 0x00000007,
|
||||
Unorm8x2 = 0x00000008,
|
||||
Unorm8x4 = 0x00000009,
|
||||
Snorm8 = 0x0000000A,
|
||||
Snorm8x2 = 0x0000000B,
|
||||
Snorm8x4 = 0x0000000C,
|
||||
Uint16 = 0x0000000D,
|
||||
Uint16x2 = 0x0000000E,
|
||||
Uint16x4 = 0x0000000F,
|
||||
Sint16 = 0x00000010,
|
||||
Sint16x2 = 0x00000011,
|
||||
Sint16x4 = 0x00000012,
|
||||
Unorm16 = 0x00000013,
|
||||
Unorm16x2 = 0x00000014,
|
||||
Unorm16x4 = 0x00000015,
|
||||
Snorm16 = 0x00000016,
|
||||
Snorm16x2 = 0x00000017,
|
||||
Snorm16x4 = 0x00000018,
|
||||
Float16 = 0x00000019,
|
||||
Float16x2 = 0x0000001A,
|
||||
Float16x4 = 0x0000001B,
|
||||
Float32 = 0x0000001C,
|
||||
Float32x2 = 0x0000001D,
|
||||
Float32x3 = 0x0000001E,
|
||||
Float32x4 = 0x0000001F,
|
||||
Uint32 = 0x00000020,
|
||||
Uint32x2 = 0x00000021,
|
||||
Uint32x3 = 0x00000022,
|
||||
Uint32x4 = 0x00000023,
|
||||
Sint32 = 0x00000024,
|
||||
Sint32x2 = 0x00000025,
|
||||
Sint32x3 = 0x00000026,
|
||||
Sint32x4 = 0x00000027,
|
||||
Unorm10_10_10_2 = 0x00000028,
|
||||
Unorm8x4BGRA = 0x00000029,
|
||||
Final
|
||||
}
|
||||
|
||||
@@ -638,11 +648,11 @@ public record struct RhiPrimitiveState(
|
||||
|
||||
public enum RhiPrimitiveTopology : byte
|
||||
{
|
||||
PointList = 0x00000000,
|
||||
LineList = 0x00000001,
|
||||
LineStrip = 0x00000002,
|
||||
TriangleList = 0x00000003,
|
||||
TriangleStrip = 0x00000004,
|
||||
PointList = 0x00000001,
|
||||
LineList = 0x00000002,
|
||||
LineStrip = 0x00000003,
|
||||
TriangleList = 0x00000004,
|
||||
TriangleStrip = 0x00000005,
|
||||
Final
|
||||
}
|
||||
|
||||
@@ -747,29 +757,31 @@ public record struct RhiBlendComponent(
|
||||
|
||||
public enum RhiBlendOperation : byte
|
||||
{
|
||||
Add = 0x00000000,
|
||||
Subtract = 0x00000001,
|
||||
ReverseSubtract = 0x00000002,
|
||||
Min = 0x00000003,
|
||||
Max = 0x00000004,
|
||||
Undefined = 0x00000000,
|
||||
Add = 0x00000001,
|
||||
Subtract = 0x00000002,
|
||||
ReverseSubtract = 0x00000003,
|
||||
Min = 0x00000004,
|
||||
Max = 0x00000005,
|
||||
Final
|
||||
}
|
||||
|
||||
public enum RhiBlendFactor : byte
|
||||
{
|
||||
Zero = 0x00000000,
|
||||
One = 0x00000001,
|
||||
Src = 0x00000002,
|
||||
OneMinusSrc = 0x00000003,
|
||||
SrcAlpha = 0x00000004,
|
||||
OneMinusSrcAlpha = 0x00000005,
|
||||
Dst = 0x00000006,
|
||||
OneMinusDst = 0x00000007,
|
||||
DstAlpha = 0x00000008,
|
||||
OneMinusDstAlpha = 0x00000009,
|
||||
SrcAlphaSaturated = 0x0000000A,
|
||||
Constant = 0x0000000B,
|
||||
OneMinusConstant = 0x0000000C,
|
||||
Undefined = 0x00000000,
|
||||
Zero = 0x00000001,
|
||||
One = 0x00000002,
|
||||
Src = 0x00000003,
|
||||
OneMinusSrc = 0x00000004,
|
||||
SrcAlpha = 0x00000005,
|
||||
OneMinusSrcAlpha = 0x00000006,
|
||||
Dst = 0x00000007,
|
||||
OneMinusDst = 0x00000008,
|
||||
DstAlpha = 0x00000009,
|
||||
OneMinusDstAlpha = 0x0000000A,
|
||||
SrcAlphaSaturated = 0x0000000B,
|
||||
Constant = 0x0000000C,
|
||||
OneMinusConstant = 0x0000000D,
|
||||
Final
|
||||
}
|
||||
|
||||
@@ -847,23 +859,23 @@ public record struct RhiSamplerDescriptor(
|
||||
|
||||
public enum RhiAddressMode : byte
|
||||
{
|
||||
Repeat = 0,
|
||||
MirrorRepeat = 1,
|
||||
ClampToEdge = 2,
|
||||
ClampToEdge = 1,
|
||||
Repeat = 2,
|
||||
MirrorRepeat = 3,
|
||||
Final
|
||||
}
|
||||
|
||||
public enum RhiFilterMode : byte
|
||||
{
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
Nearest = 1,
|
||||
Linear = 2,
|
||||
Final
|
||||
}
|
||||
|
||||
public enum RhiMipmapFilterMode : byte
|
||||
{
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
Nearest = 1,
|
||||
Linear = 2,
|
||||
Final
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
pAttachment->clearValue = WgpuColor(attachment.ClearValue);
|
||||
pAttachment->loadOp = (WGPULoadOp)attachment.LoadOp;
|
||||
pAttachment->storeOp = (WGPUStoreOp)attachment.StoreOp;
|
||||
pAttachment->depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
|
||||
}
|
||||
|
||||
if (descriptor.DepthStencilAttachment is { } depthStencilAttachment)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -85,12 +86,18 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
return format;
|
||||
}
|
||||
|
||||
private static RhiTextureDimension ValidateTextureDimension(RhiTextureDimension dimension)
|
||||
private static WGPUTextureDimension ValidateTextureDimension(RhiTextureDimension dimension)
|
||||
{
|
||||
if (dimension > RhiTextureDimension.Dim3D)
|
||||
throw new ArgumentException($"Invalid {nameof(RhiTextureDimension)}");
|
||||
|
||||
return dimension;
|
||||
return dimension switch
|
||||
{
|
||||
RhiTextureDimension.Dim1D => WGPUTextureDimension.WGPUTextureDimension_1D,
|
||||
RhiTextureDimension.Dim2D => WGPUTextureDimension.WGPUTextureDimension_2D,
|
||||
RhiTextureDimension.Dim3D => WGPUTextureDimension.WGPUTextureDimension_3D,
|
||||
_ => throw new UnreachableException()
|
||||
};
|
||||
}
|
||||
|
||||
private static RhiTextureUsage ValidateTextureUsage(RhiTextureUsage usage)
|
||||
|
||||
@@ -80,7 +80,9 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
{
|
||||
ref var bufferLayout = ref pipelineDesc.vertex.buffers[i];
|
||||
bufferLayout.arrayStride = buffers[i].ArrayStride;
|
||||
bufferLayout.stepMode = (WGPUVertexStepMode)buffers[i].StepMode;
|
||||
bufferLayout.stepMode = buffers[i].StepMode == RhiVertexStepMode.Instance
|
||||
? WGPUVertexStepMode.WGPUVertexStepMode_Instance
|
||||
: WGPUVertexStepMode.WGPUVertexStepMode_Vertex;
|
||||
|
||||
var attributes = buffers[i].Attributes;
|
||||
bufferLayout.attributeCount = (uint)attributes.Length;
|
||||
|
||||
@@ -10,10 +10,9 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
public override RhiTexture CreateTexture(in RhiTextureDescriptor descriptor)
|
||||
{
|
||||
var format = descriptor.Format;
|
||||
var dimension = descriptor.Dimension;
|
||||
var usage = descriptor.Usage;
|
||||
ValidateTextureFormat(format);
|
||||
ValidateTextureDimension(dimension);
|
||||
var dimension = ValidateTextureDimension(descriptor.Dimension);
|
||||
ValidateTextureUsage(usage);
|
||||
|
||||
// TODO: Copy to stackalloc instead.
|
||||
@@ -36,7 +35,7 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
{
|
||||
sampleCount = descriptor.SampleCount,
|
||||
mipLevelCount = descriptor.MipLevelCount,
|
||||
dimension = (WGPUTextureDimension) dimension,
|
||||
dimension = dimension,
|
||||
format = (WGPUTextureFormat) format,
|
||||
label = new WGPUStringView
|
||||
{
|
||||
@@ -112,7 +111,7 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
_textureViewRegistry.Remove(textureView.Handle);
|
||||
}
|
||||
|
||||
internal override RhiTexture CreateTextureViewForWindow(WindowData reg)
|
||||
internal override RhiTexture GetSurfaceTextureForWindow(WindowData reg)
|
||||
{
|
||||
// TODO: Thread safety
|
||||
|
||||
|
||||
@@ -89,10 +89,11 @@ internal sealed unsafe partial class RhiWebGpu
|
||||
var swapChainDesc = new WGPUSurfaceConfiguration
|
||||
{
|
||||
format = format,
|
||||
height = (uint)size.X,
|
||||
width = (uint)size.Y,
|
||||
width = (uint)size.X,
|
||||
height = (uint)size.Y,
|
||||
usage = WGPUTextureUsage_RenderAttachment,
|
||||
presentMode = WGPUPresentMode.WGPUPresentMode_Fifo
|
||||
presentMode = WGPUPresentMode.WGPUPresentMode_Fifo,
|
||||
device = _wgpuDevice
|
||||
};
|
||||
|
||||
wgpuSurfaceConfigure(window.Surface, &swapChainDesc);
|
||||
|
||||
21
Robust.Client.Interop.RobustNative/DllMap.cs
Normal file
21
Robust.Client.Interop.RobustNative/DllMap.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Robust.Client.Interop.RobustNative;
|
||||
|
||||
|
||||
internal static class DllMap
|
||||
{
|
||||
#pragma warning disable CA2255
|
||||
[ModuleInitializer]
|
||||
#pragma warning restore CA2255
|
||||
public static void Initializer()
|
||||
{
|
||||
if (Environment.GetEnvironmentVariable("ROBUST_NATIVE_PATH") is not { } nativePath)
|
||||
return;
|
||||
|
||||
NativeLibrary.SetDllImportResolver(
|
||||
typeof(DllMap).Assembly,
|
||||
(_, _, _) => NativeLibrary.Load(nativePath));
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,5 @@ internal static partial class Wgpu
|
||||
{
|
||||
public static readonly nuint WGPU_STRLEN = nuint.MaxValue;
|
||||
public const ulong WGPU_WHOLE_SIZE = ulong.MaxValue;
|
||||
public const uint WGPU_DEPTH_SLICE_UNDEFINED = uint.MaxValue;
|
||||
}
|
||||
|
||||
@@ -111,10 +111,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (!reg.IsVisible) // Only send this for open windows
|
||||
return;
|
||||
|
||||
// var loaded = RtToLoaded(reg.RenderTarget);
|
||||
// loaded.Size = reg.FramebufferSize;
|
||||
|
||||
Rhi.WindowRecreateSwapchain(reg);
|
||||
reg.NeedSurfaceReconfigure = true;
|
||||
|
||||
var eventArgs = new WindowResizedEventArgs(
|
||||
oldSize,
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
if (string.IsNullOrEmpty(splashTex))
|
||||
return;
|
||||
|
||||
var backbuffer = _mainWindow!.CurSwapchainView!;
|
||||
var backbuffer = _mainWindow!.CurSurfaceTextureView!;
|
||||
|
||||
var size = _mainWindow!.FramebufferSize;
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public void RenderNow(IRenderTarget renderTarget, Action<IRenderHandle> callback)
|
||||
{
|
||||
ClearRenderState();
|
||||
// ClearRenderState();
|
||||
|
||||
_renderHandle.RenderInRenderTarget(
|
||||
renderTarget,
|
||||
|
||||
@@ -603,6 +603,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
private sealed class LightCapacityComparer : IComparer<(PointLightComponent light, Vector2 pos, float distanceSquared, Angle rot)>
|
||||
{
|
||||
@@ -626,6 +627,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
private (int count, Box2 expandedBounds) GetLightsToRender(
|
||||
MapId map,
|
||||
in Box2Rotated worldBounds,
|
||||
@@ -676,6 +679,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
return (state.count, expandedBounds);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Pure]
|
||||
@@ -685,6 +689,18 @@ namespace Robust.Client.Graphics.Clyde
|
||||
MapLightComponent.DefaultColor;
|
||||
}
|
||||
|
||||
public void BlurRenderTarget(
|
||||
IClydeViewport viewport,
|
||||
IRenderTarget target,
|
||||
IRenderTarget blurBuffer,
|
||||
IEye eye,
|
||||
float multiplier)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void BlurRenderTarget(IClydeViewport viewport, IRenderTarget target, IRenderTarget blurBuffer, IEye eye, float multiplier)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics.Rhi;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Maths;
|
||||
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||
using Robust.Shared.Graphics;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
@@ -38,13 +37,12 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public void SetModelTransform(in Matrix3x2 matrix)
|
||||
{
|
||||
matrix.Transpose(out var transposed);
|
||||
_spriteBatch.SetModelTransform((Matrix3x2)transposed);
|
||||
_spriteBatch.SetModelTransform(matrix);
|
||||
}
|
||||
|
||||
public Matrix3x2 GetModelTransform()
|
||||
{
|
||||
return _clyde.DrawGetModelTransform();
|
||||
return _spriteBatch.GetModelTransform();
|
||||
}
|
||||
|
||||
public void SetProjView(in Matrix3x2 proj, in Matrix3x2 view)
|
||||
@@ -145,7 +143,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
if (loaded.IsWindow)
|
||||
{
|
||||
targetTexture = loaded.Window!.CurSwapchainView!;
|
||||
targetTexture = loaded.Window!.CurSurfaceTextureView!;
|
||||
targetSize = loaded.Window!.FramebufferSize;
|
||||
}
|
||||
else
|
||||
@@ -284,9 +282,10 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public ShaderInstance? GetShader()
|
||||
{
|
||||
return _clyde._queuedShaderInstance == _clyde._defaultShader
|
||||
? null
|
||||
: _clyde._queuedShaderInstance;
|
||||
throw new NotImplementedException();
|
||||
// return _clyde._queuedShaderInstance == _clyde._defaultShader
|
||||
// ? null
|
||||
// : _clyde._queuedShaderInstance;
|
||||
}
|
||||
|
||||
public void Viewport(Box2i viewport)
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public IRenderTexture CreateLightRenderTarget(Vector2i size, string? name = null, bool depthStencil = true)
|
||||
{
|
||||
var lightMapColorFormat = _hasGLFloatFramebuffers
|
||||
var lightMapColorFormat = true // _hasGLFloatFramebuffers
|
||||
? RTCF.R11FG11FB10F
|
||||
: RTCF.Rgba8;
|
||||
var lightMapSampleParameters = new TextureSampleParameters { Filter = true };
|
||||
@@ -109,13 +109,12 @@ namespace Robust.Client.Graphics.Clyde
|
||||
ColorFormat = format.ColorFormat,
|
||||
DepthStencilTexture = depthStencilTexture,
|
||||
DepthSencilTextureView = depthStencilTextureView,
|
||||
MemoryPressure = pressure,
|
||||
MemoryPressure = 0, // pressure,
|
||||
SampleParameters = sampleParameters,
|
||||
Instance = new WeakReference<RenderTargetBase>(renderTarget),
|
||||
Name = name,
|
||||
};
|
||||
|
||||
var renderTarget = new RenderTexture(size, textureObject, this, handle);
|
||||
_renderTargets.Add(handle, data);
|
||||
return renderTarget;
|
||||
}
|
||||
@@ -171,6 +170,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
public bool IsWindow;
|
||||
public WindowReg? Window;
|
||||
public string? Name;
|
||||
|
||||
public Vector2i Size;
|
||||
public bool IsSrgb;
|
||||
@@ -186,6 +186,11 @@ namespace Robust.Client.Graphics.Clyde
|
||||
// Depth/stencil attachment.
|
||||
public RhiTexture? DepthStencilTexture;
|
||||
public RhiTextureView? DepthSencilTextureView;
|
||||
|
||||
public TextureSampleParameters? SampleParameters;
|
||||
public required WeakReference<RenderTargetBase> Instance;
|
||||
|
||||
public long MemoryPressure;
|
||||
}
|
||||
|
||||
internal abstract class RenderTargetBase : IRenderTarget
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Robust.Client.Graphics.Rhi;
|
||||
using Robust.Client.Graphics.Rhi.WebGpu;
|
||||
using Robust.Client.Interop.RobustNative.Webgpu;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Utility;
|
||||
using RhiBase = Robust.Client.Graphics.Rhi.RhiBase;
|
||||
@@ -26,10 +27,13 @@ internal sealed partial class Clyde
|
||||
};
|
||||
|
||||
Rhi.Init(new RhiBase.RhiInitParams
|
||||
{
|
||||
Backends = _cfg.GetCVar(CVars.DisplayWgpuBackends),
|
||||
PowerPreference = (RhiPowerPreference)_cfg.GetCVar(CVars.DisplayGpuPowerPreference)
|
||||
});
|
||||
{
|
||||
Backends = _cfg.GetCVar(CVars.DisplayWgpuBackends),
|
||||
PowerPreference = (RhiPowerPreference)_cfg.GetCVar(CVars.DisplayGpuPowerPreference),
|
||||
MainWindowSize = _mainWindow!.FramebufferSize,
|
||||
MainWindowSurfaceParams = _mainWindow.SurfaceParams
|
||||
},
|
||||
out _mainWindow.RhiWebGpuData);
|
||||
}
|
||||
|
||||
private void AcquireSwapchainTextures()
|
||||
@@ -41,13 +45,29 @@ internal sealed partial class Clyde
|
||||
|
||||
foreach (var window in _windows)
|
||||
{
|
||||
window.CurSwapchainView?.Dispose();
|
||||
window.CurSwapchainView = Rhi.CreateTextureViewForWindow(window);
|
||||
window.CurSurfaceTexture?.Dispose();
|
||||
window.CurSurfaceTextureView?.Dispose();
|
||||
|
||||
if (window.NeedSurfaceReconfigure)
|
||||
{
|
||||
Rhi.WindowRecreateSwapchain(window.RhiWebGpuData!, window.FramebufferSize);
|
||||
window.NeedSurfaceReconfigure = false;
|
||||
}
|
||||
|
||||
window.CurSurfaceTexture = Rhi.GetSurfaceTextureForWindow(window.RhiWebGpuData!);
|
||||
window.CurSurfaceTextureView = window.CurSurfaceTexture.CreateView(new RhiTextureViewDescriptor
|
||||
{
|
||||
Dimension = RhiTextureViewDimension.Dim2D,
|
||||
Format = RhiTextureFormat.BGRA8UnormSrgb,
|
||||
ArrayLayerCount = 1,
|
||||
MipLevelCount = 1,
|
||||
Aspect = RhiTextureAspect.All,
|
||||
});
|
||||
|
||||
var pass = encoder.BeginRenderPass(new RhiRenderPassDescriptor(
|
||||
new[]
|
||||
{
|
||||
new RhiRenderPassColorAttachment(window.CurSwapchainView, RhiLoadOp.Clear, RhiStoreOp.Store)
|
||||
new RhiRenderPassColorAttachment(window.CurSurfaceTextureView, RhiLoadOp.Clear, RhiStoreOp.Store)
|
||||
}
|
||||
));
|
||||
|
||||
@@ -61,13 +81,16 @@ internal sealed partial class Clyde
|
||||
{
|
||||
foreach (var window in _windows)
|
||||
{
|
||||
if (window.CurSwapchainView == null)
|
||||
if (window.CurSurfaceTexture == null)
|
||||
return;
|
||||
|
||||
window.CurSwapchainView.Dispose();
|
||||
window.CurSwapchainView = null;
|
||||
window.CurSurfaceTexture.Dispose();
|
||||
window.CurSurfaceTexture = null;
|
||||
|
||||
Rhi.WindowPresent(window);
|
||||
window.CurSurfaceTextureView!.Dispose();
|
||||
window.CurSurfaceTextureView = null;
|
||||
|
||||
Rhi.WindowPresent(window.RhiWebGpuData!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Robust.Client.Graphics.Rhi;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
using RhiBase = Robust.Client.Graphics.Rhi.RhiBase;
|
||||
using RVector2 = Robust.Shared.Maths.Vector2;
|
||||
using RVector4 = Robust.Shared.Maths.Vector4;
|
||||
using SVector2 = System.Numerics.Vector2;
|
||||
using SVector4 = System.Numerics.Vector4;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde;
|
||||
|
||||
@@ -18,10 +15,10 @@ internal partial class Clyde
|
||||
// Implementation of a sprite batch on the new RHI.
|
||||
// Basically, the old rendering API.
|
||||
|
||||
private sealed class SpriteBatch
|
||||
internal sealed class SpriteBatch
|
||||
{
|
||||
private const int VertexSize = 32;
|
||||
private const int UniformPassSize = 32;
|
||||
private const int UniformPassSize = 64;
|
||||
|
||||
private const uint BindGroup0 = 0;
|
||||
private const uint BindGroup1 = 1;
|
||||
@@ -83,7 +80,7 @@ internal partial class Clyde
|
||||
|
||||
var uniformPoolSize = MathHelper.CeilingPowerOfTwo(
|
||||
UniformPassSize,
|
||||
(int)_rhi.DeviceLimits.MinUniformBufferOffsetAlignment
|
||||
Math.Max((int)_rhi.DeviceLimits.MinUniformBufferOffsetAlignment, UniformPassSize)
|
||||
) * 20;
|
||||
|
||||
_uniformPassPool = new GpuExpansionBuffer(
|
||||
@@ -118,7 +115,7 @@ internal partial class Clyde
|
||||
new RhiBindGroupLayoutEntry(
|
||||
0,
|
||||
RhiShaderStage.Vertex | RhiShaderStage.Fragment,
|
||||
new RhiBufferBindingLayout(MinBindingSize: 32)
|
||||
new RhiBufferBindingLayout(MinBindingSize: UniformPassSize)
|
||||
)
|
||||
},
|
||||
"SpriteBatch bind group 1 (view)"
|
||||
@@ -216,8 +213,8 @@ internal partial class Clyde
|
||||
|
||||
uniformPass[0] = new UniformView
|
||||
{
|
||||
ProjViewMatrix = ShaderMat3x2F.Transpose(projView),
|
||||
ScreenPixelSize = new SVector2(1f / size.X, 1f / size.Y)
|
||||
ProjViewMatrix = ShaderMat2x3F.FromMatrix(projView),
|
||||
ScreenPixelSize = new Vector2(1f / size.X, 1f / size.Y)
|
||||
};
|
||||
|
||||
var rhiClearColor = clearColor == null ? new RhiColor(0, 0, 0, 1) : Color.FromSrgb(clearColor.Value);
|
||||
@@ -279,7 +276,7 @@ internal partial class Clyde
|
||||
Clear();
|
||||
}
|
||||
|
||||
public void Draw(ClydeTexture texture, RVector2 position, Color color)
|
||||
public void Draw(ClydeTexture texture, Vector2 position, Color color)
|
||||
{
|
||||
var textureHandle = texture.TextureId;
|
||||
|
||||
@@ -291,24 +288,24 @@ internal partial class Clyde
|
||||
var width = texture.Width;
|
||||
var height = texture.Height;
|
||||
|
||||
var bl = (SVector2)(position);
|
||||
var br = (SVector2)(position + (width, 0));
|
||||
var tr = (SVector2)(position + (width, height));
|
||||
var tl = (SVector2)(position + (0, height));
|
||||
var bl = (position);
|
||||
var br = (position + new Vector2(width, 0));
|
||||
var tr = (position + new Vector2(width, height));
|
||||
var tl = (position + new Vector2(0, height));
|
||||
|
||||
var sBl = SVector2.Transform(bl, _modelTransform);
|
||||
var sBr = SVector2.Transform(br, _modelTransform);
|
||||
var sTl = SVector2.Transform(tl, _modelTransform);
|
||||
var sTr = SVector2.Transform(tr, _modelTransform);
|
||||
var sBl = Vector2.Transform(bl, _modelTransform);
|
||||
var sBr = Vector2.Transform(br, _modelTransform);
|
||||
var sTl = Vector2.Transform(tl, _modelTransform);
|
||||
var sTr = Vector2.Transform(tr, _modelTransform);
|
||||
|
||||
var asColor = Unsafe.As<Color, SVector4>(ref color);
|
||||
var asColor = Unsafe.As<Color, Vector4>(ref color);
|
||||
|
||||
vertices[0] = new Vertex2D(sBl, new SVector2(0, 1), asColor);
|
||||
vertices[1] = new Vertex2D(sBr, new SVector2(1, 1), asColor);
|
||||
vertices[2] = new Vertex2D(sTr, new SVector2(1, 0), asColor);
|
||||
vertices[3] = new Vertex2D(sTr, new SVector2(1, 0), asColor);
|
||||
vertices[4] = new Vertex2D(sTl, new SVector2(0, 0), asColor);
|
||||
vertices[5] = new Vertex2D(sBl, new SVector2(0, 1), asColor);
|
||||
vertices[0] = new Vertex2D(sBl, new Vector2(0, 1), asColor);
|
||||
vertices[1] = new Vertex2D(sBr, new Vector2(1, 1), asColor);
|
||||
vertices[2] = new Vertex2D(sTr, new Vector2(1, 0), asColor);
|
||||
vertices[3] = new Vertex2D(sTr, new Vector2(1, 0), asColor);
|
||||
vertices[4] = new Vertex2D(sTl, new Vector2(0, 0), asColor);
|
||||
vertices[5] = new Vertex2D(sBl, new Vector2(0, 1), asColor);
|
||||
|
||||
_vertexStartIndex += 6;
|
||||
_curBatchSize += 6;
|
||||
@@ -316,7 +313,7 @@ internal partial class Clyde
|
||||
|
||||
public void Draw(
|
||||
ClydeTexture texture,
|
||||
RVector2 bl, RVector2 br, RVector2 tl, RVector2 tr,
|
||||
Vector2 bl, Vector2 br, Vector2 tl, Vector2 tr,
|
||||
in Color color,
|
||||
in Box2 region)
|
||||
{
|
||||
@@ -327,18 +324,18 @@ internal partial class Clyde
|
||||
|
||||
var vertices = AllocateVertexSpace(6);
|
||||
|
||||
var asColor = Unsafe.As<Color, SVector4>(ref Unsafe.AsRef(color));
|
||||
var asColor = Unsafe.As<Color, Vector4>(ref Unsafe.AsRef(color));
|
||||
|
||||
var sBl = SVector2.Transform((SVector2)bl, _modelTransform);
|
||||
var sBr = SVector2.Transform((SVector2)br, _modelTransform);
|
||||
var sTl = SVector2.Transform((SVector2)tl, _modelTransform);
|
||||
var sTr = SVector2.Transform((SVector2)tr, _modelTransform);
|
||||
var sBl = Vector2.Transform((Vector2)bl, _modelTransform);
|
||||
var sBr = Vector2.Transform((Vector2)br, _modelTransform);
|
||||
var sTl = Vector2.Transform((Vector2)tl, _modelTransform);
|
||||
var sTr = Vector2.Transform((Vector2)tr, _modelTransform);
|
||||
|
||||
vertices[0] = new Vertex2D(sBl, (SVector2)region.BottomLeft, asColor);
|
||||
vertices[1] = new Vertex2D(sBr, (SVector2)region.BottomRight, asColor);
|
||||
vertices[2] = new Vertex2D(sTr, (SVector2)region.TopRight, asColor);
|
||||
vertices[0] = new Vertex2D(sBl, (Vector2)region.BottomLeft, asColor);
|
||||
vertices[1] = new Vertex2D(sBr, (Vector2)region.BottomRight, asColor);
|
||||
vertices[2] = new Vertex2D(sTr, (Vector2)region.TopRight, asColor);
|
||||
vertices[3] = vertices[2];
|
||||
vertices[4] = new Vertex2D(sTl, (SVector2)region.TopLeft, asColor);
|
||||
vertices[4] = new Vertex2D(sTl, (Vector2)region.TopLeft, asColor);
|
||||
vertices[5] = vertices[0];
|
||||
|
||||
_vertexStartIndex += 6;
|
||||
@@ -515,6 +512,11 @@ internal partial class Clyde
|
||||
_modelTransform = matrix;
|
||||
}
|
||||
|
||||
public Matrix3x2 GetModelTransform()
|
||||
{
|
||||
return _modelTransform;
|
||||
}
|
||||
|
||||
private RhiBindGroup AllocTempBindGroup(in RhiBindGroupDescriptor descriptor)
|
||||
{
|
||||
var bindGroup = _rhi.CreateBindGroup(descriptor);
|
||||
@@ -524,11 +526,11 @@ internal partial class Clyde
|
||||
|
||||
private struct Vertex2D
|
||||
{
|
||||
public SVector2 Position;
|
||||
public SVector2 TexCoord;
|
||||
public SVector4 Color;
|
||||
public Vector2 Position;
|
||||
public Vector2 TexCoord;
|
||||
public Vector4 Color;
|
||||
|
||||
public Vertex2D(SVector2 position, SVector2 texCoord, SVector4 color)
|
||||
public Vertex2D(Vector2 position, Vector2 texCoord, Vector4 color)
|
||||
{
|
||||
Position = position;
|
||||
TexCoord = texCoord;
|
||||
@@ -536,10 +538,13 @@ internal partial class Clyde
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct UniformView
|
||||
{
|
||||
public ShaderMat3x2F ProjViewMatrix;
|
||||
public SVector2 ScreenPixelSize;
|
||||
[FieldOffset(0)]
|
||||
public ShaderMat2x3F ProjViewMatrix;
|
||||
[FieldOffset(32)]
|
||||
public Vector2 ScreenPixelSize;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -159,6 +159,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
Height = height,
|
||||
Format = format,
|
||||
Name = name,
|
||||
TextureInstance = new WeakReference<ClydeTexture>(instance),
|
||||
};
|
||||
|
||||
_loadedTextures.Add(id, loaded);
|
||||
@@ -609,6 +610,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public int Width;
|
||||
public int Height;
|
||||
public long MemoryPressure;
|
||||
public RhiTextureFormat Format;
|
||||
public string? Name;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Graphics.Rhi;
|
||||
@@ -10,7 +9,6 @@ using Robust.Client.Graphics.Rhi.WebGpu;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -79,11 +77,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
}
|
||||
}
|
||||
|
||||
public uint? GetX11WindowId()
|
||||
{
|
||||
return _windowing?.WindowGetX11Id(_mainWindow!) ?? null;
|
||||
}
|
||||
|
||||
private bool InitWindowing()
|
||||
{
|
||||
var iconPath = _cfg.GetCVar(CVars.DisplayWindowIconSet);
|
||||
@@ -288,7 +281,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
Size = reg.FramebufferSize,
|
||||
IsWindow = true,
|
||||
WindowId = reg.Id,
|
||||
Window = reg,
|
||||
IsSrgb = true,
|
||||
Instance = new WeakReference<RenderTargetBase>(renderTarget),
|
||||
});
|
||||
@@ -296,7 +289,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
reg.RenderTarget = renderTarget;
|
||||
|
||||
if (!isMain)
|
||||
Rhi.WindowCreated(reg);
|
||||
Rhi.WindowCreated(in reg.SurfaceParams, reg.FramebufferSize);
|
||||
}
|
||||
|
||||
// Pass through result whether successful or not, caller handles it.
|
||||
@@ -315,7 +308,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
reg.IsDisposed = true;
|
||||
|
||||
Rhi.WindowDestroy(reg);
|
||||
Rhi.WindowDestroy(reg.RhiWebGpuData!);
|
||||
|
||||
_windowing!.WindowDestroy(reg);
|
||||
|
||||
@@ -424,10 +417,14 @@ namespace Robust.Client.Graphics.Clyde
|
||||
public IClydeWindow? Owner;
|
||||
|
||||
public RhiWebGpu.WindowData? RhiWebGpuData;
|
||||
public RhiTextureView? CurSwapchainView;
|
||||
public RhiTexture? CurSurfaceTexture;
|
||||
public RhiTextureView? CurSurfaceTextureView;
|
||||
|
||||
public bool DisposeOnClose;
|
||||
|
||||
public bool NeedSurfaceReconfigure;
|
||||
public RhiBase.RhiWindowSurfaceParams SurfaceParams;
|
||||
|
||||
public bool IsMainWindow;
|
||||
public WindowHandle Handle = default!;
|
||||
public RenderWindow RenderTarget = default!;
|
||||
@@ -529,8 +526,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
_clyde._windowing!.TextInputStop(Reg);
|
||||
}
|
||||
|
||||
public nint? WindowsHWnd => _clyde._windowing!.WindowGetWin32Window(Reg);
|
||||
}
|
||||
|
||||
private sealed class MonitorHandle : IClydeMonitor
|
||||
|
||||
@@ -19,6 +19,8 @@ using Robust.Shared.Maths;
|
||||
using Robust.Shared.Profiling;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
/// <summary>
|
||||
@@ -26,7 +28,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
/// </summary>
|
||||
internal sealed partial class Clyde : IClydeInternal, IPostInjectInit, IEntityEventSubscriber
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
[Dependency] private readonly IClydeTileDefinitionManager _tileDefinitionManager = default!;
|
||||
[Dependency] private readonly ILightManager _lightManager = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
@@ -56,6 +57,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
private Thread? _gameThread;
|
||||
|
||||
private ISawmill _sawmillWin = default!;
|
||||
private ISawmill _clydeSawmill = default!;
|
||||
|
||||
private bool _threadWindowApi;
|
||||
|
||||
public Clyde()
|
||||
@@ -76,7 +80,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_proto.PrototypesReloaded += OnProtoReload;
|
||||
|
||||
|
||||
_cfg.OnValueChanged(CVars.DisplayVSync, VSyncChanged, true);
|
||||
_cfg.OnValueChanged(CVars.DisplayVSync, b => VsyncEnabled = b, true);
|
||||
_cfg.OnValueChanged(CVars.DisplayWindowMode, WindowModeChanged, true);
|
||||
/*
|
||||
_cfg.OnValueChanged(CVars.LightResolutionScale, LightResolutionScaleChanged, true);
|
||||
@@ -189,9 +193,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
public void RegisterGridEcsEvents()
|
||||
{
|
||||
_entityManager.EventBus.SubscribeEvent<TileChangedEvent>(EventSource.Local, this, _updateTileMapOnUpdate);
|
||||
_entityManager.EventBus.SubscribeEvent<GridStartupEvent>(EventSource.Local, this, _updateOnGridCreated);
|
||||
_entityManager.EventBus.SubscribeEvent<GridRemovalEvent>(EventSource.Local, this, _updateOnGridRemoved);
|
||||
// _entityManager.EventBus.SubscribeEvent<TileChangedEvent>(EventSource.Local, this, _updateTileMapOnUpdate);
|
||||
// _entityManager.EventBus.SubscribeEvent<GridStartupEvent>(EventSource.Local, this, _updateOnGridCreated);
|
||||
// _entityManager.EventBus.SubscribeEvent<GridRemovalEvent>(EventSource.Local, this, _updateOnGridRemoved);
|
||||
}
|
||||
|
||||
public void ShutdownGridEcsEvents()
|
||||
|
||||
@@ -41,12 +41,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
void WindowSetSize(WindowReg window, Vector2i size);
|
||||
void WindowSetVisible(WindowReg window, bool visible);
|
||||
void WindowRequestAttention(WindowReg window);
|
||||
void WindowSwapBuffers(WindowReg window);
|
||||
uint? WindowGetX11Id(WindowReg window);
|
||||
nint? WindowGetX11Display(WindowReg window);
|
||||
nint? WindowGetMetalLayer(WindowReg window);
|
||||
HWND WindowGetWin32Window(WindowReg window);
|
||||
HINSTANCE WindowGetWin32Instance(WindowReg window);
|
||||
|
||||
// Keyboard
|
||||
string? KeyGetName(Keyboard.Key key);
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Graphics.Rhi;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using SDL3;
|
||||
using TerraFX.Interop.Windows;
|
||||
using TerraFX.Interop.Xlib;
|
||||
#if WINDOWS
|
||||
using BOOL = TerraFX.Interop.Windows.BOOL;
|
||||
using Windows = TerraFX.Interop.Windows.Windows;
|
||||
#endif
|
||||
using GLAttr = SDL3.SDL.SDL_GLAttr;
|
||||
using X11Window = TerraFX.Interop.Xlib.Window;
|
||||
|
||||
namespace Robust.Client.Graphics.Clyde;
|
||||
@@ -23,24 +19,14 @@ internal partial class Clyde
|
||||
private int _nextWindowId = 1;
|
||||
|
||||
public (WindowReg?, string? error) WindowCreate(
|
||||
GLContextSpec? spec,
|
||||
WindowCreateParameters parameters,
|
||||
WindowReg? share,
|
||||
WindowReg? owner)
|
||||
{
|
||||
nint shareWindow = 0;
|
||||
nint shareContext = 0;
|
||||
if (share is Sdl3WindowReg shareReg)
|
||||
{
|
||||
shareWindow = shareReg.Sdl3Window;
|
||||
shareContext = shareReg.GlContext;
|
||||
}
|
||||
|
||||
nint ownerPtr = 0;
|
||||
if (owner is Sdl3WindowReg ownerReg)
|
||||
ownerPtr = ownerReg.Sdl3Window;
|
||||
|
||||
var task = SharedWindowCreate(spec, parameters, shareWindow, shareContext, ownerPtr);
|
||||
var task = SharedWindowCreate(parameters, ownerPtr);
|
||||
|
||||
// Block the main thread (to avoid stuff like texture uploads being problematic).
|
||||
WaitWindowCreate(task);
|
||||
@@ -68,10 +54,7 @@ internal partial class Clyde
|
||||
}
|
||||
|
||||
private Task<Sdl3WindowCreateResult> SharedWindowCreate(
|
||||
GLContextSpec? glSpec,
|
||||
WindowCreateParameters parameters,
|
||||
nint shareWindow,
|
||||
nint shareContext,
|
||||
nint owner)
|
||||
{
|
||||
//
|
||||
@@ -93,10 +76,7 @@ internal partial class Clyde
|
||||
var tcs = new TaskCompletionSource<Sdl3WindowCreateResult>();
|
||||
SendCmd(new CmdWinCreate
|
||||
{
|
||||
GLSpec = glSpec,
|
||||
Parameters = parameters,
|
||||
ShareWindow = shareWindow,
|
||||
ShareContext = shareContext,
|
||||
OwnerWindow = owner,
|
||||
Tcs = tcs
|
||||
});
|
||||
@@ -110,12 +90,7 @@ internal partial class Clyde
|
||||
|
||||
private void WinThreadWinCreate(CmdWinCreate cmd)
|
||||
{
|
||||
var (window, context) = CreateSdl3WindowForRenderer(
|
||||
cmd.GLSpec,
|
||||
cmd.Parameters,
|
||||
cmd.ShareWindow,
|
||||
cmd.ShareContext,
|
||||
cmd.OwnerWindow);
|
||||
var window = CreateSdl3WindowForRenderer(cmd.Parameters, cmd.OwnerWindow);
|
||||
|
||||
if (window == 0)
|
||||
{
|
||||
@@ -135,7 +110,7 @@ internal partial class Clyde
|
||||
// * it'd not be synchronized to other incoming window events correctly which might be icky.
|
||||
// So we send the TCS back to the game thread
|
||||
// which processes events in the correct order and has better control of stuff during init.
|
||||
var reg = WinThreadSetupWindow(window, context);
|
||||
var reg = WinThreadSetupWindow(window);
|
||||
|
||||
SendEvent(new EventWindowCreate
|
||||
{
|
||||
@@ -152,11 +127,8 @@ internal partial class Clyde
|
||||
#endif
|
||||
}
|
||||
|
||||
private (nint window, nint context) CreateSdl3WindowForRenderer(
|
||||
GLContextSpec? spec,
|
||||
private nint CreateSdl3WindowForRenderer(
|
||||
WindowCreateParameters parameters,
|
||||
nint shareWindow,
|
||||
nint shareContext,
|
||||
nint ownerWindow)
|
||||
{
|
||||
var createProps = SDL.SDL_CreateProperties();
|
||||
@@ -164,55 +136,6 @@ internal partial class Clyde
|
||||
SDL.SDL_SetBooleanProperty(createProps, SDL.SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true);
|
||||
SDL.SDL_SetBooleanProperty(createProps, SDL.SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true);
|
||||
|
||||
if (spec is { } s)
|
||||
{
|
||||
SDL.SDL_SetBooleanProperty(createProps, SDL.SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
|
||||
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_RED_SIZE, 8);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_GREEN_SIZE, 8);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_BLUE_SIZE, 8);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_ALPHA_SIZE, 8);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL.SDL_GL_SetAttribute(
|
||||
GLAttr.SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
|
||||
s.Profile == GLContextProfile.Es ? 0 : 1);
|
||||
int ctxFlags = 0;
|
||||
#if DEBUG
|
||||
ctxFlags |= SDL.SDL_GL_CONTEXT_DEBUG_FLAG;
|
||||
#endif
|
||||
if (s.Profile == GLContextProfile.Core)
|
||||
ctxFlags |= SDL.SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
|
||||
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_CONTEXT_FLAGS, (int)ctxFlags);
|
||||
|
||||
if (shareContext != 0)
|
||||
{
|
||||
SDL.SDL_GL_MakeCurrent(shareWindow, shareContext);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0);
|
||||
}
|
||||
|
||||
var profile = s.Profile switch
|
||||
{
|
||||
GLContextProfile.Compatibility => SDL.SDL_GL_CONTEXT_PROFILE_COMPATIBILITY,
|
||||
GLContextProfile.Core => SDL.SDL_GL_CONTEXT_PROFILE_CORE,
|
||||
GLContextProfile.Es => SDL.SDL_GL_CONTEXT_PROFILE_ES,
|
||||
_ => SDL.SDL_GL_CONTEXT_PROFILE_COMPATIBILITY,
|
||||
};
|
||||
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_CONTEXT_PROFILE_MASK, profile);
|
||||
SDL.SDL_SetHint(SDL.SDL_HINT_OPENGL_ES_DRIVER, s.CreationApi == GLContextCreationApi.Egl ? "1" : "0");
|
||||
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_CONTEXT_MAJOR_VERSION, s.Major);
|
||||
SDL.SDL_GL_SetAttribute(GLAttr.SDL_GL_CONTEXT_MINOR_VERSION, s.Minor);
|
||||
|
||||
if (s.CreationApi == GLContextCreationApi.Egl)
|
||||
WsiShared.EnsureEglAvailable();
|
||||
}
|
||||
|
||||
if (parameters.Fullscreen)
|
||||
SDL.SDL_SetBooleanProperty(createProps, SDL.SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true);
|
||||
|
||||
@@ -251,13 +174,6 @@ internal partial class Clyde
|
||||
if (window == 0)
|
||||
return default;
|
||||
|
||||
nint glContext = SDL.SDL_GL_CreateContext(window);
|
||||
if (glContext == 0)
|
||||
{
|
||||
SDL.SDL_DestroyWindow(window);
|
||||
return default;
|
||||
}
|
||||
|
||||
if ((parameters.Styles & OSWindowStyles.NoTitleOptions) != 0)
|
||||
{
|
||||
var props = SDL.SDL_GetWindowProperties(window);
|
||||
@@ -295,44 +211,24 @@ internal partial class Clyde
|
||||
|
||||
// TODO: Monitors, window maximize.
|
||||
|
||||
// Make sure window thread doesn't keep hold of the GL context.
|
||||
SDL.SDL_GL_MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
if (parameters.Visible)
|
||||
SDL.SDL_ShowWindow(window);
|
||||
|
||||
return (window, glContext);
|
||||
return window;
|
||||
}
|
||||
|
||||
private Sdl3WindowReg WinThreadSetupWindow(nint window, nint context)
|
||||
private Sdl3WindowReg WinThreadSetupWindow(nint window)
|
||||
{
|
||||
var reg = new Sdl3WindowReg
|
||||
{
|
||||
Sdl3Window = window,
|
||||
GlContext = context,
|
||||
WindowId = SDL.SDL_GetWindowID(window),
|
||||
Id = new WindowId(_nextWindowId++)
|
||||
};
|
||||
var handle = new WindowHandle(_clyde, reg);
|
||||
reg.Handle = handle;
|
||||
|
||||
var windowProps = SDL.SDL_GetWindowProperties(window);
|
||||
switch (_videoDriver)
|
||||
{
|
||||
case SdlVideoDriver.Windows:
|
||||
reg.WindowsHwnd = SDL.SDL_GetPointerProperty(
|
||||
windowProps,
|
||||
SDL.SDL_PROP_WINDOW_WIN32_HWND_POINTER,
|
||||
0);
|
||||
break;
|
||||
case SdlVideoDriver.X11:
|
||||
reg.X11Display = SDL.SDL_GetPointerProperty(
|
||||
windowProps,
|
||||
SDL.SDL_PROP_WINDOW_X11_DISPLAY_POINTER,
|
||||
0);
|
||||
reg.X11Id = (uint)SDL.SDL_GetNumberProperty(windowProps, SDL.SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
break;
|
||||
}
|
||||
reg.SurfaceParams = GetSurfaceParams(window);
|
||||
|
||||
AssignWindowIconToWindow(window);
|
||||
|
||||
@@ -461,95 +357,6 @@ internal partial class Clyde
|
||||
_sawmill.Error("Failed to flash window: {error}", SDL.SDL_GetError());
|
||||
}
|
||||
|
||||
public unsafe void WindowSwapBuffers(WindowReg window)
|
||||
{
|
||||
var reg = (Sdl3WindowReg)window;
|
||||
var windowPtr = WinPtr(reg);
|
||||
|
||||
#if WINDOWS
|
||||
// On Windows, SwapBuffers does not correctly sync to the DWM compositor.
|
||||
// This means OpenGL vsync is effectively broken by default on Windows.
|
||||
// We manually sync via DwmFlush(). GLFW does this automatically, SDL3 does not.
|
||||
//
|
||||
// Windows DwmFlush logic partly taken from:
|
||||
// https://github.com/love2d/love/blob/5175b0d1b599ea4c7b929f6b4282dd379fa116b8/src/modules/window/sdl/Window.cpp#L1018
|
||||
// https://github.com/glfw/glfw/blob/d3ede7b6847b66cf30b067214b2b4b126d4c729b/src/wgl_context.c#L321-L340
|
||||
// See also: https://github.com/libsdl-org/SDL/issues/5797
|
||||
|
||||
var dwmFlush = false;
|
||||
var swapInterval = 0;
|
||||
|
||||
if (!reg.Fullscreen && reg.SwapInterval > 0)
|
||||
{
|
||||
BOOL compositing;
|
||||
// 6.2 is Windows 8
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw
|
||||
if (OperatingSystem.IsWindowsVersionAtLeast(6, 2)
|
||||
|| Windows.SUCCEEDED(Windows.DwmIsCompositionEnabled(&compositing)) && compositing)
|
||||
{
|
||||
var curCtx = SDL.SDL_GL_GetCurrentContext();
|
||||
var curWin = SDL.SDL_GL_GetCurrentWindow();
|
||||
|
||||
if (curCtx != reg.GlContext || curWin != reg.Sdl3Window)
|
||||
throw new InvalidOperationException("Window context must be current!");
|
||||
|
||||
SDL.SDL_GL_SetSwapInterval(0);
|
||||
dwmFlush = true;
|
||||
swapInterval = reg.SwapInterval;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//_sawmill.Debug($"Swapping: {window.Id} @ {_clyde._gameTiming.CurFrame}");
|
||||
SDL.SDL_GL_SwapWindow(windowPtr);
|
||||
|
||||
#if WINDOWS
|
||||
if (dwmFlush)
|
||||
{
|
||||
var i = swapInterval;
|
||||
while (i-- > 0)
|
||||
{
|
||||
Windows.DwmFlush();
|
||||
}
|
||||
|
||||
SDL.SDL_GL_SetSwapInterval(swapInterval);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public uint? WindowGetX11Id(WindowReg window)
|
||||
{
|
||||
CheckWindowDisposed(window);
|
||||
|
||||
if (_videoDriver != SdlVideoDriver.X11)
|
||||
return null;
|
||||
|
||||
var reg = (Sdl3WindowReg)window;
|
||||
return reg.X11Id;
|
||||
}
|
||||
|
||||
public nint? WindowGetX11Display(WindowReg window)
|
||||
{
|
||||
CheckWindowDisposed(window);
|
||||
|
||||
if (_videoDriver != SdlVideoDriver.X11)
|
||||
return null;
|
||||
|
||||
var reg = (Sdl3WindowReg)window;
|
||||
return reg.X11Display;
|
||||
}
|
||||
|
||||
public nint? WindowGetWin32Window(WindowReg window)
|
||||
{
|
||||
CheckWindowDisposed(window);
|
||||
|
||||
if (_videoDriver != SdlVideoDriver.Windows)
|
||||
return null;
|
||||
|
||||
var reg = (Sdl3WindowReg)window;
|
||||
return reg.WindowsHwnd;
|
||||
}
|
||||
|
||||
public void RunOnWindowThread(Action a)
|
||||
{
|
||||
SendCmd(new CmdRunAction { Action = a });
|
||||
@@ -643,23 +450,56 @@ internal partial class Clyde
|
||||
return null;
|
||||
}
|
||||
|
||||
private unsafe RhiBase.RhiWindowSurfaceParams GetSurfaceParams(nint sdlWindow)
|
||||
{
|
||||
var props = SDL.SDL_GetWindowProperties(sdlWindow);
|
||||
#if WINDOWS
|
||||
return new RhiBase.RhiWindowSurfaceParams()
|
||||
{
|
||||
HInstance = (void*)SDL.SDL_GetPointerProperty(props, SDL.SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER, 0),
|
||||
HWnd = (void*)SDL.SDL_GetPointerProperty(props, SDL.SDL_PROP_WINDOW_WIN32_HWND_POINTER, 0),
|
||||
};
|
||||
#elif LINUX
|
||||
if (_videoDriver == SdlVideoDriver.Wayland)
|
||||
{
|
||||
return new RhiBase.RhiWindowSurfaceParams
|
||||
{
|
||||
X11Display = SDL.SDL_GetPointerProperty(windowProps, SDL.SDL_PROP_WINDOW_X11_DISPLAY_POINTER, 0),
|
||||
X11Id = SDL.SDL_GetPointerProperty(windowProps, SDL.SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(_videoDriver == _sdlVideoDriver.X11);
|
||||
return new RhiBase.RhiWindowSurfaceParams
|
||||
{
|
||||
Wayland = true,
|
||||
WaylandDisplay = SDL.SDL_GetPointerProperty(
|
||||
windowProps,
|
||||
SDL.SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER,
|
||||
0),
|
||||
WaylandSurface = SDL.SDL_GetPointerProperty(
|
||||
windowProps,
|
||||
SDL.SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER,
|
||||
0),
|
||||
};
|
||||
}
|
||||
#else
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private sealed class Sdl3WindowReg : WindowReg
|
||||
{
|
||||
public nint Sdl3Window;
|
||||
public uint WindowId;
|
||||
public nint GlContext;
|
||||
#pragma warning disable CS0649
|
||||
public bool Fullscreen;
|
||||
#pragma warning restore CS0649
|
||||
public int SwapInterval;
|
||||
|
||||
// Kept around to avoid it being GCd.
|
||||
public CursorImpl? Cursor;
|
||||
|
||||
public nint WindowsHwnd;
|
||||
public nint X11Display;
|
||||
public uint X11Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ internal partial class Clyde
|
||||
{
|
||||
"windows" => SdlVideoDriver.Windows,
|
||||
"x11" => SdlVideoDriver.X11,
|
||||
"wayland" => SdlVideoDriver.Wayland,
|
||||
_ => SdlVideoDriver.Other,
|
||||
};
|
||||
}
|
||||
@@ -139,29 +140,6 @@ internal partial class Clyde
|
||||
// Not currently used
|
||||
}
|
||||
|
||||
public void GLMakeContextCurrent(WindowReg? reg)
|
||||
{
|
||||
SDL.SDLBool res;
|
||||
if (reg is Sdl3WindowReg sdlReg)
|
||||
res = SDL.SDL_GL_MakeCurrent(sdlReg.Sdl3Window, sdlReg.GlContext);
|
||||
else
|
||||
res = SDL.SDL_GL_MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
if (!res)
|
||||
_sawmill.Error("SDL_GL_MakeCurrent failed: {error}", SDL.SDL_GetError());
|
||||
}
|
||||
|
||||
public void GLSwapInterval(WindowReg reg, int interval)
|
||||
{
|
||||
((Sdl3WindowReg)reg).SwapInterval = interval;
|
||||
SDL.SDL_GL_SetSwapInterval(interval);
|
||||
}
|
||||
|
||||
public unsafe void* GLGetProcAddress(string procName)
|
||||
{
|
||||
return (void*) SDL.SDL_GL_GetProcAddress(procName);
|
||||
}
|
||||
|
||||
public string GetDescription()
|
||||
{
|
||||
var version = SDL.SDL_GetVersion();
|
||||
@@ -224,7 +202,8 @@ internal partial class Clyde
|
||||
// These are the ones we need to be able to check against.
|
||||
Other,
|
||||
Windows,
|
||||
X11
|
||||
X11,
|
||||
Wayland
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,9 +63,6 @@ namespace Robust.Client.Graphics
|
||||
|
||||
void Shutdown();
|
||||
|
||||
/// <returns>Null if not running on X11.</returns>
|
||||
uint? GetX11WindowId();
|
||||
|
||||
void RegisterGridEcsEvents();
|
||||
|
||||
void ShutdownGridEcsEvents();
|
||||
|
||||
@@ -69,6 +69,5 @@ namespace Robust.Client.Graphics
|
||||
|
||||
public interface IClydeWindowInternal : IClydeWindow
|
||||
{
|
||||
nint? WindowsHWnd { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,6 @@ public abstract class Texture : IRsiStateLike
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract Color GetPixel(int x, int y);
|
||||
|
||||
public static Texture Transparent =>
|
||||
IoCManager.Resolve<IClydeInternal>().GetStockTexture(ClydeStockTexture.Transparent);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Audio;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared;
|
||||
@@ -23,7 +24,6 @@ namespace Robust.Client.ResourceManagement
|
||||
internal partial class ResourceCache
|
||||
{
|
||||
[field: Dependency] public IClyde Clyde { get; } = default!;
|
||||
[field: Dependency] public IAudioInternal ClydeAudio { get; } = default!;
|
||||
[Dependency] private readonly IResourceManager _manager = default!;
|
||||
[field: Dependency] public IFontManager FontManager { get; } = default!;
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
@@ -215,6 +215,7 @@ namespace Robust.Client.ResourceManagement
|
||||
Array.Sort(atlasList, (b, a) => a.AtlasSheet.Height.CompareTo(b.AtlasSheet.Height));
|
||||
|
||||
var maxSize = _configurationManager.GetCVar(CVars.ResRSIAtlasSize);
|
||||
maxSize = Math.Min((int)Clyde.Rhi.DeviceLimits.MaxTextureDimension2D, maxSize);
|
||||
|
||||
// THIS IS NOT GUARANTEED TO HAVE ANY PARTICULARLY LOGICAL ORDERING.
|
||||
// E.G you could have atlas 1 RSIs appear *before* you're done seeing atlas 2 RSIs.
|
||||
|
||||
@@ -45,9 +45,9 @@ namespace Robust.Client.UserInterface.CustomControls.DebugMonitorControls
|
||||
var stats = _clydeInternal.DebugStats;
|
||||
|
||||
_textBuilder.AppendLine($@"RHI: {rhi.Description}
|
||||
Adapter: {rhi.AdapterInfo.Name}
|
||||
Vendor: {rhi.AdapterInfo.VendorName} ({rhi.AdapterInfo.VendorID})
|
||||
Driver: {rhi.AdapterInfo.Driver}");
|
||||
Adapter: {rhi.AdapterInfo.Device}
|
||||
Vendor: {rhi.AdapterInfo.Vendor} ({rhi.AdapterInfo.VendorID})
|
||||
Driver: {rhi.AdapterInfo.Description}");
|
||||
|
||||
_textBuilder.Append($"Windowing: {info.WindowingApi}\n");
|
||||
|
||||
|
||||
@@ -112,14 +112,14 @@ internal sealed partial class DevWindowTabRenderTargets : Control
|
||||
|
||||
if (loaded.Name != null)
|
||||
AddColumnText(loaded.Name);
|
||||
else if (loaded.WindowId != WindowId.Invalid)
|
||||
AddColumnText(loaded.WindowId.ToString());
|
||||
else if (loaded.Window != null)
|
||||
AddColumnText(loaded.Window.Id.ToString());
|
||||
else
|
||||
AddColumnText(_loc.GetString("dev-window-tab-render-targets-value-null"));
|
||||
|
||||
AddColumnText(loaded.Size.ToString());
|
||||
var type = loaded.ColorFormat.ToString();
|
||||
if (loaded.DepthStencilHandle != default)
|
||||
if (loaded.DepthStencilTexture != null)
|
||||
type += "+DS";
|
||||
AddColumnText(type);
|
||||
AddColumnText(ByteHelpers.FormatBytes(loaded.MemoryPressure));
|
||||
|
||||
@@ -32,9 +32,9 @@ public sealed partial class DevWindowTabRenderer : Control
|
||||
|
||||
var adapter = rhi.AdapterInfo;
|
||||
|
||||
Add("Adapter name", adapter.Name);
|
||||
Add("Adapter vendor", $"{adapter.VendorName} ({adapter.VendorID})");
|
||||
Add("Adapter driver", $"{adapter.Driver}");
|
||||
Add("Adapter name", adapter.Device);
|
||||
Add("Adapter vendor", $"{adapter.Vendor} ({adapter.VendorID})");
|
||||
Add("Adapter driver", $"{adapter.Description}");
|
||||
Add("Adapter architecture", $"{adapter.Architecture}");
|
||||
Add("Adapter backend", $"{adapter.BackendType}");
|
||||
Add("Adapter type", $"{adapter.AdapterType}");
|
||||
@@ -70,7 +70,6 @@ public sealed partial class DevWindowTabRenderer : Control
|
||||
Add("MaxBufferSize", limits.MaxBufferSize);
|
||||
Add("MaxVertexAttributes", limits.MaxVertexAttributes);
|
||||
Add("MaxVertexBufferArrayStride", limits.MaxVertexBufferArrayStride);
|
||||
Add("MaxInterStageShaderComponents", limits.MaxInterStageShaderComponents);
|
||||
Add("MaxInterStageShaderVariables", limits.MaxInterStageShaderVariables);
|
||||
Add("MaxColorAttachments", limits.MaxColorAttachments);
|
||||
Add("MaxColorAttachmentBytesPerSample", limits.MaxColorAttachmentBytesPerSample);
|
||||
|
||||
@@ -92,7 +92,7 @@ internal sealed partial class DevWindowTabTextures : Control
|
||||
SelectedTextureInfo.Text = _loc.GetString("dev-window-tab-textures-info",
|
||||
("width", loaded.Width),
|
||||
("height", loaded.Height),
|
||||
("pixelType", loaded.TexturePixelType),
|
||||
("pixelType", loaded.Format),
|
||||
("srgb", loaded.IsSrgb),
|
||||
("name", loaded.Name ?? ""),
|
||||
("bytes", ByteHelpers.FormatBytes(loaded.MemoryPressure)));
|
||||
|
||||
@@ -1,35 +1,15 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.UserInterface
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "IdentifierTypo")]
|
||||
[SuppressMessage("ReSharper", "CommentTypo")]
|
||||
[SuppressMessage("ReSharper", "StringLiteralTypo")]
|
||||
internal sealed class FileDialogManager : IFileDialogManager, IPostInjectInit
|
||||
internal sealed class FileDialogManager : IFileDialogManager
|
||||
{
|
||||
// Uses nativefiledialog to open the file dialogs cross platform.
|
||||
// On Linux, if the kdialog command is found, it will be used instead.
|
||||
// TODO: Should we maybe try to avoid running kdialog if the DE isn't KDE?
|
||||
[Dependency] private readonly IClydeInternal _clyde = default!;
|
||||
[Dependency] private readonly ILogManager _log = default!;
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
private bool _kDialogAvailable;
|
||||
private bool _checkedKDialogAvailable;
|
||||
|
||||
public async Task<Stream?> OpenFile(
|
||||
FileDialogFilters? filters = null,
|
||||
@@ -47,7 +27,7 @@ namespace Robust.Client.UserInterface
|
||||
if (_clyde.FileDialogImpl is { } clydeImpl)
|
||||
name = await clydeImpl.OpenFile(filters);
|
||||
else
|
||||
name = await GetOpenFileName(filters);
|
||||
throw new NotSupportedException();
|
||||
|
||||
if (name == null)
|
||||
return null;
|
||||
@@ -55,16 +35,6 @@ namespace Robust.Client.UserInterface
|
||||
return File.Open(name, FileMode.Open, access, realShare);
|
||||
}
|
||||
|
||||
private async Task<string?> GetOpenFileName(FileDialogFilters? filters)
|
||||
{
|
||||
if (await IsKDialogAvailable())
|
||||
{
|
||||
return await OpenFileKDialog(filters);
|
||||
}
|
||||
|
||||
return await OpenFileNfd(filters);
|
||||
}
|
||||
|
||||
public async Task<(Stream, bool)?> SaveFile(
|
||||
FileDialogFilters? filters,
|
||||
bool truncate = true,
|
||||
@@ -81,7 +51,7 @@ namespace Robust.Client.UserInterface
|
||||
if (_clyde.FileDialogImpl is { } clydeImpl)
|
||||
name = await clydeImpl.SaveFile(filters);
|
||||
else
|
||||
name = await GetSaveFileName(filters);
|
||||
throw new NotSupportedException();
|
||||
|
||||
if (name == null)
|
||||
return null;
|
||||
@@ -95,329 +65,6 @@ namespace Robust.Client.UserInterface
|
||||
return (File.Open(name, FileMode.Create, access, share), false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string?> GetSaveFileName(FileDialogFilters? filters)
|
||||
{
|
||||
if (await IsKDialogAvailable())
|
||||
{
|
||||
return await SaveFileKDialog(filters);
|
||||
}
|
||||
|
||||
return await SaveFileNfd(filters);
|
||||
}
|
||||
|
||||
private unsafe Task<string?> OpenFileNfd(FileDialogFilters? filters)
|
||||
{
|
||||
// Have to run it in the thread pool to avoid blocking the main thread.
|
||||
return RunAsyncMaybe(() =>
|
||||
{
|
||||
byte* outPath;
|
||||
|
||||
var filterPtr = FormatFiltersNfd(filters);
|
||||
|
||||
sw_nfdresult result;
|
||||
|
||||
try
|
||||
{
|
||||
result = sw_NFD_OpenDialog((byte*)filterPtr, null, &outPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (filterPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(filterPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return HandleNfdResult(result, outPath);
|
||||
});
|
||||
}
|
||||
|
||||
private static IntPtr FormatFiltersNfd(FileDialogFilters? filters)
|
||||
{
|
||||
if (filters != null)
|
||||
{
|
||||
var filterString = string.Join(';', filters.Groups.Select(f => string.Join(',', f.Extensions)));
|
||||
|
||||
return Marshal.StringToCoTaskMemUTF8(filterString);
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private unsafe Task<string?> SaveFileNfd(FileDialogFilters? filters)
|
||||
{
|
||||
// Have to run it in the thread pool to avoid blocking the main thread.
|
||||
return RunAsyncMaybe(() =>
|
||||
{
|
||||
byte* outPath;
|
||||
|
||||
var filterPtr = FormatFiltersNfd(filters);
|
||||
|
||||
sw_nfdresult result;
|
||||
try
|
||||
{
|
||||
result = sw_NFD_SaveDialog((byte*) filterPtr, null, &outPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (filterPtr != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(filterPtr);
|
||||
}
|
||||
}
|
||||
|
||||
return HandleNfdResult(result, outPath);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
private unsafe Task<string?> OpenFolderNfd()
|
||||
{
|
||||
// Have to run it in the thread pool to avoid blocking the main thread.
|
||||
return RunAsyncMaybe(() =>
|
||||
{
|
||||
byte* outPath;
|
||||
|
||||
var result = sw_NFD_PickFolder(null, &outPath);
|
||||
|
||||
return HandleNfdResult(result, outPath);
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
// ReSharper disable once MemberCanBeMadeStatic.Local
|
||||
private Task<string?> RunAsyncMaybe(Func<string?> action)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
// macOS seems pretty annoying about having the file dialog opened from the main windowing thread.
|
||||
// So we are forced to execute this synchronously on the main windowing thread.
|
||||
// nativefiledialog doesn't provide any form of async API, so this WILL lock up half the client.
|
||||
var tcs = new TaskCompletionSource<string?>();
|
||||
_clyde.RunOnWindowThread(() => tcs.SetResult(action()));
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Luckily, GTK Linux and COM Windows are both happily threaded. Yay!
|
||||
// * Actual attempts to have multiple file dialogs up at the same time, and the resulting crashes,
|
||||
// have shown that at least for GTK+ (Linux), just because it can handle being on any thread doesn't mean it handle being on two at the same time.
|
||||
// Testing system was Ubuntu 20.04.
|
||||
// COM on Windows might handle this, but honestly, who exactly wants to risk it?
|
||||
// In particular this could very well be an swnfd issue.
|
||||
return Task.Run(() =>
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
return action();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe string? HandleNfdResult(sw_nfdresult result, byte* outPath)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case sw_nfdresult.SW_NFD_ERROR:
|
||||
var errPtr = sw_NFD_GetError();
|
||||
throw new Exception(Marshal.PtrToStringUTF8((IntPtr) errPtr));
|
||||
|
||||
case sw_nfdresult.SW_NFD_OKAY:
|
||||
var str = Marshal.PtrToStringUTF8((IntPtr) outPath)!;
|
||||
|
||||
sw_NFD_Free(outPath);
|
||||
return str;
|
||||
|
||||
case sw_nfdresult.SW_NFD_CANCEL:
|
||||
return null;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CheckKDialogSupport()
|
||||
{
|
||||
var currentDesktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
|
||||
if (currentDesktop == null || !currentDesktop.Contains("KDE"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var process = Process.Start(
|
||||
new ProcessStartInfo
|
||||
{
|
||||
FileName = "kdialog",
|
||||
Arguments = "--version",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false
|
||||
});
|
||||
|
||||
if (process == null)
|
||||
{
|
||||
_kDialogAvailable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
_kDialogAvailable = process.ExitCode == 0;
|
||||
|
||||
if (_kDialogAvailable)
|
||||
{
|
||||
_sawmill.Debug("kdialog available.");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_kDialogAvailable = false;
|
||||
}
|
||||
}
|
||||
|
||||
private Task<string?> OpenFileKDialog(FileDialogFilters? filters)
|
||||
{
|
||||
var filtersFormatted = FormatFiltersKDialog(filters);
|
||||
|
||||
return RunKDialog("--getopenfilename", Environment.GetEnvironmentVariable("HOME")!, filtersFormatted);
|
||||
}
|
||||
|
||||
private static string FormatFiltersKDialog(FileDialogFilters? filters)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (filters != null && filters.Groups.Count != 0)
|
||||
{
|
||||
var first = true;
|
||||
foreach (var group in filters.Groups)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
sb.Append('|');
|
||||
}
|
||||
|
||||
foreach (var extension in @group.Extensions)
|
||||
{
|
||||
sb.AppendFormat(".{0} ", extension);
|
||||
}
|
||||
|
||||
sb.Append('(');
|
||||
|
||||
foreach (var extension in @group.Extensions)
|
||||
{
|
||||
sb.AppendFormat("*.{0} ", extension);
|
||||
}
|
||||
|
||||
sb.Append(')');
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
sb.Append("| All Files (*)");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private Task<string?> SaveFileKDialog(FileDialogFilters? filters)
|
||||
{
|
||||
var filtersFormatted = FormatFiltersKDialog(filters);
|
||||
|
||||
return RunKDialog("--getsavefilename", Environment.GetEnvironmentVariable("HOME")!, filtersFormatted);
|
||||
}
|
||||
|
||||
/*
|
||||
private Task<string?> OpenFolderKDialog()
|
||||
{
|
||||
return RunKDialog("--getexistingdirectory");
|
||||
}
|
||||
*/
|
||||
|
||||
private async Task<string?> RunKDialog(params string[] options)
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "kdialog",
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
StandardOutputEncoding = EncodingHelpers.UTF8
|
||||
};
|
||||
|
||||
foreach (var option in options)
|
||||
{
|
||||
startInfo.ArgumentList.Add(option);
|
||||
}
|
||||
|
||||
if (_clyde.GetX11WindowId() is { } id)
|
||||
{
|
||||
startInfo.ArgumentList.Add("--attach");
|
||||
startInfo.ArgumentList.Add(id.ToString());
|
||||
}
|
||||
|
||||
var process = Process.Start(startInfo);
|
||||
|
||||
DebugTools.AssertNotNull(process);
|
||||
|
||||
await process!.WaitForExitAsync();
|
||||
|
||||
// Cancel hit.
|
||||
if (process.ExitCode == 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (await process.StandardOutput.ReadLineAsync())?.Trim();
|
||||
}
|
||||
|
||||
private async Task<bool> IsKDialogAvailable()
|
||||
{
|
||||
if (!OperatingSystem.IsLinux())
|
||||
return false;
|
||||
|
||||
if (!_checkedKDialogAvailable)
|
||||
{
|
||||
await CheckKDialogSupport();
|
||||
_checkedKDialogAvailable = true;
|
||||
}
|
||||
|
||||
return _kDialogAvailable;
|
||||
}
|
||||
|
||||
[DllImport("swnfd.dll")]
|
||||
private static extern unsafe byte* sw_NFD_GetError();
|
||||
|
||||
[DllImport("swnfd.dll")]
|
||||
private static extern unsafe sw_nfdresult
|
||||
sw_NFD_OpenDialog(byte* filterList, byte* defaultPath, byte** outPath);
|
||||
|
||||
[DllImport("swnfd.dll")]
|
||||
private static extern unsafe sw_nfdresult
|
||||
sw_NFD_SaveDialog(byte* filterList, byte* defaultPath, byte** outPath);
|
||||
|
||||
/*
|
||||
[DllImport("swnfd.dll")]
|
||||
private static extern unsafe sw_nfdresult
|
||||
sw_NFD_PickFolder(byte* defaultPath, byte** outPath);
|
||||
*/
|
||||
|
||||
[DllImport("swnfd.dll")]
|
||||
private static extern unsafe void sw_NFD_Free(void* ptr);
|
||||
|
||||
public void PostInject()
|
||||
{
|
||||
_sawmill = _log.GetSawmill("filedialog");
|
||||
}
|
||||
|
||||
private enum sw_nfdresult
|
||||
{
|
||||
SW_NFD_ERROR,
|
||||
SW_NFD_OKAY,
|
||||
SW_NFD_CANCEL,
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OpenFileCommand : LocalizedCommands
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
[assembly: InternalsVisibleTo("Robust.Client.Graphics.Rhi")]
|
||||
[assembly: InternalsVisibleTo("Robust.Server")]
|
||||
[assembly: InternalsVisibleTo("Robust.Shared")]
|
||||
[assembly: InternalsVisibleTo("Robust.UnitTesting")]
|
||||
|
||||
@@ -1385,7 +1385,7 @@ namespace Robust.Shared
|
||||
/// the purpose of using an atlas if it gets too small.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<int> ResRSIAtlasSize =
|
||||
CVarDef.Create("res.rsi_atlas_size", 12288, CVar.CLIENTONLY);
|
||||
CVarDef.Create("res.rsi_atlas_size", 16384, CVar.CLIENTONLY);
|
||||
|
||||
// TODO: Currently unimplemented.
|
||||
/// <summary>
|
||||
|
||||
179
native/Cargo.lock
generated
179
native/Cargo.lock
generated
@@ -78,7 +78,7 @@ version = "0.72.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools 0.13.0",
|
||||
@@ -107,20 +107,11 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
@@ -211,8 +202,6 @@ version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
@@ -227,9 +216,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -243,11 +232,11 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.3"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
|
||||
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"libc",
|
||||
]
|
||||
@@ -363,6 +352,12 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
@@ -444,7 +439,7 @@ version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"gpu-alloc-types",
|
||||
]
|
||||
|
||||
@@ -454,7 +449,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -475,7 +470,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"gpu-descriptor-types",
|
||||
"hashbrown 0.15.5",
|
||||
]
|
||||
@@ -486,7 +481,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -506,7 +501,7 @@ version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"foldhash",
|
||||
"foldhash 0.1.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -514,12 +509,9 @@ name = "hashbrown"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hexf-parse"
|
||||
@@ -804,11 +796,11 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e"
|
||||
checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"block",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
@@ -834,18 +826,21 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "25.0.1"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b2e757b11b47345d44e7760e45458339bc490463d9548cd8651c53ae523153"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"codespan-reporting",
|
||||
"half",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
"hexf-parse",
|
||||
"indexmap",
|
||||
"libm",
|
||||
"log",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
@@ -853,16 +848,15 @@ dependencies = [
|
||||
"pp-rs",
|
||||
"rustc-hash 1.1.0",
|
||||
"spirv",
|
||||
"strum",
|
||||
"thiserror 2.0.17",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk-sys"
|
||||
version = "0.5.0+25.2.9519653"
|
||||
version = "0.6.0+11769913"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
|
||||
checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873"
|
||||
dependencies = [
|
||||
"jni-sys",
|
||||
]
|
||||
@@ -965,7 +959,6 @@ dependencies = [
|
||||
"fixedbitset",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1056,7 +1049,7 @@ version = "0.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1158,36 +1151,6 @@ version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha3"
|
||||
version = "0.10.8"
|
||||
@@ -1231,7 +1194,7 @@ version = "0.3.0+sdk-1.3.268.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1246,28 +1209,6 @@ dependencies = [
|
||||
"precomputed-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
@@ -1288,15 +1229,6 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
@@ -1506,17 +1438,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "25.0.2"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d654c0b6c6335edfca18c11bdaed964def641b8e9997d3a495a2ff4077c922"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"bytemuck",
|
||||
"cfg_aliases",
|
||||
"document-features",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
"indexmap",
|
||||
"log",
|
||||
"naga",
|
||||
@@ -1536,38 +1469,42 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core-deps-apple"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233"
|
||||
dependencies = [
|
||||
"wgpu-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core-deps-emscripten"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5"
|
||||
dependencies = [
|
||||
"wgpu-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core-deps-windows-linux-android"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3"
|
||||
dependencies = [
|
||||
"wgpu-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "25.0.2"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2618a2d6b8a5964ecc1ac32a5db56cb3b1e518725fcd773fd9a782e023453f2b"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"arrayvec",
|
||||
"ash",
|
||||
"bit-set",
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"block",
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
@@ -1578,7 +1515,7 @@ dependencies = [
|
||||
"gpu-alloc",
|
||||
"gpu-allocator",
|
||||
"gpu-descriptor",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
"js-sys",
|
||||
"khronos-egl",
|
||||
"libc",
|
||||
@@ -1588,6 +1525,7 @@ dependencies = [
|
||||
"naga",
|
||||
"ndk-sys",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"ordered-float",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
@@ -1608,7 +1546,7 @@ name = "wgpu-native"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"log",
|
||||
"naga",
|
||||
"parking_lot",
|
||||
@@ -1623,10 +1561,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "25.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?tag=v25.0.2#f35cf942af1a3bb6f48aa9185f4d2bcee809f814"
|
||||
version = "27.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"bitflags",
|
||||
"bytemuck",
|
||||
"js-sys",
|
||||
"log",
|
||||
|
||||
Reference in New Issue
Block a user