void SetParameters(
        FRHICommandList& RHICmdList,
        const FViewInfo& View,
        FIntPoint TileListGroupSizeValue,
        FSceneRenderTargetItem& DistanceFieldNormal,
        const FDistanceFieldAOParameters& Parameters,
        FSceneRenderTargetItem& SpecularOcclusionBuffer)
    {
        FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
        FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
        DeferredParameters.Set(RHICmdList, ShaderRHI, View);
        ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers);
        AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
        ScreenGridParameters.Set(RHICmdList, ShaderRHI, View, DistanceFieldNormal);

        FAOSampleData2 AOSampleData;

        TArray<FVector, TInlineAllocator<9> > SampleDirections;
        GetSpacedVectors(SampleDirections);

        for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
        {
            AOSampleData.SampleDirections[SampleIndex] = FVector4(SampleDirections[SampleIndex]);
        }

        SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FAOSampleData2>(), AOSampleData);

        FTileIntersectionResources* TileIntersectionResources = View.ViewState->AOTileIntersectionResources;

        SetSRVParameter(RHICmdList, ShaderRHI, TileHeadDataUnpacked, TileIntersectionResources->TileHeadDataUnpacked.SRV);
        SetSRVParameter(RHICmdList, ShaderRHI, TileArrayData, TileIntersectionResources->TileArrayData.SRV);
        SetSRVParameter(RHICmdList, ShaderRHI, TileConeDepthRanges, TileIntersectionResources->TileConeDepthRanges.SRV);

        SetShaderValue(RHICmdList, ShaderRHI, TileListGroupSize, TileListGroupSizeValue);

        extern float GAOConeHalfAngle;
        SetShaderValue(RHICmdList, ShaderRHI, TanConeHalfAngle, FMath::Tan(GAOConeHalfAngle));

        FVector UnoccludedVector(0);

        for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
        {
            UnoccludedVector += SampleDirections[SampleIndex];
        }

        float BentNormalNormalizeFactorValue = 1.0f / (UnoccludedVector / NumConeSampleDirections).Size();
        SetShaderValue(RHICmdList, ShaderRHI, BentNormalNormalizeFactor, BentNormalNormalizeFactorValue);

        int32 NumOutUAVs = 0;
        FUnorderedAccessViewRHIParamRef OutUAVs[1];
        OutUAVs[NumOutUAVs++] = SpecularOcclusionBuffer.UAV;

        RHICmdList.TransitionResources(EResourceTransitionAccess::ERWBarrier, EResourceTransitionPipeline::EComputeToCompute, OutUAVs, NumOutUAVs);

        SpecularOcclusion.SetTexture(RHICmdList, ShaderRHI, SpecularOcclusionBuffer.ShaderResourceTexture, SpecularOcclusionBuffer.UAV);
    }
	void SetParameters(
		FRHICommandList& RHICmdList, 
		const FViewInfo& View, 
		FIntPoint TileListGroupSizeValue, 
		FSceneRenderTargetItem& DistanceFieldNormal, 
		const FDistanceFieldAOParameters& Parameters,
		const FGlobalDistanceFieldInfo& GlobalDistanceFieldInfo)
	{
		FComputeShaderRHIParamRef ShaderRHI = GetComputeShader();
		FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View);
		DeferredParameters.Set(RHICmdList, ShaderRHI, View);
		ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers);
		AOParameters.Set(RHICmdList, ShaderRHI, Parameters);
		ScreenGridParameters.Set(RHICmdList, ShaderRHI, View, DistanceFieldNormal);

		if (bUseGlobalDistanceField)
		{
			GlobalDistanceFieldParameters.Set(RHICmdList, ShaderRHI, GlobalDistanceFieldInfo.ParameterData);
		}

		FAOSampleData2 AOSampleData;

		TArray<FVector, TInlineAllocator<9> > SampleDirections;
		GetSpacedVectors(SampleDirections);

		for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
		{
			AOSampleData.SampleDirections[SampleIndex] = FVector4(SampleDirections[SampleIndex]);
		}

		SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FAOSampleData2>(), AOSampleData);

		FTileIntersectionResources* TileIntersectionResources = View.ViewState->AOTileIntersectionResources;

		SetSRVParameter(RHICmdList, ShaderRHI, TileHeadDataUnpacked, TileIntersectionResources->TileHeadDataUnpacked.SRV);
		SetSRVParameter(RHICmdList, ShaderRHI, TileArrayData, TileIntersectionResources->TileArrayData.SRV);
		SetSRVParameter(RHICmdList, ShaderRHI, TileConeDepthRanges, TileIntersectionResources->TileConeDepthRanges.SRV);

		SetShaderValue(RHICmdList, ShaderRHI, TileListGroupSize, TileListGroupSizeValue);

		extern float GAOConeHalfAngle;
		SetShaderValue(RHICmdList, ShaderRHI, TanConeHalfAngle, FMath::Tan(GAOConeHalfAngle));

		FVector UnoccludedVector(0);

		for (int32 SampleIndex = 0; SampleIndex < NumConeSampleDirections; SampleIndex++)
		{
			UnoccludedVector += SampleDirections[SampleIndex];
		}

		float BentNormalNormalizeFactorValue = 1.0f / (UnoccludedVector / NumConeSampleDirections).Size();
		SetShaderValue(RHICmdList, ShaderRHI, BentNormalNormalizeFactor, BentNormalNormalizeFactorValue);

		FAOScreenGridResources* ScreenGridResources = View.ViewState->AOScreenGridResources;

		ScreenGridConeVisibility.SetBuffer(RHICmdList, ShaderRHI, ScreenGridResources->ScreenGridConeVisibility);

		if (bSupportIrradiance)
		{
			ConeDepthVisibilityFunction.SetBuffer(RHICmdList, ShaderRHI, ScreenGridResources->ConeDepthVisibilityFunction);
		}
	}