public unsafe BottomLevelAccelerationStructure(Api api, RayTracingProperties rayTracingProperties, BottomLevelGeometry geometries)
            : base(api, rayTracingProperties)
        {
            _geometry = GC.AllocateArray <AccelerationStructureGeometryKHR>(geometries.Geometry.Count, true);
            geometries.Geometry.CopyTo(_geometry);

            _buildOffsetInfo = GC.AllocateArray <AccelerationStructureBuildRangeInfoKHR>(geometries.BuildOffsetInfo.Count, true);
            geometries.BuildOffsetInfo.CopyTo(_buildOffsetInfo);

            _buildGeometryInfo.SType                    = StructureType.AccelerationStructureBuildGeometryInfoKhr;
            _buildGeometryInfo.Flags                    = _flags;
            _buildGeometryInfo.GeometryCount            = (uint)_geometry.Length;
            _buildGeometryInfo.PGeometries              = (AccelerationStructureGeometryKHR *)Unsafe.AsPointer(ref _geometry[0]);
            _buildGeometryInfo.Mode                     = BuildAccelerationStructureModeKHR.BuildAccelerationStructureModeBuildKhr;
            _buildGeometryInfo.Type                     = AccelerationStructureTypeKHR.AccelerationStructureTypeBottomLevelKhr;
            _buildGeometryInfo.SrcAccelerationStructure = default;

            // Note: Could use stackalloc here, but the model count might be too high
            uint[] maxPrimCount = new uint[_buildOffsetInfo.Length];

            for (int i = 0; i != maxPrimCount.Length; i++)
                maxPrimCount[i] = _buildOffsetInfo[i].PrimitiveCount;

            fixed(uint *maxPrimCountPtr = &maxPrimCount[0])
            GetBuildSizes(maxPrimCountPtr, out _buildSizesInfo);
        }
Beispiel #2
0
        public unsafe TopLevelAccelerationStructure(Api api, RayTracingProperties rayTracingProperties, ulong instanceAddress, uint instancesCount)
            : base(api, rayTracingProperties)
        {
            _instancesCount = instancesCount;

            // Create VkAccelerationStructureGeometryInstancesDataKHR. This wraps a device pointer to the above uploaded instances.
            var instancesVk = new AccelerationStructureGeometryInstancesDataKHR();

            instancesVk.SType              = StructureType.AccelerationStructureGeometryInstancesDataKhr;
            instancesVk.ArrayOfPointers    = new Silk.NET.Core.Bool32(false);
            instancesVk.Data.DeviceAddress = instanceAddress;

            // Put the above into a VkAccelerationStructureGeometryKHR. We need to put the
            // instances struct in a union and label it as instance data.
            _topASGeometry.Value.SType              = StructureType.AccelerationStructureGeometryKhr;
            _topASGeometry.Value.GeometryType       = GeometryTypeKHR.GeometryTypeInstancesKhr;
            _topASGeometry.Value.Geometry.Instances = instancesVk;

            _buildGeometryInfo.SType                    = StructureType.AccelerationStructureBuildGeometryInfoKhr;
            _buildGeometryInfo.Flags                    = _flags;
            _buildGeometryInfo.GeometryCount            = 1;
            _buildGeometryInfo.PGeometries              = _topASGeometry.Ptr;
            _buildGeometryInfo.Mode                     = BuildAccelerationStructureModeKHR.BuildAccelerationStructureModeBuildKhr;
            _buildGeometryInfo.Type                     = AccelerationStructureTypeKHR.AccelerationStructureTypeTopLevelKhr;
            _buildGeometryInfo.SrcAccelerationStructure = default;

            GetBuildSizes(&instancesCount, out _buildSizesInfo);
        }
        public unsafe ShaderBindingTable(
            Api api,
            RayTracingPipeline rayTracingPipeline,
            RayTracingProperties rayTracingProperties,
            List <Entry> rayGenPrograms,
            List <Entry> missPrograms,
            List <Entry> hitGroups)
        {
            RayGenEntrySize   = GetEntrySize(rayTracingProperties, rayGenPrograms);
            MissEntrySize     = GetEntrySize(rayTracingProperties, missPrograms);
            HitGroupEntrySize = GetEntrySize(rayTracingProperties, hitGroups);

            RayGenOffset   = 0;
            MissOffset     = (ulong)rayGenPrograms.Count * RayGenEntrySize;
            HitGroupOffset = MissOffset + (ulong)missPrograms.Count * MissEntrySize;

            RayGenSize   = (ulong)rayGenPrograms.Count * RayGenEntrySize;
            MissSize     = (ulong)missPrograms.Count * MissEntrySize;
            HitGroupSize = (ulong)hitGroups.Count * HitGroupEntrySize;

            // Compute the size of the table.
            ulong sbtSize =
                (ulong)rayGenPrograms.Count * RayGenEntrySize +
                (ulong)missPrograms.Count * MissEntrySize +
                (ulong)hitGroups.Count * HitGroupEntrySize;

            // Allocate buffer & memory.
            _buffer       = new Buffer(api, sbtSize, BufferUsageFlags.BufferUsageShaderDeviceAddressBit | BufferUsageFlags.BufferUsageTransferSrcBit);
            _bufferMemory = _buffer.AllocateMemory(MemoryAllocateFlags.MemoryAllocateDeviceAddressBit, MemoryPropertyFlags.MemoryPropertyHostVisibleBit);

            // Generate the table.
            uint  handleSize = rayTracingProperties.ShaderGroupHandleSize;
            ulong groupCount = (ulong)rayGenPrograms.Count + (ulong)missPrograms.Count + (ulong)hitGroups.Count;

            byte[] shaderHandleStorage = new byte[groupCount * handleSize];

            fixed(byte *shaderHandleStoragePtr = &shaderHandleStorage[0])
            {
                Util.Verify(api.KhrRayTracingPipeline.GetRayTracingShaderGroupHandles(
                                api.Device.VkDevice,
                                rayTracingPipeline.VkPipeline,
                                0,
                                (uint)groupCount,
                                (nuint)shaderHandleStorage.Length,
                                shaderHandleStoragePtr
                                ), $"{nameof(ShaderBindingTable)}: Unable to get ray tracing shader group handles");

                // Copy the shader identifiers followed by their resource pointers or root constants:
                // first the ray generation, then the miss shaders, and finally the set of hit groups.
                byte *pData = (byte *)_bufferMemory.Map(0, sbtSize);

                pData += CopyShaderData(pData, rayTracingProperties, rayGenPrograms, RayGenEntrySize, shaderHandleStoragePtr);
                pData += CopyShaderData(pData, rayTracingProperties, missPrograms, MissEntrySize, shaderHandleStoragePtr);
                CopyShaderData(pData, rayTracingProperties, hitGroups, HitGroupEntrySize, shaderHandleStoragePtr);
            }

            _bufferMemory.Unmap();
        }
Beispiel #4
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();
        }
Beispiel #5
0
 protected AccelerationStructure(Api api, RayTracingProperties rayTracingProperties) =>
 (_api, _rayTracingProperties, _flags) =