Пример #1
0
    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);
    }
Пример #2
0
    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);
    }
Пример #3
0
    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);
    }
Пример #4
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);
    }
Пример #5
0
    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);
    }
Пример #6
0
        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();
        }