public void TestChainLoadWithErrorTooLong() { var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = true }; // Load an unmanaged chain DeviceCreateInfo .Chain(out var unmanagedChain) .AddNext(out PhysicalDeviceFeatures2 features2) .SetNext(ref indexingFeatures) .AddNext(out PhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeaturesKhr); // Try loading a shorter managed chain using var managedChain = Chain.Load < DeviceCreateInfo, PhysicalDeviceFeatures2, PhysicalDeviceDescriptorIndexingFeatures>(out var errors, unmanagedChain); // Check for errors Assert.Equal(@"The unmanaged chain was longer than the expected length 3", errors); // Despite the errors indexing features was at the right location so was loaded Assert.True(managedChain.Item2.ShaderInputAttachmentArrayDynamicIndexing); }
public unsafe void TestChainLoad() { // Load an unmanaged chain var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = true }; PhysicalDeviceFeatures2 .Chain(out var unmanagedChain) .SetNext(ref indexingFeatures) .AddNext(out PhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeaturesKhr); // Loads a new managed chain from an unmanaged chain using var managedChain = Chain.Load <PhysicalDeviceFeatures2, PhysicalDeviceDescriptorIndexingFeatures, PhysicalDeviceAccelerationStructureFeaturesKHR>(out var errors, unmanagedChain); // Check we had no loading errors Assert.Equal("", errors); // Check the flag still set Assert.True(managedChain.Item1.ShaderInputAttachmentArrayDynamicIndexing); // Ensure all STypes set correctly Assert.Equal(StructureType.PhysicalDeviceFeatures2, managedChain.Head.SType); Assert.Equal(StructureType.PhysicalDeviceDescriptorIndexingFeatures, managedChain.Item1.SType); Assert.Equal(StructureType.PhysicalDeviceAccelerationStructureFeaturesKhr, managedChain.Item2.SType); // Ensure pointers set correctly Assert.Equal((nint)managedChain.Item1Ptr, (nint)managedChain.Head.PNext); Assert.Equal((nint)managedChain.Item2Ptr, (nint)managedChain.Item1.PNext); Assert.Equal(0, (nint)managedChain.Item2.PNext); }
public unsafe void TestSetNextUpdates() { var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = true }; PhysicalDeviceFeatures2 .Chain(out var features2) // SetNext accepts an existing struct, note, it will coerce the SType and blank the PNext .SetNext(ref indexingFeatures); Assert.Equal((nint)(&indexingFeatures), (nint)features2.PNext); Assert.Equal(0, (nint)indexingFeatures.PNext); Assert.Equal(StructureType.PhysicalDeviceFeatures2, features2.SType); Assert.Equal(StructureType.PhysicalDeviceDescriptorIndexingFeatures, indexingFeatures.SType); // Update indexing features var indexingFeatures2 = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = false }; features2.SetNext(ref indexingFeatures2); Assert.Equal((nint)(&indexingFeatures2), (nint)features2.PNext); Assert.Equal(0, (nint)indexingFeatures2.PNext); Assert.Equal(StructureType.PhysicalDeviceDescriptorIndexingFeatures, indexingFeatures2.SType); Assert.Equal(1, features2.IndexOf(ref indexingFeatures2)); Assert.True(features2.IndexOf(ref indexingFeatures) < 0); }
public unsafe void TestSetNext() { var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = true }; var accelerationStructureFeaturesKhr = new PhysicalDeviceAccelerationStructureFeaturesKHR { AccelerationStructure = true }; PhysicalDeviceFeatures2 .Chain(out var features2) // SetNext accepts an existing struct, note, it will coerce the SType and blank the PNext .SetNext(ref indexingFeatures) .SetNext(ref accelerationStructureFeaturesKhr); Assert.Equal((nint)(&indexingFeatures), (nint)features2.PNext); Assert.Equal((nint)(&accelerationStructureFeaturesKhr), (nint)indexingFeatures.PNext); Assert.Equal(0, (nint)accelerationStructureFeaturesKhr.PNext); Assert.Equal(StructureType.PhysicalDeviceFeatures2, features2.SType); Assert.Equal(StructureType.PhysicalDeviceDescriptorIndexingFeatures, indexingFeatures.SType); Assert.Equal ( StructureType.PhysicalDeviceAccelerationStructureFeaturesKhr, accelerationStructureFeaturesKhr.SType ); Assert.True(indexingFeatures.ShaderInputAttachmentArrayDynamicIndexing); Assert.True(accelerationStructureFeaturesKhr.AccelerationStructure); }
public void TestChainLoadWithError() { var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures { ShaderInputAttachmentArrayDynamicIndexing = true }; // Load an unmanaged chain DeviceCreateInfo .Chain(out var unmanagedChain) .AddNext(out PhysicalDeviceFeatures2 features2) .SetNext(ref indexingFeatures) .AddNext(out PhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeaturesKhr); // Loads a new managed chain from an unmanaged chain using var managedChain = Chain.Load < DeviceCreateInfo, // Note we are supplied a PhysicalDeviceFeatures2 here from the unmanaged chain PhysicalDeviceAccelerationStructureFeaturesKHR, PhysicalDeviceDescriptorIndexingFeatures, PhysicalDeviceAccelerationStructureFeaturesKHR, // Note that the unmanaged chain did not supply a 5th entry PhysicalDeviceFeatures2>(out var errors, unmanagedChain); // Check for errors var errorsArray = errors.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); Assert.Equal(2, errorsArray.Length); Assert.Equal ( "The unmanaged chain has a structure type PhysicalDeviceFeatures2 at position 2; expected PhysicalDeviceAccelerationStructureFeatures", // PATCH: Due to the way ToString() interacts with enum aliases, the structure types may end in Khr, so removing. errorsArray[0].Replace("Khr", "") ); Assert.Equal ( "The unmanaged chain was length 4, expected length 5", errorsArray[1] ); // Despite the errors indexing features was at the right location so was loaded Assert.True(managedChain.Item2.ShaderInputAttachmentArrayDynamicIndexing); }
public unsafe VulkanRenderer(UserSettings userSettings, Window window, IScene scene, CameraInitialState cameraInitialState, ILogger logger, bool enableDebugLogging) { _userSettings = userSettings; _window = window; _api = new Api(enableDebugLogging, logger); _presentMode = _userSettings.VSync ? PresentModeKHR.PresentModeFifoKhr : PresentModeKHR.PresentModeImmediateKhr; _api.Instance = new Instance(_api, _window, new Version32(1, 2, 0)); _surface = new Surface(_api, _window, _api.Instance); // Find the vulkan device we want var physicalDevice = _api.Instance.PhysicalDevices.Where(d => { _api.Vk.GetPhysicalDeviceFeatures(d, out var deviceFeatures); if (deviceFeatures.GeometryShader == false) { return(false); } var queueFamilies = Enumerate.Get <PhysicalDevice, QueueFamilyProperties>(d, (device, count, values) => _api.Vk.GetPhysicalDeviceQueueFamilyProperties(device, (uint *)count, (QueueFamilyProperties *)values)); for (var i = 0; i < queueFamilies.Count; i++) { if (queueFamilies[i].QueueCount > 0 && queueFamilies[i].QueueFlags.HasFlag(QueueFlags.QueueGraphicsBit)) { return(true); } } return(false); }).FirstOrDefault(); if (physicalDevice.Handle == 0) { throw new Exception($"{nameof(VulkanRenderer)}: Could not find a suitable graphics device."); } var deviceProps = new PhysicalDeviceProperties2(); deviceProps.SType = StructureType.PhysicalDeviceProperties2; _api.Vk.GetPhysicalDeviceProperties2(physicalDevice, &deviceProps); _api.Logger.Debug($"{nameof(VulkanRenderer)}: Setting physical device: {deviceProps.Properties.DeviceID} ({Marshal.PtrToStringAnsi((nint)deviceProps.Properties.DeviceName)})"); // Opt-in into mandatory device features. var shaderClockFeatures = new PhysicalDeviceShaderClockFeaturesKHR(); shaderClockFeatures.SType = StructureType.PhysicalDeviceShaderClockFeaturesKhr; shaderClockFeatures.PNext = null; shaderClockFeatures.ShaderSubgroupClock = true; var deviceFeatures = new PhysicalDeviceFeatures(); deviceFeatures.FillModeNonSolid = true; deviceFeatures.SamplerAnisotropy = true; deviceFeatures.ShaderInt64 = true; // Required device features. var bufferDeviceAddressFeatures = new PhysicalDeviceBufferDeviceAddressFeatures(); bufferDeviceAddressFeatures.SType = StructureType.PhysicalDeviceBufferDeviceAddressFeatures; bufferDeviceAddressFeatures.PNext = &shaderClockFeatures; bufferDeviceAddressFeatures.BufferDeviceAddress = true; var indexingFeatures = new PhysicalDeviceDescriptorIndexingFeatures(); indexingFeatures.SType = StructureType.PhysicalDeviceDescriptorIndexingFeatures; indexingFeatures.PNext = &bufferDeviceAddressFeatures; indexingFeatures.RuntimeDescriptorArray = true; indexingFeatures.ShaderSampledImageArrayNonUniformIndexing = true; var accelerationStructureFeatures = new PhysicalDeviceAccelerationStructureFeaturesKHR(); accelerationStructureFeatures.SType = StructureType.PhysicalDeviceAccelerationStructureFeaturesKhr; accelerationStructureFeatures.PNext = &indexingFeatures; accelerationStructureFeatures.AccelerationStructure = true; var rayTracingFeatures = new PhysicalDeviceRayTracingPipelineFeaturesKHR(); rayTracingFeatures.SType = StructureType.PhysicalDeviceRayTracingPipelineFeaturesKhr; rayTracingFeatures.PNext = &accelerationStructureFeatures; rayTracingFeatures.RayTracingPipeline = true; _api.Device = new Device(_api, physicalDevice, _surface, deviceFeatures, Unsafe.AsPointer(ref rayTracingFeatures)); // Now that we have an instance and a device, load all of the extentions we need. _api.InitializeExtensions(); _commandPool = new CommandPool(_api, _api.Device.GraphicsFamilyIndex, true); _rayTracingProperties = new RayTracingProperties(_api); // Load the scene, and create the swap chain / command buffers LoadScene(scene, cameraInitialState); _currentFrame = 0; _api.Device.WaitIdle(); }