// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "RHIShaderParameters.h" namespace UE::RHICore { inline FRHIDescriptorHandle GetBindlessParameterHandle(const FRHIShaderParameterResource& Parameter) { if (FRHIResource* Resource = Parameter.Resource) { switch (Parameter.Type) { case FRHIShaderParameterResource::EType::Texture: return static_cast(Resource)->GetDefaultBindlessHandle(); case FRHIShaderParameterResource::EType::ResourceView: return static_cast(Resource)->GetBindlessHandle(); case FRHIShaderParameterResource::EType::UnorderedAccessView: return static_cast(Resource)->GetBindlessHandle(); case FRHIShaderParameterResource::EType::Sampler: return static_cast(Resource)->GetBindlessHandle(); case FRHIShaderParameterResource::EType::ResourceCollection: return static_cast(Resource)->GetBindlessHandle(); default: checkf(false, TEXT("Unhandled resource type?")); break; } } return FRHIDescriptorHandle(); } template inline void SetShaderUAV(FContextRHI& Context, FRHIGraphicsShader* ShaderRHI, uint16 Index, FRHIUnorderedAccessView* UAV) { if (ShaderRHI->GetType() == RRT_PixelShader) { Context.RHISetUAVParameter(static_cast(ShaderRHI), Index, UAV); } else { checkf(false, TEXT("TShaderRHI Can't have compute shader to be set. UAVs are not supported on vertex, tessellation and geometry shaders.")); } } template inline void SetShaderUAV(FContextRHI& Context, FRHIComputeShader* ShaderRHI, uint16 Index, FRHIUnorderedAccessView* UAV) { Context.RHISetUAVParameter(ShaderRHI, Index, UAV); } template inline void RHISetShaderParametersShared( FContextRHI& Context , TShaderRHI* ShaderRHI , TConstArrayView InParametersData , TConstArrayView InParameters , TConstArrayView InResourceParameters , TConstArrayView InBindlessParameters , bool bBindUAVsFirst = true // UE TODO: investigate where this is absolutely necessary ) { if (InParameters.Num()) { for (const FRHIShaderParameter& Parameter : InParameters) { Context.RHISetShaderParameter(ShaderRHI, Parameter.BufferIndex, Parameter.BaseIndex, Parameter.ByteSize, &InParametersData[Parameter.ByteOffset]); } } #if PLATFORM_SUPPORTS_BINDLESS_RENDERING for (const FRHIShaderParameterResource& Parameter : InBindlessParameters) { const FRHIDescriptorHandle Handle = GetBindlessParameterHandle(Parameter); if (Handle.IsValid()) { const uint32 BindlessIndex = Handle.GetIndex(); Context.RHISetShaderParameter(ShaderRHI, 0, Parameter.Index, 4, &BindlessIndex); } } #endif if (bBindUAVsFirst) { for (const FRHIShaderParameterResource& Parameter : InResourceParameters) { if (Parameter.Type == FRHIShaderParameterResource::EType::UnorderedAccessView) { SetShaderUAV(Context, ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); } } } for (const FRHIShaderParameterResource& Parameter : InResourceParameters) { switch (Parameter.Type) { case FRHIShaderParameterResource::EType::Texture: Context.RHISetShaderTexture(ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); break; case FRHIShaderParameterResource::EType::ResourceView: Context.RHISetShaderResourceViewParameter(ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); break; case FRHIShaderParameterResource::EType::UnorderedAccessView: if (!bBindUAVsFirst) { SetShaderUAV(Context, ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); } break; case FRHIShaderParameterResource::EType::Sampler: Context.RHISetShaderSampler(ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); break; case FRHIShaderParameterResource::EType::UniformBuffer: Context.RHISetShaderUniformBuffer(ShaderRHI, Parameter.Index, static_cast(Parameter.Resource)); break; default: checkf(false, TEXT("Unhandled resource type?")); break; } } } template inline void RHISetShaderUnbindsShared(FContextRHI& Context, TShaderRHI* ShaderRHI, TConstArrayView InUnbinds) { for (const FRHIShaderParameterUnbind& Unbind : InUnbinds) { switch (Unbind.Type) { case FRHIShaderParameterUnbind::EType::ResourceView: Context.RHISetShaderResourceViewParameter(ShaderRHI, Unbind.Index, nullptr); break; case FRHIShaderParameterUnbind::EType::UnorderedAccessView: SetShaderUAV(Context, ShaderRHI, Unbind.Index, nullptr); break; default: checkf(false, TEXT("Unhandled resource type?")); break; } } } }