Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/Substrate/Glint/GlintShadingLUTs.cpp
2025-05-18 13:04:45 +08:00

146 lines
5.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
GlintShadingLUTs.cpp
=============================================================================*/
#include "GlintShadingLUTs.h"
#include "ScenePrivate.h"
#include "SceneRendering.h"
#include "Engine/Engine.h"
#include "RenderUtils.h"
#include "TextureResource.h"
#include "Engine/Texture2DArray.h"
#include "GlintShadingLUTsData.h"
void FGlintShadingLUTsStateData::Init(FRDGBuilder& GraphBuilder, FViewInfo& View)
{
#if OVERRIDE_GLINT_LUT_ASSSET_WITH_EMBEDDED_DATA
if (Substrate::IsGlintEnabled(View->GetShaderPlatform()))
{
if (View.ViewState && View.ViewState->GlintShadingLUTsData.GlintShadingLUTs == nullptr)
{
FGlintShadingLUTsStateData& GlintShadingLUTsStateData = View.ViewState->GlintShadingLUTsData;
const uint32 MipCount = 7;
const EPixelFormat PixelFormat = PF_FloatR11G11B10;
GlintShadingLUTsStateData.GlintShadingLUTs = GRenderTargetPool.FindFreeElement(
FRDGTextureDesc::Create2DArray(FIntPoint(GlintLut1DArrayMip0Width, 1), PixelFormat, FClearValueBinding::None, TexCreate_ShaderResource, GlintLut1DArrayMip0Height, MipCount), TEXT("Material.Glints"));
auto UploadGlintTextureArrayMipData = [&](uint32 LutArrayIndex, uint32 LutMipLevel, uint32 LutMipWidth, uint8* SrcData)
{
#if 0
check(PixelFormat == PF_A32B32G32R32F);
const uint32 SrcBytesPerPixel = sizeof(float) * 4;
#elif 1
check(PixelFormat == PF_FloatR11G11B10);
const uint32 SrcBytesPerPixel = sizeof(uint32) * 1;
// If we have a texture2darray of 64x1 texel with 1024 slices, then all the source arrays are 1024*(64+32+16+8+4+2+1) = 130048 = 127KB.
// Loaded on GPU with this format, it seems to be 3MB as reported by dx12.
#elif 0
check(PixelFormat == PF_FloatRGBA);
const uint32 SrcBytesPerPixel = sizeof(uint32) * 2;
#else
#error A valid branch must be taken
#endif
uint32 SrcStride = SrcBytesPerPixel * LutMipWidth;
uint32 DstStride;
uint8* Dst = (uint8*)GraphBuilder.RHICmdList.LockTexture2DArray(GlintShadingLUTsStateData.GlintShadingLUTs->GetRHI()->GetTexture2DArray(), LutArrayIndex, LutMipLevel, RLM_WriteOnly, DstStride, false);
const uint8* Src = SrcData +LutArrayIndex * SrcStride;
FMemory::Memcpy(Dst, Src, SrcStride);
GraphBuilder.RHICmdList.UnlockTexture2DArray(GlintShadingLUTsStateData.GlintShadingLUTs->GetRHI()->GetTexture2DArray(), LutArrayIndex, LutMipLevel, false);
};
const uint32 GlintLut1DArraySize = GlintLut1DArrayMip0Height;
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 0, GlintLut1DArrayMip0Width, (uint8*)GlintLut1DArrayMip0RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 1, GlintLut1DArrayMip1Width, (uint8*)GlintLut1DArrayMip1RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 2, GlintLut1DArrayMip2Width, (uint8*)GlintLut1DArrayMip2RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 3, GlintLut1DArrayMip3Width, (uint8*)GlintLut1DArrayMip3RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 4, GlintLut1DArrayMip4Width, (uint8*)GlintLut1DArrayMip4RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 5, GlintLut1DArrayMip5Width, (uint8*)GlintLut1DArrayMip5RGBA);
}
for (int LutArrayIndex = 0; LutArrayIndex < GlintLut1DArraySize; ++LutArrayIndex)
{
UploadGlintTextureArrayMipData(LutArrayIndex, 6, GlintLut1DArrayMip6Width, (uint8*)GlintLut1DArrayMip6RGBA);
}
GlintShadingLUTsStateData.SetDictionaryParameter(16, 64, 0.5); // Match the embedded LUT
}
}
else
{
if (View.ViewState)
{
View.ViewState->GlintShadingLUTsData.GlintShadingLUTs = nullptr;
View.ViewState->GlintShadingLUTsData.RHIGlintShadingLUTs = nullptr;
}
}
// Assign the RHI texture is is possible
if (View.ViewState && View.ViewState->GlintShadingLUTsData.RHIGlintShadingLUTs == nullptr && View.ViewState->GlintShadingLUTsData.GlintShadingLUTs != nullptr)
{
View.ViewState->GlintShadingLUTsData.RHIGlintShadingLUTs = View.ViewState->GlintShadingLUTsData.GlintShadingLUTs->GetRHI()->GetTexture2DArray();
}
#else
// Use the conditionally loaded asset
if (View.ViewState)
{
FGlintShadingLUTsStateData& GlintShadingLUTsStateData = View.ViewState->GlintShadingLUTsData;
GlintShadingLUTsStateData.GlintShadingLUTs = nullptr;
GlintShadingLUTsStateData.RHIGlintShadingLUTs = nullptr;
if (GEngine->GlintTexture)
{
if (Substrate::GlintLUTIndex() == 0)
{
GlintShadingLUTsStateData.RHIGlintShadingLUTs = GEngine->GlintTexture->GetResource()->TextureRHI->GetTexture2DArray();
GlintShadingLUTsStateData.SetDictionaryParameter(16, 64, 0.5); // Match the embedded LUT
}
else
{
GlintShadingLUTsStateData.RHIGlintShadingLUTs = GEngine->GlintTexture2->GetResource()->TextureRHI->GetTexture2DArray();
GlintShadingLUTsStateData.SetDictionaryParameter(8, 256, 0.5); // Match the embedded LUT
}
}
}
#endif
}
void FGlintShadingLUTsStateData::SetDictionaryParameter(int32 InNumberOfLevels, int32 InNumberOfDistributionsPerChannel, float InDictionaryAlpha)
{
Dictionary_Alpha = InDictionaryAlpha;
Dictionary_NLevels = InNumberOfLevels;
Dictionary_NDistributionsPerChannel = InNumberOfDistributionsPerChannel;
Dictionary_N = Dictionary_NDistributionsPerChannel * 3;
Dictionary_Pyramid0Size = 1u << (Dictionary_NLevels - 1u);
}