void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights rayTracingLights, DebugDisplaySettings debugDisplaySettings)
        {
            // If no lights, exit
            if (rayTracingLights.lightCount == 0)
            {
                ResizeLightDataBuffer(1);
                return;
            }

            // Also we need to build the light list data
            if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != rayTracingLights.lightCount)
            {
                ResizeLightDataBuffer(rayTracingLights.lightCount);
            }

            m_LightDataCPUArray.Clear();

            // Grab the shadow settings
            var hdShadowSettings = hdCamera.volumeStack.GetComponent <HDShadowSettings>();
            BoolScalableSetting contactShadowScalableSetting = HDAdditionalLightData.ScalableSettings.UseContactShadow(m_RenderPipeline.asset);

            // Build the data for every light
            HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance;
            var processedLightEntity            = new HDProcessedVisibleLight()
            {
                shadowMapFlags = HDProcessedVisibleLightsBuilder.ShadowMapFlags.None
            };

            var globalConfig     = HDGpuLightsBuilder.CreateGpuLightDataJobGlobalConfig.Create(hdCamera, hdShadowSettings);
            var shadowInitParams = m_RenderPipeline.currentPlatformRenderPipelineSettings.hdShadowInitParams;

            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightEntityArray.Count; ++lightIdx)
            {
                // Grab the additinal light data to process
                int dataIndex = lightEntities.GetEntityDataIndex(rayTracingLights.hdLightEntityArray[lightIdx]);
                HDAdditionalLightData additionalLightData = lightEntities.hdAdditionalLightData[dataIndex];

                LightData lightData = new LightData();
                // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered
                // the workaround for this is simply to add an invalid light for that frame
                if (additionalLightData == null)
                {
                    m_LightDataCPUArray.Add(lightData);
                    continue;
                }

                // Evaluate all the light type data that we need
                LightCategory   lightCategory   = LightCategory.Count;
                GPULightType    gpuLightType    = GPULightType.Point;
                LightVolumeType lightVolumeType = LightVolumeType.Count;
                HDLightType     lightType       = additionalLightData.type;
                HDRenderPipeline.EvaluateGPULightType(lightType, additionalLightData.spotLightShape, additionalLightData.areaLightShape, ref lightCategory, ref gpuLightType, ref lightVolumeType);

                // Fetch the light component for this light
                additionalLightData.gameObject.TryGetComponent(out lightComponent);

                ref HDLightRenderData lightRenderData = ref lightEntities.GetLightDataAsRef(dataIndex);

                // Build the processed light data  that we need
                processedLightEntity.dataIndex                   = dataIndex;
                processedLightEntity.gpuLightType                = gpuLightType;
                processedLightEntity.lightType                   = additionalLightData.type;
                processedLightEntity.distanceToCamera            = (additionalLightData.transform.position - hdCamera.camera.transform.position).magnitude;
                processedLightEntity.lightDistanceFade           = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.fadeDistance);
                processedLightEntity.lightVolumetricDistanceFade = HDUtils.ComputeLinearDistanceFade(processedLightEntity.distanceToCamera, lightRenderData.volumetricFadeDistance);
                processedLightEntity.isBakedShadowMask           = HDRenderPipeline.IsBakedShadowMaskLight(lightComponent);

                // Build a visible light
                visibleLight.finalColor = LightUtils.EvaluateLightColor(lightComponent, additionalLightData);
                visibleLight.range      = lightComponent.range;
                // This should be done explicitly, localToWorld matrix doesn't work here
                localToWorldMatrix.SetColumn(3, lightComponent.gameObject.transform.position);
                localToWorldMatrix.SetColumn(2, lightComponent.transform.forward);
                localToWorldMatrix.SetColumn(1, lightComponent.transform.up);
                localToWorldMatrix.SetColumn(0, lightComponent.transform.right);
                visibleLight.localToWorldMatrix = localToWorldMatrix;
                visibleLight.spotAngle          = lightComponent.spotAngle;

                int     shadowIndex     = additionalLightData.shadowIndex;
                Vector3 lightDimensions = new Vector3(0.0f, 0.0f, 0.0f);

                // Use the shared code to build the light data
                HDGpuLightsBuilder.CreateGpuLightDataJob.ConvertLightToGPUFormat(
                    lightCategory, gpuLightType, globalConfig,
                    lightComponent.lightShadowCasterMode, lightComponent.bakingOutput,
                    visibleLight, processedLightEntity, lightRenderData, out var _, ref lightData);
                m_RenderPipeline.gpuLightList.ProcessLightDataShadowIndex(cmd, shadowInitParams, lightType, lightComponent, additionalLightData, shadowIndex, ref lightData);

                // We make the light position camera-relative as late as possible in order
                // to allow the preceding code to work with the absolute world space coordinates.
                Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos;
                HDRenderPipeline.UpdateLightCameraRelativetData(ref lightData, camPosWS);

                // Set the data for this light
                m_LightDataCPUArray.Add(lightData);
            }
        void BuildGPULightVolumes(HDCamera hdCamera, HDRayTracingLights rayTracingLights)
        {
            int totalNumLights = rayTracingLights.lightCount;

            // Make sure the light volume buffer has the right size
            if (m_LightVolumesCPUArray == null || totalNumLights != m_LightVolumesCPUArray.Length)
            {
                ResizeVolumeBuffer(totalNumLights);
            }

            // Set Light volume data to the CPU buffer
            punctualLightCount = 0;
            areaLightCount     = 0;
            envLightCount      = 0;
            totalLightCount    = 0;

            int realIndex = 0;
            HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance;

            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightEntityArray.Count; ++lightIdx)
            {
                int dataIndex = lightEntities.GetEntityDataIndex(rayTracingLights.hdLightEntityArray[lightIdx]);
                HDAdditionalLightData currentLight = lightEntities.hdAdditionalLightData[dataIndex];

                // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered
                // the workaround for this is simply to not add it if it is null for that invalid frame
                if (currentLight != null)
                {
                    Light light = currentLight.gameObject.GetComponent <Light>();
                    if (light == null || !light.enabled)
                    {
                        continue;
                    }

                    // If the light is flagged as baked and has been effectively been baked, we need to skip it and not add it to the light cluster
                    if (light.bakingOutput.lightmapBakeType == LightmapBakeType.Baked && light.bakingOutput.isBaked)
                    {
                        continue;
                    }

                    // If this light should not be included when ray tracing is active on the camera, skip it
                    if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && !currentLight.includeForRayTracing)
                    {
                        continue;
                    }

                    // Reserve space in the cookie atlas
                    m_RenderPipeline.ReserveCookieAtlasTexture(currentLight, light, currentLight.type);

                    // Compute the camera relative position
                    Vector3 lightPositionRWS = currentLight.gameObject.transform.position;
                    if (ShaderConfig.s_CameraRelativeRendering != 0)
                    {
                        lightPositionRWS -= hdCamera.camera.transform.position;
                    }

                    // Grab the light range
                    float lightRange = light.range;

                    if (currentLight.type != HDLightType.Area)
                    {
                        m_LightVolumesCPUArray[realIndex].range      = new Vector3(lightRange, lightRange, lightRange);
                        m_LightVolumesCPUArray[realIndex].position   = lightPositionRWS;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 0;
                        m_LightVolumesCPUArray[realIndex].lightType  = 0;
                        punctualLightCount++;
                    }
                    else
                    {
                        // let's compute the oobb of the light influence volume first
                        Vector3 oobbDimensions = new Vector3(currentLight.shapeWidth + 2 * lightRange, currentLight.shapeHeight + 2 * lightRange, lightRange); // One-sided
                        Vector3 extents        = 0.5f * oobbDimensions;
                        Vector3 oobbCenter     = lightPositionRWS + extents.z * currentLight.gameObject.transform.forward;

                        // Let's now compute an AABB that matches the previously defined OOBB
                        OOBBToAABBBounds(oobbCenter, extents, currentLight.gameObject.transform.up, currentLight.gameObject.transform.right, currentLight.gameObject.transform.forward, ref bounds);

                        // Fill the volume data
                        m_LightVolumesCPUArray[realIndex].range      = bounds.extents;
                        m_LightVolumesCPUArray[realIndex].position   = bounds.center;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 1;
                        m_LightVolumesCPUArray[realIndex].lightType  = 1;
                        areaLightCount++;
                    }
                    realIndex++;
                }
            }

            int indexOffset = realIndex;

            // Set Env Light volume data to the CPU buffer
            for (int lightIdx = 0; lightIdx < rayTracingLights.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe currentEnvLight = rayTracingLights.reflectionProbeArray[lightIdx];


                if (currentEnvLight != null)
                {
                    // If the reflection probe is disabled, we should not be adding it
                    if (!currentEnvLight.enabled)
                    {
                        continue;
                    }

                    // If the reflection probe is not baked yet.
                    if (!currentEnvLight.HasValidRenderedData())
                    {
                        continue;
                    }

                    // Compute the camera relative position
                    Vector3 probePositionRWS = currentEnvLight.influenceToWorld.GetColumn(3);
                    if (ShaderConfig.s_CameraRelativeRendering != 0)
                    {
                        probePositionRWS -= hdCamera.camera.transform.position;
                    }

                    if (currentEnvLight.influenceVolume.shape == InfluenceShape.Sphere)
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 0;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    else
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 1;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.boxSize.x / 2.0f, currentEnvLight.influenceVolume.boxSize.y / 2.0f, currentEnvLight.influenceVolume.boxSize.z / 2.0f);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    m_LightVolumesCPUArray[lightIdx + indexOffset].active     = (currentEnvLight.gameObject.activeInHierarchy ? 1 : 0);
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightIndex = (uint)lightIdx;
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightType  = 2;
                    envLightCount++;
                }
            }

            totalLightCount = punctualLightCount + areaLightCount + envLightCount;

            // Push the light volumes to the GPU
            m_LightVolumeGPUArray.SetData(m_LightVolumesCPUArray);
        }