private static (GraphicsDevice gd, Swapchain sc) CreateDeviceAndSwapchain( Sdl2Window window, VRContext vrc, GraphicsBackend backend, GraphicsDeviceOptions gdo) { if (backend == GraphicsBackend.Vulkan) { (string[] instance, string[] device) = vrc.GetRequiredVulkanExtensions(); var vdo = new VulkanDeviceOptions(instance, device); var gd = GraphicsDevice.CreateVulkan(gdo, vdo); var swd = new SwapchainDescription( VeldridStartup.GetSwapchainSource(window), (uint)window.Width, (uint)window.Height, gdo.SwapchainDepthFormat, gdo.SyncToVerticalBlank, true); var sc = gd.ResourceFactory.CreateSwapchain(swd); return(gd, sc); } else { var gd = VeldridStartup.CreateGraphicsDevice(window, gdo, backend); var sc = gd.MainSwapchain; return(gd, sc); } }
public D3D11GraphicsDevice(GraphicsDeviceOptions options, SwapchainDescription?swapchainDesc) { #if DEBUG DeviceCreationFlags creationFlags = DeviceCreationFlags.Debug; #else DeviceCreationFlags creationFlags = options.Debug ? DeviceCreationFlags.Debug : DeviceCreationFlags.None; #endif _device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, creationFlags); if (swapchainDesc != null) { SwapchainDescription desc = swapchainDesc.Value; _mainSwapchain = new D3D11Swapchain(_device, ref desc); } _immediateContext = _device.ImmediateContext; _device.CheckThreadingSupport(out _supportsConcurrentResources, out _supportsCommandLists); Features = new GraphicsDeviceFeatures( computeShader: true, geometryShader: true, tessellationShaders: true, multipleViewports: true, samplerLodBias: true, drawBaseVertex: true, drawBaseInstance: true, fillModeWireframe: true, samplerAnisotropy: true, depthClipDisable: true, texture1D: true, independentBlend: true); _d3d11ResourceFactory = new D3D11ResourceFactory(this); PostDeviceCreated(); }
public VeldridControl(GraphicsDevice graphics, GraphicsDeviceOptions options) { SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); DoubleBuffered = false; var hWnd = Handle; // Will call CreateHandle internally var hInstance = HInstance; uint w = (uint)Width, h = (uint)Height; if (w <= 0) { w = 1; } if (h <= 0) { h = 1; } var source = SwapchainSource.CreateWin32(hWnd, hInstance); var desc = new SwapchainDescription(source, w, h, options.SwapchainDepthFormat, options.SyncToVerticalBlank); Swapchain = graphics.ResourceFactory.CreateSwapchain(desc); Camera = new PerspectiveCamera(Width, Height); }
public override void ViewDidLoad() { base.ViewDidLoad(); SwapchainSource ss = SwapchainSource.CreateUIView(this.View.Handle); SwapchainDescription scd = new SwapchainDescription( ss, (uint)View.Frame.Width, (uint)View.Frame.Height, PixelFormat.R32_Float, false); if (_backend == GraphicsBackend.Metal) { _gd = GraphicsDevice.CreateMetal(_options); _sc = _gd.ResourceFactory.CreateSwapchain(ref scd); } else if (_backend == GraphicsBackend.OpenGLES) { _gd = GraphicsDevice.CreateOpenGLES(_options, scd); _sc = _gd.MainSwapchain; } else if (_backend == GraphicsBackend.Vulkan) { throw new NotImplementedException(); } GraphicsDeviceCreated?.Invoke(_gd, _gd.ResourceFactory, _sc); _viewLoaded = true; }
public override Swapchain CreateSwapchain(ref SwapchainDescription description) { Swapchain sc = Factory.CreateSwapchain(ref description); DisposeCollector.Add(sc); return(sc); }
private static GraphicsDevice Init(GraphicsBackend backend, GraphicsDeviceOptions options, SwapchainSource swapchainSource, uint startWidth, uint startHeight) { if (!GraphicsDevice.IsBackendSupported(backend) || backend == GraphicsBackend.OpenGL) { throw new NotSupportedException($"Graphics backend {backend} is not supported on this system."); } if (swapchainSource is null) { throw new ArgumentNullException(nameof(swapchainSource)); } var swapchainDescription = new SwapchainDescription { Source = swapchainSource, Width = startWidth, Height = startHeight, DepthFormat = options.SwapchainDepthFormat, SyncToVerticalBlank = options.SyncToVerticalBlank, ColorSrgb = options.SwapchainSrgbFormat }; var device = backend switch { GraphicsBackend.Direct3D11 => GraphicsDevice.CreateD3D11(options, swapchainDescription), GraphicsBackend.Metal => GraphicsDevice.CreateMetal(options, swapchainDescription), GraphicsBackend.Vulkan => GraphicsDevice.CreateVulkan(options, swapchainDescription), GraphicsBackend.OpenGLES => GraphicsDevice.CreateOpenGLES(options, swapchainDescription), _ => throw new InvalidOperationException($"Can't create a device for GraphicsBackend value: {backend}") }; return(device); }
public D3D11GraphicsDevice(GraphicsDeviceOptions options, SwapchainDescription?swapchainDesc) { DeviceCreationFlags flags = DeviceCreationFlags.None; bool debug = options.Debug; #if DEBUG debug = true; #endif if (debug) { flags = DeviceCreationFlags.Debug; } try { _device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, flags); } catch (SharpDXException ex) when(debug && (uint)ex.HResult == 0x887A002D) { // The D3D11 debug layer is not installed. Create a normal device without debug support, instead. _device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.None); } if (swapchainDesc != null) { SwapchainDescription desc = swapchainDesc.Value; _mainSwapchain = new D3D11Swapchain(_device, ref desc); } _immediateContext = _device.ImmediateContext; _device.CheckThreadingSupport(out _supportsConcurrentResources, out _supportsCommandLists); Features = new GraphicsDeviceFeatures( computeShader: true, geometryShader: true, tessellationShaders: true, multipleViewports: true, samplerLodBias: true, drawBaseVertex: true, drawBaseInstance: true, drawIndirect: true, drawIndirectBaseInstance: true, fillModeWireframe: true, samplerAnisotropy: true, depthClipDisable: true, texture1D: true, independentBlend: true, structuredBuffer: true, subsetTextureView: true, commandListDebugMarkers: _device.FeatureLevel >= SharpDX.Direct3D.FeatureLevel.Level_11_1); _d3d11ResourceFactory = new D3D11ResourceFactory(this); PostDeviceCreated(); }
public static void InitDevice(SwapchainDescription swapchainDescription) { GraphicsDeviceOptions options = new GraphicsDeviceOptions( debug: false, swapchainDepthFormat: null, syncToVerticalBlank: false, resourceBindingModel: ResourceBindingModel.Improved, preferDepthRangeZeroToOne: true, preferStandardClipSpaceYDirection: true); Device = GraphicsDevice.CreateOpenGLES(options, swapchainDescription); }
public override void ViewDidLoad() { base.ViewDidLoad(); View.BackgroundColor = UIColor.SystemPinkColor; // device init GraphicsDeviceOptions options = new GraphicsDeviceOptions(false, null, false, ResourceBindingModel.Improved); #if DEBUG options.Debug = true; #endif SwapchainSource ss = SwapchainSource.CreateUIView(this.View.Handle); SwapchainDescription scd = new SwapchainDescription( ss, width, height, PixelFormat.R32_Float, false); graphicsDevice = GraphicsDevice.CreateMetal(options); swapchain = graphicsDevice.ResourceFactory.CreateSwapchain(ref scd); factory = graphicsDevice.ResourceFactory; // resource init CreateSizeDependentResources(); VertexPosition[] quadVertices = { new VertexPosition(new Vector3(-1, 1, 0)), new VertexPosition(new Vector3(1, 1, 0)), new VertexPosition(new Vector3(-1, -1, 0)), new VertexPosition(new Vector3(1, -1, 0)) }; uint[] quadIndices = new uint[] { 0, 1, 2, 1, 3, 2 }; vertexBuffer = factory.CreateBuffer(new BufferDescription(4 * VertexPosition.SizeInBytes, BufferUsage.VertexBuffer)); indexBuffer = factory.CreateBuffer(new BufferDescription(6 * sizeof(uint), BufferUsage.IndexBuffer)); graphicsDevice.UpdateBuffer(vertexBuffer, 0, quadVertices); graphicsDevice.UpdateBuffer(indexBuffer, 0, quadIndices); commandList = factory.CreateCommandList(); viewLoaded = true; displayLink = CADisplayLink.Create(Render); displayLink.PreferredFramesPerSecond = 60; displayLink.AddToRunLoop(NSRunLoop.Main, NSRunLoop.NSDefaultRunLoopMode); }
protected virtual void CreateSwapchain() { var dpiScale = GetDpiScale(); var width = (uint)(ActualWidth < 0 ? 0 : Math.Ceiling(ActualWidth * dpiScale)); var height = (uint)(ActualHeight < 0 ? 0 : Math.Ceiling(ActualHeight * dpiScale)); var mainModule = typeof(VeldridComponent).Module; var hinstance = Marshal.GetHINSTANCE(mainModule); var win32Source = SwapchainSource.CreateWin32(Hwnd, hinstance); var scDesc = new SwapchainDescription(win32Source, width, height, PixelFormat.R32_Float, true); _sc = _gd.ResourceFactory.CreateSwapchain(scDesc); }
public MTLSwapchain(MTLGraphicsDevice gd, ref SwapchainDescription description) { _gd = gd; SyncToVerticalBlank = description.SyncToVerticalBlank; _metalLayer = CAMetalLayer.New(); uint width; uint height; SwapchainSource source = description.Source; if (source is NSWindowSwapchainSource nsWindowSource) { NSWindow nswindow = new NSWindow(nsWindowSource.NSWindow); CGSize windowContentSize = nswindow.contentView.frame.size; width = (uint)windowContentSize.width; height = (uint)windowContentSize.height; NSView contentView = nswindow.contentView; contentView.wantsLayer = true; contentView.layer = _metalLayer.NativePtr; } else if (source is UIViewSwapchainSource uiViewSource) { _uiView = new UIView(uiViewSource.UIView); CGSize viewSize = _uiView.frame.size; width = (uint)viewSize.width; height = (uint)viewSize.height; _metalLayer.frame = _uiView.frame; _metalLayer.opaque = true; _uiView.layer.addSublayer(_metalLayer.NativePtr); } else { throw new VeldridException($"A Metal Swapchain can only be created from an NSWindow or UIView."); } _metalLayer.device = _gd.Device; _metalLayer.pixelFormat = MTLPixelFormat.BGRA8Unorm; _metalLayer.framebufferOnly = true; _metalLayer.drawableSize = new CGSize(width, height); GetNextDrawable(); _framebuffer = new MTLSwapchainFramebuffer( gd, this, width, height, description.DepthFormat, PixelFormat.B8_G8_R8_A8_UNorm); }
public override void ViewDidLoad() { base.ViewDidLoad(); // device init GraphicsDeviceOptions options = new GraphicsDeviceOptions(false, null, false, ResourceBindingModel.Improved); #if DEBUG options.Debug = true; #endif SwapchainSource ss = SwapchainSource.CreateNSView(this.View.Handle); SwapchainDescription scd = new SwapchainDescription( ss, width, height, PixelFormat.R32_Float, false); graphicsDevice = GraphicsDevice.CreateMetal(options); swapchain = graphicsDevice.ResourceFactory.CreateSwapchain(ref scd); factory = graphicsDevice.ResourceFactory; // resource init CreateSizeDependentResources(); VertexPosition[] quadVertices = { new VertexPosition(new Vector3(-1, 1, 0)), new VertexPosition(new Vector3(1, 1, 0)), new VertexPosition(new Vector3(-1, -1, 0)), new VertexPosition(new Vector3(1, -1, 0)) }; uint[] quadIndices = new uint[] { 0, 1, 2, 1, 3, 2 }; vertexBuffer = factory.CreateBuffer(new BufferDescription(4 * VertexPosition.SizeInBytes, BufferUsage.VertexBuffer)); indexBuffer = factory.CreateBuffer(new BufferDescription(6 * sizeof(uint), BufferUsage.IndexBuffer)); graphicsDevice.UpdateBuffer(vertexBuffer, 0, quadVertices); graphicsDevice.UpdateBuffer(indexBuffer, 0, quadIndices); commandList = factory.CreateCommandList(); viewLoaded = true; displayTimer = NSTimer.CreateRepeatingTimer(60.0 / 1000.0, Render); displayTimer.Fire(); }
private static GraphicsDevice CreateVulkanGraphicsDevice(Window window, GraphicsDeviceOptions options) { window.GetSize(out var width, out var height); var swapChainDescription = new SwapchainDescription( GetSwapchainSource(window.WindowHandle), (uint)width, (uint)height, options.SwapchainDepthFormat, false ); return(GraphicsDevice.CreateVulkan(options, swapChainDescription)); }
public static GraphicsDevice CreateDefaultD3D11GraphicsDevice( GraphicsDeviceOptions options, Sdl2Window window) { SwapchainSource source = GetSwapchainSource(window); SwapchainDescription swapchainDesc = new SwapchainDescription( source, (uint)window.Width, (uint)window.Height, options.SwapchainDepthFormat, options.SyncToVerticalBlank, options.SwapchainSrgbFormat); return(GraphicsDevice.CreateD3D11(options, swapchainDesc)); }
public VeldridImGuiWindow(GraphicsDevice gd, ImGuiViewportPtr vp) { _gcHandle = GCHandle.Alloc(this); _gd = gd; _vp = vp; SDL_WindowFlags flags = SDL_WindowFlags.Hidden; if ((vp.Flags & ImGuiViewportFlags.NoTaskBarIcon) != 0) { flags |= SDL_WindowFlags.SkipTaskbar; } if ((vp.Flags & ImGuiViewportFlags.NoDecoration) != 0) { flags |= SDL_WindowFlags.Borderless; } else { flags |= SDL_WindowFlags.Resizable; } if ((vp.Flags & ImGuiViewportFlags.TopMost) != 0) { flags |= SDL_WindowFlags.AlwaysOnTop; } _window = new Sdl2Window( "No Title Yet", (int)vp.Pos.X, (int)vp.Pos.Y, (int)vp.Size.X, (int)vp.Size.Y, flags, false); _window.Resized += () => _vp.PlatformRequestResize = true; _window.Moved += p => _vp.PlatformRequestMove = true; _window.Closed += () => _vp.PlatformRequestClose = true; SwapchainSource scSource = VeldridStartup.GetSwapchainSource(_window); SwapchainDescription scDesc = new SwapchainDescription(scSource, (uint)_window.Width, (uint)_window.Height, null, true, false); _sc = _gd.ResourceFactory.CreateSwapchain(scDesc); _window.Resized += () => _sc.Resize((uint)_window.Width, (uint)_window.Height); unsafe { ViewportDataPtr data = new ViewportDataPtr(Marshal.AllocHGlobal(Unsafe.SizeOf <ViewportDataPtr>())); vp.PlatformUserData = new HandleRef(data, (IntPtr)data.NativePtr).Handle; } vp.PlatformUserData = (IntPtr)_gcHandle; }
private void InitializeSubWindow(GraphicsDevice gd, Sdl2Window sdlWindow) { GcHandle = GCHandle.Alloc(this); graphicsDevice = gd; VSync = gd.SyncToVerticalBlank; window = sdlWindow; SwapchainSource scSrc = WindowStartup.GetSwapchainSource(sdlWindow); SwapchainDescription scDesc = new SwapchainDescription(scSrc, (uint)sdlWindow.Width, (uint)sdlWindow.Height, gd.SwapchainFramebuffer.OutputDescription.DepthAttachment?.Format, VSync); swapchain = gd.ResourceFactory.CreateSwapchain(scDesc); window.Resized += () => swapchain.Resize((uint)window.Width, (uint)window.Height); }
private static unsafe GraphicsDevice CreateMetalGraphicsDevice( GraphicsDeviceOptions options, Sdl2Window window, bool colorSrgb) { SwapchainSource source = GetSwapchainSource(window); SwapchainDescription swapchainDesc = new SwapchainDescription( source, (uint)window.Width, (uint)window.Height, options.SwapchainDepthFormat, options.SyncToVerticalBlank, colorSrgb); return(GraphicsDevice.CreateMetal(options, swapchainDesc)); }
public static unsafe GraphicsDevice CreateVulkanGraphicsDevice( GraphicsDeviceOptions options, Sdl2Window window, bool colorSrgb) { SwapchainDescription scDesc = new SwapchainDescription( GetSwapchainSource(window), (uint)window.Width, (uint)window.Height, options.SwapchainDepthFormat, options.SyncToVerticalBlank, colorSrgb); return(GraphicsDevice.CreateVulkan(options, scDesc, new VulkanDeviceOptions())); }
public VeldridControl(GraphicsBackend backend, GraphicsDeviceOptions deviceOptions) { if (!(backend == GraphicsBackend.Vulkan || backend == GraphicsBackend.OpenGL || backend == GraphicsBackend.Direct3D11)) { throw new NotSupportedException($"{backend} is not supported on windows."); } if (backend == GraphicsBackend.OpenGL) { throw new NotSupportedException($"{backend} is not currently implemented in this demo."); } _backend = backend; DeviceOptions = deviceOptions; SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); DoubleBuffered = false; NativeMethods.CreateWindow(Handle, MessageHandler, Width, Height, out var hwnd, out var hinstance); HWND = hwnd; HInstance = hinstance; if (_backend == GraphicsBackend.Vulkan) { GraphicsDevice = GraphicsDevice.CreateVulkan(deviceOptions); } else { GraphicsDevice = GraphicsDevice.CreateD3D11(deviceOptions); } const double dpiScale = 1; uint width = (uint)(Width < 0 ? 0 : Math.Ceiling(Width * dpiScale)); uint height = (uint)(Height < 0 ? 0 : Math.Ceiling(Height * dpiScale)); SwapchainSource swapchainSource = SwapchainSource.CreateWin32(HWND, HInstance); SwapchainDescription swapchainDescription = new SwapchainDescription(swapchainSource, width, height, PixelFormat.R32_Float, true); MainSwapchain = GraphicsDevice.ResourceFactory.CreateSwapchain(swapchainDescription); Disposed += OnDisposed; }
public void SurfaceCreated(ISurfaceHolder holder) { bool deviceCreated = false; if (_backend == GraphicsBackend.Vulkan) { if (GraphicsDevice == null) { SwapchainSource ss = SwapchainSource.CreateAndroidSurface(holder.Surface.Handle, JNIEnv.Handle); SwapchainDescription sd = new SwapchainDescription( ss, (uint)Width, (uint)Height, DeviceOptions.SwapchainDepthFormat, DeviceOptions.SyncToVerticalBlank); GraphicsDevice = GraphicsDevice.CreateVulkan(DeviceOptions, sd); deviceCreated = true; } Debug.Assert(MainSwapchain == null); MainSwapchain = GraphicsDevice.MainSwapchain; } else { Debug.Assert(GraphicsDevice == null && MainSwapchain == null); SwapchainSource ss = SwapchainSource.CreateAndroidSurface(holder.Surface.Handle, JNIEnv.Handle); SwapchainDescription sd = new SwapchainDescription( ss, (uint)Width, (uint)Height, DeviceOptions.SwapchainDepthFormat, DeviceOptions.SyncToVerticalBlank); GraphicsDevice = GraphicsDevice.CreateOpenGLES(DeviceOptions, sd); MainSwapchain = GraphicsDevice.MainSwapchain; deviceCreated = true; } if (deviceCreated) { DeviceCreated?.Invoke(); } _surfaceCreated = true; }
public override void MovedToWindow() { base.MovedToWindow(); var swapchainSource = SwapchainSource.CreateUIView(Handle); var swapchainDescription = new SwapchainDescription(swapchainSource, (uint)Frame.Width, (uint)Frame.Height, null, true, true); if (_backend == GraphicsBackend.Metal) { GraphicsDevice = GraphicsDevice.CreateMetal(_deviceOptions); } MainSwapchain = GraphicsDevice.ResourceFactory.CreateSwapchain(swapchainDescription); DeviceReady?.Invoke(); _displayLink = CADisplayLink.Create(HandleDisplayLinkOutputCallback); _displayLink.AddToRunLoop(NSRunLoop.Current, NSRunLoopMode.Default); }
public D3D11GraphicsDevice(GraphicsDeviceOptions options, SwapchainDescription?swapchainDesc) { #if DEBUG DeviceCreationFlags creationFlags = DeviceCreationFlags.Debug; #else DeviceCreationFlags creationFlags = options.Debug ? DeviceCreationFlags.Debug : DeviceCreationFlags.None; #endif _device = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, creationFlags); if (swapchainDesc != null) { SwapchainDescription desc = swapchainDesc.Value; _mainSwapchain = new D3D11Swapchain(_device, ref desc); } _immediateContext = _device.ImmediateContext; _device.CheckThreadingSupport(out _supportsConcurrentResources, out _supportsCommandLists); _d3d11ResourceFactory = new D3D11ResourceFactory(this); PostDeviceCreated(); }
public override void ViewDidMoveToWindow() { base.ViewDidMoveToWindow(); var swapchainSource = SwapchainSource.CreateNSView(Handle); var swapchainDescription = new SwapchainDescription(swapchainSource, (uint)Frame.Width, (uint)Frame.Height, null, true, true); if (_backend == GraphicsBackend.Metal) { GraphicsDevice = GraphicsDevice.CreateMetal(_deviceOptions); } MainSwapchain = GraphicsDevice.ResourceFactory.CreateSwapchain(swapchainDescription); DeviceReady?.Invoke(); _displayLink = new CVDisplayLink(); _displayLink.SetOutputCallback(HandleDisplayLinkOutputCallback); _displayLink.Start(); }
public static unsafe GraphicsDevice CreateVulkanGraphicsDevice( GraphicsDeviceOptions options, Sdl2Window window, bool colorSrgb) { SwapchainDescription scDesc = new SwapchainDescription( GetSwapchainSource(window), (uint)window.Width, (uint)window.Height, options.SwapchainDepthFormat, options.SyncToVerticalBlank, colorSrgb); VulkanDeviceOptions vkopts = new VulkanDeviceOptions(); vkopts.InstanceExtensions = new string[] { "VK_KHR_get_physical_device_properties2" }; vkopts.DeviceExtensions = new string[] { "VK_KHR_maintenance3", "VK_EXT_descriptor_indexing" }; GraphicsDevice gd = GraphicsDevice.CreateVulkan(options, scDesc, vkopts); return(gd); }
public void Ctor_SetsProperties(PixelFormat?depthFormat, bool syncToVerticalBlank) { Sdl2Window window = new Sdl2Window("SwapchainTestWindow", 0, 0, 100, 100, SDL_WindowFlags.Hidden, false); SwapchainSource source = VeldridStartup.GetSwapchainSource(window); SwapchainDescription swapchainDesc = new SwapchainDescription(source, 100, 100, depthFormat, syncToVerticalBlank); Swapchain swapchain = RF.CreateSwapchain(ref swapchainDesc); if (depthFormat == null) { Assert.Null(swapchain.Framebuffer.DepthTarget); } else { Assert.NotNull(swapchain.Framebuffer.DepthTarget); Assert.Equal(depthFormat, swapchain.Framebuffer.DepthTarget.Value.Target.Format); } Assert.Equal(syncToVerticalBlank, swapchain.SyncToVerticalBlank); window.Close(); }
public override Swapchain CreateSwapchain(ref SwapchainDescription description) { return(new D3D11Swapchain(_device, ref description)); }
public override Swapchain CreateSwapchain(ref SwapchainDescription description) { throw new NotSupportedException("OpenGL does not support creating Swapchain objects."); }
public abstract Swapchain CreateSwapchain(ref SwapchainDescription description);
public Swapchain CreateSwapchain(SwapchainDescription description) => CreateSwapchain(ref description);
public MTLGraphicsDevice( GraphicsDeviceOptions options, SwapchainDescription?swapchainDesc) { _device = MTLDevice.MTLCreateSystemDefaultDevice(); MetalFeatures = new MTLFeatureSupport(_device); Features = new GraphicsDeviceFeatures( computeShader: true, geometryShader: false, tessellationShaders: false, multipleViewports: MetalFeatures.IsSupported(MTLFeatureSet.macOS_GPUFamily1_v3), samplerLodBias: false, drawBaseVertex: true, drawBaseInstance: true, drawIndirect: true, drawIndirectBaseInstance: true, fillModeWireframe: true, samplerAnisotropy: true, depthClipDisable: true, texture1D: true, // TODO: Should be macOS 10.11+ and iOS 11.0+. independentBlend: true, structuredBuffer: true, subsetTextureView: true, commandListDebugMarkers: true, bufferRangeBinding: true); ResourceBindingModel = options.ResourceBindingModel; _libSystem = new NativeLibrary("libSystem.dylib"); _concreteGlobalBlock = _libSystem.LoadFunction <IntPtr>("_NSConcreteGlobalBlock"); if (MetalFeatures.IsMacOS) { _completionHandler = OnCommandBufferCompleted; } else { _completionHandler = OnCommandBufferCompleted_Static; } _completionHandlerFuncPtr = Marshal.GetFunctionPointerForDelegate <MTLCommandBufferHandler>(_completionHandler); _completionBlockDescriptor = Marshal.AllocHGlobal(Unsafe.SizeOf <BlockDescriptor>()); BlockDescriptor *descriptorPtr = (BlockDescriptor *)_completionBlockDescriptor; descriptorPtr->reserved = 0; descriptorPtr->Block_size = (ulong)Unsafe.SizeOf <BlockDescriptor>(); _completionBlockLiteral = Marshal.AllocHGlobal(Unsafe.SizeOf <BlockLiteral>()); BlockLiteral *blockPtr = (BlockLiteral *)_completionBlockLiteral; blockPtr->isa = _concreteGlobalBlock; blockPtr->flags = 1 << 28 | 1 << 29; blockPtr->invoke = _completionHandlerFuncPtr; blockPtr->descriptor = descriptorPtr; if (!MetalFeatures.IsMacOS) { lock (s_aotRegisteredBlocks) { s_aotRegisteredBlocks.Add(_completionBlockLiteral, this); } } ResourceFactory = new MTLResourceFactory(this); _commandQueue = _device.newCommandQueue(); TextureSampleCount[] allSampleCounts = (TextureSampleCount[])Enum.GetValues(typeof(TextureSampleCount)); _supportedSampleCounts = new bool[allSampleCounts.Length]; for (int i = 0; i < allSampleCounts.Length; i++) { TextureSampleCount count = allSampleCounts[i]; uint uintValue = FormatHelpers.GetSampleCountUInt32(count); if (_device.supportsTextureSampleCount((UIntPtr)uintValue)) { _supportedSampleCounts[i] = true; } } if (swapchainDesc != null) { SwapchainDescription desc = swapchainDesc.Value; _mainSwapchain = new MTLSwapchain(this, ref desc); } PostDeviceCreated(); }