2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-05-30 14:48:02 -04:00
# include "GenerateMips.h"
# include "RenderGraphUtils.h"
2020-09-24 00:43:27 -04:00
# include "PipelineStateCache.h"
# include "GlobalShader.h"
# include "CommonRenderResources.h"
# include "RHIStaticStates.h"
2021-11-18 14:37:34 -05:00
# include "PixelShaderUtils.h"
2019-05-30 14:48:02 -04:00
2024-04-08 10:34:40 -04:00
# if PLATFORM_WINDOWS || PLATFORM_ANDROID || PLATFORM_LINUX
# include "IOpenGLDynamicRHI.h"
# endif
2019-05-30 14:48:02 -04:00
class FGenerateMipsCS : public FGlobalShader
{
2019-11-04 19:42:39 -05:00
public :
2020-09-24 00:43:27 -04:00
DECLARE_GLOBAL_SHADER ( FGenerateMipsCS )
SHADER_USE_PARAMETER_STRUCT ( FGenerateMipsCS , FGlobalShader )
2019-11-05 10:01:21 -05:00
class FGenMipsSRGB : SHADER_PERMUTATION_BOOL ( " GENMIPS_SRGB " ) ;
2019-11-18 18:19:05 -05:00
class FGenMipsSwizzle : SHADER_PERMUTATION_BOOL ( " GENMIPS_SWIZZLE " ) ;
using FPermutationDomain = TShaderPermutationDomain < FGenMipsSRGB , FGenMipsSwizzle > ;
2019-11-05 10:01:21 -05:00
2019-05-30 14:48:02 -04:00
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , TexelSize )
2019-05-30 14:48:02 -04:00
SHADER_PARAMETER_RDG_TEXTURE_SRV ( Texture2D , MipInSRV )
SHADER_PARAMETER_RDG_TEXTURE_UAV ( RWTexture2D , MipOutUAV )
SHADER_PARAMETER_SAMPLER ( SamplerState , MipSampler )
END_SHADER_PARAMETER_STRUCT ( )
2020-09-24 00:43:27 -04:00
static void ModifyCompilationEnvironment ( const FShaderPermutationParameters & , FShaderCompilerEnvironment & OutEnvironment )
{
OutEnvironment . SetDefine ( TEXT ( " GENMIPS_COMPUTE " ) , 1 ) ;
}
2019-05-30 14:48:02 -04:00
} ;
2020-09-24 00:43:27 -04:00
2019-05-30 14:48:02 -04:00
IMPLEMENT_GLOBAL_SHADER ( FGenerateMipsCS , " /Engine/Private/ComputeGenerateMips.usf " , " MainCS " , SF_Compute ) ;
2020-09-24 00:43:27 -04:00
class FGenerateMipsVS : public FGlobalShader
2019-11-18 18:19:05 -05:00
{
public :
2020-09-24 00:43:27 -04:00
DECLARE_GLOBAL_SHADER ( FGenerateMipsVS ) ;
SHADER_USE_PARAMETER_STRUCT ( FGenerateMipsVS , FGlobalShader ) ;
using FParameters = FEmptyShaderParameters ;
static void ModifyCompilationEnvironment ( const FShaderPermutationParameters & , FShaderCompilerEnvironment & OutEnvironment )
{
OutEnvironment . SetDefine ( TEXT ( " GENMIPS_COMPUTE " ) , 0 ) ;
}
2019-11-18 18:19:05 -05:00
} ;
2020-09-24 00:43:27 -04:00
IMPLEMENT_GLOBAL_SHADER ( FGenerateMipsVS , " /Engine/Private/ComputeGenerateMips.usf " , " MainVS " , SF_Vertex ) ;
2019-11-18 18:19:05 -05:00
2020-09-24 00:43:27 -04:00
class FGenerateMipsPS : public FGlobalShader
2019-11-18 18:19:05 -05:00
{
public :
2020-09-24 00:43:27 -04:00
DECLARE_GLOBAL_SHADER ( FGenerateMipsPS ) ;
SHADER_USE_PARAMETER_STRUCT ( FGenerateMipsPS , FGlobalShader ) ;
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , HalfTexelSize )
2020-09-24 00:43:27 -04:00
SHADER_PARAMETER ( float , Level )
SHADER_PARAMETER_RDG_TEXTURE_SRV ( Texture2D , MipInSRV )
SHADER_PARAMETER_SAMPLER ( SamplerState , MipSampler )
RENDER_TARGET_BINDING_SLOTS ( )
END_SHADER_PARAMETER_STRUCT ( )
static void ModifyCompilationEnvironment ( const FShaderPermutationParameters & , FShaderCompilerEnvironment & OutEnvironment )
2019-11-18 18:19:05 -05:00
{
2020-09-24 00:43:27 -04:00
OutEnvironment . SetDefine ( TEXT ( " GENMIPS_COMPUTE " ) , 0 ) ;
2019-11-18 18:19:05 -05:00
}
} ;
2020-09-24 00:43:27 -04:00
IMPLEMENT_GLOBAL_SHADER ( FGenerateMipsPS , " /Engine/Private/ComputeGenerateMips.usf " , " MainPS " , SF_Pixel ) ;
2019-11-18 18:19:05 -05:00
2021-10-29 12:53:33 -04:00
// Determine the indirect dispatch based on conditions
class FBuildIndirectDispatchArgsBufferCS : public FGlobalShader
{
public :
DECLARE_GLOBAL_SHADER ( FBuildIndirectDispatchArgsBufferCS )
SHADER_USE_PARAMETER_STRUCT ( FBuildIndirectDispatchArgsBufferCS , FGlobalShader )
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
SHADER_PARAMETER ( FIntPoint , TextureSize )
SHADER_PARAMETER ( uint32 , Offset )
SHADER_PARAMETER ( uint32 , NumMips )
SHADER_PARAMETER_RDG_BUFFER_SRV ( Buffer < uint32 > , ConditionBuffer )
SHADER_PARAMETER_RDG_BUFFER_UAV ( RWBuffer < uint32 > , RWIndirectDispatchArgsBuffer )
END_SHADER_PARAMETER_STRUCT ( )
static void ModifyCompilationEnvironment ( const FShaderPermutationParameters & , FShaderCompilerEnvironment & OutEnvironment )
{
OutEnvironment . SetDefine ( TEXT ( " GENMIPS_COMPUTE " ) , 1 ) ;
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FBuildIndirectDispatchArgsBufferCS , " /Engine/Private/ComputeGenerateMips.usf " , " BuildIndirectDispatchArgsCS " , SF_Compute ) ;
class FGenerateMipsIndirectCS : public FGlobalShader
{
public :
DECLARE_GLOBAL_SHADER ( FGenerateMipsIndirectCS )
SHADER_USE_PARAMETER_STRUCT ( FGenerateMipsIndirectCS , FGlobalShader )
class FGenMipsSRGB : SHADER_PERMUTATION_BOOL ( " GENMIPS_SRGB " ) ;
class FGenMipsSwizzle : SHADER_PERMUTATION_BOOL ( " GENMIPS_SWIZZLE " ) ;
using FPermutationDomain = TShaderPermutationDomain < FGenMipsSRGB , FGenMipsSwizzle > ;
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , TexelSize )
2021-10-29 12:53:33 -04:00
SHADER_PARAMETER_RDG_TEXTURE_SRV ( Texture2D , MipInSRV )
SHADER_PARAMETER_RDG_TEXTURE_UAV ( RWTexture2D , MipOutUAV )
SHADER_PARAMETER_SAMPLER ( SamplerState , MipSampler )
RDG_BUFFER_ACCESS ( IndirectDispatchArgsBuffer , ERHIAccess : : IndirectArgs )
END_SHADER_PARAMETER_STRUCT ( )
static void ModifyCompilationEnvironment ( const FShaderPermutationParameters & , FShaderCompilerEnvironment & OutEnvironment )
{
OutEnvironment . SetDefine ( TEXT ( " GENMIPS_COMPUTE " ) , 1 ) ;
}
} ;
IMPLEMENT_GLOBAL_SHADER ( FGenerateMipsIndirectCS , " /Engine/Private/ComputeGenerateMips.usf " , " MainCS " , SF_Compute ) ;
2024-04-08 10:34:40 -04:00
BEGIN_SHADER_PARAMETER_STRUCT ( FGenerateMipsRHIImplParameters , )
RDG_TEXTURE_ACCESS ( Texture , ERHIAccess : : CopyDest )
END_SHADER_PARAMETER_STRUCT ( )
2022-08-18 15:29:29 -04:00
void FGenerateMips : : ExecuteRaster ( FRDGBuilder & GraphBuilder , ERHIFeatureLevel : : Type FeatureLevel , FRDGTextureRef Texture , FRHISamplerState * Sampler )
2019-11-18 18:19:05 -05:00
{
2020-09-24 00:43:27 -04:00
check ( Texture ) ;
check ( Sampler ) ;
2019-11-18 18:19:05 -05:00
2024-03-25 12:03:28 -04:00
const FRDGTextureDesc & TextureDesc = Texture - > Desc ;
2022-08-18 15:29:29 -04:00
auto ShaderMap = GetGlobalShaderMap ( FeatureLevel ) ;
2020-09-24 00:43:27 -04:00
TShaderMapRef < FGenerateMipsVS > VertexShader ( ShaderMap ) ;
TShaderMapRef < FGenerateMipsPS > PixelShader ( ShaderMap ) ;
2019-11-18 18:19:05 -05:00
2024-03-25 12:03:28 -04:00
int32 SliceCount = 1 ;
2019-11-18 18:19:05 -05:00
2024-03-25 12:03:28 -04:00
FRDGTextureSRVDesc SRVDesc ( Texture ) ;
SRVDesc . NumMipLevels = 1 ;
if ( TextureDesc . Dimension = = ETextureDimension : : TextureCube )
{
SliceCount = ECubeFace : : CubeFace_MAX ;
SRVDesc . DimensionOverride = ETextureDimension : : Texture2DArray ;
SRVDesc . NumArraySlices = 1 ;
}
// Loop through each level of the mips that require creation and add a dispatch pass per level.
2022-01-07 10:39:08 -05:00
for ( uint8 MipLevel = 1 , MipCount = TextureDesc . NumMips ; MipLevel < MipCount ; + + MipLevel )
2019-11-18 18:19:05 -05:00
{
2020-09-24 00:43:27 -04:00
const uint32 InputMipLevel = MipLevel - 1 ;
2019-11-18 18:19:05 -05:00
2020-09-24 00:43:27 -04:00
const FIntPoint DestTextureSize (
FMath : : Max ( TextureDesc . Extent . X > > MipLevel , 1 ) ,
FMath : : Max ( TextureDesc . Extent . Y > > MipLevel , 1 ) ) ;
2024-03-25 12:03:28 -04:00
SRVDesc . MipLevel = InputMipLevel ;
2020-09-24 00:43:27 -04:00
2024-03-25 12:03:28 -04:00
for ( int32 SliceIndex = 0 ; SliceIndex < SliceCount ; + + SliceIndex )
2019-11-18 18:19:05 -05:00
{
2024-03-25 12:03:28 -04:00
SRVDesc . FirstArraySlice = SliceIndex ;
2019-11-18 18:19:05 -05:00
2024-03-25 12:03:28 -04:00
FGenerateMipsPS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FGenerateMipsPS : : FParameters > ( ) ;
PassParameters - > HalfTexelSize = FVector2f ( 0.5f / DestTextureSize . X , 0.5f / DestTextureSize . Y ) ;
PassParameters - > Level = InputMipLevel ;
PassParameters - > MipInSRV = GraphBuilder . CreateSRV ( SRVDesc ) ;
PassParameters - > MipSampler = Sampler ;
PassParameters - > RenderTargets [ 0 ] = FRenderTargetBinding ( Texture , ERenderTargetLoadAction : : ELoad , MipLevel , SliceCount > 1 ? SliceIndex : INDEX_NONE ) ;
2019-11-18 18:19:05 -05:00
2024-03-25 12:03:28 -04:00
GraphBuilder . AddPass (
RDG_EVENT_NAME ( " GenerateMips DestMipLevel=%d Slice=%d " , MipLevel , SliceIndex ) ,
PassParameters ,
ERDGPassFlags : : Raster ,
2024-09-05 11:12:23 -04:00
[ VertexShader , PixelShader , PassParameters , DestTextureSize ] ( FRDGAsyncTask , FRHICommandList & RHICmdList )
2024-03-25 12:03:28 -04:00
{
RHICmdList . SetViewport ( 0.0f , 0.0f , 0.0f , ( float ) DestTextureSize . X , ( float ) DestTextureSize . Y , 1.0f ) ;
FGraphicsPipelineStateInitializer GraphicsPSOInit ;
GraphicsPSOInit . DepthStencilState = TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ;
GraphicsPSOInit . RasterizerState = TStaticRasterizerState < > : : GetRHI ( ) ;
GraphicsPSOInit . BlendState = TStaticBlendStateWriteMask < CW_RGBA , CW_NONE , CW_NONE , CW_NONE , CW_NONE , CW_NONE , CW_NONE , CW_NONE > : : GetRHI ( ) ;
GraphicsPSOInit . PrimitiveType = PT_TriangleStrip ;
GraphicsPSOInit . BoundShaderState . VertexDeclarationRHI = GFilterVertexDeclaration . VertexDeclarationRHI ;
GraphicsPSOInit . BoundShaderState . VertexShaderRHI = VertexShader . GetVertexShader ( ) ;
GraphicsPSOInit . BoundShaderState . PixelShaderRHI = PixelShader . GetPixelShader ( ) ;
RHICmdList . ApplyCachedRenderTargets ( GraphicsPSOInit ) ;
SetGraphicsPipelineState ( RHICmdList , GraphicsPSOInit , 0 ) ;
SetShaderParameters ( RHICmdList , PixelShader , PixelShader . GetPixelShader ( ) , * PassParameters ) ;
FPixelShaderUtils : : DrawFullscreenTriangle ( RHICmdList , 1 ) ;
} ) ;
}
2019-11-18 18:19:05 -05:00
}
}
2022-08-18 15:29:29 -04:00
void FGenerateMips : : ExecuteCompute ( FRDGBuilder & GraphBuilder , ERHIFeatureLevel : : Type FeatureLevel , FRDGTextureRef Texture , FRHISamplerState * Sampler )
2019-05-30 14:48:02 -04:00
{
2020-09-24 00:43:27 -04:00
check ( Texture ) ;
check ( Sampler ) ;
2019-11-18 18:19:05 -05:00
2020-09-24 00:43:27 -04:00
const FRDGTextureDesc & TextureDesc = Texture - > Desc ;
2019-05-30 14:48:02 -04:00
2020-09-24 00:43:27 -04:00
// Select compute shader variant (normal vs. sRGB etc.)
2021-03-11 15:52:03 -04:00
bool bMipsSRGB = EnumHasAnyFlags ( TextureDesc . Flags , TexCreate_SRGB ) ;
const bool bMipsSwizzle = false ;
2020-02-12 13:27:19 -05:00
2019-11-05 10:01:21 -05:00
FGenerateMipsCS : : FPermutationDomain PermutationVector ;
2021-03-11 15:52:03 -04:00
PermutationVector . Set < FGenerateMipsCS : : FGenMipsSRGB > ( bMipsSRGB ) ;
PermutationVector . Set < FGenerateMipsCS : : FGenMipsSwizzle > ( bMipsSwizzle ) ;
2022-08-18 15:29:29 -04:00
TShaderMapRef < FGenerateMipsCS > ComputeShader ( GetGlobalShaderMap ( FeatureLevel ) , PermutationVector ) ;
2019-05-30 14:48:02 -04:00
2024-03-25 12:03:28 -04:00
int32 SliceCount = 1 ;
FRDGTextureSRVDesc SRVDesc ( Texture ) ;
FRDGTextureUAVDesc UAVDesc ( Texture ) ;
SRVDesc . NumMipLevels = 1 ;
if ( TextureDesc . Dimension = = ETextureDimension : : TextureCube )
{
SliceCount = ECubeFace : : CubeFace_MAX ;
SRVDesc . DimensionOverride = ETextureDimension : : Texture2DArray ;
SRVDesc . NumArraySlices = 1 ;
UAVDesc . DimensionOverride = ETextureDimension : : Texture2DArray ;
UAVDesc . NumArraySlices = 1 ;
}
2020-09-24 00:43:27 -04:00
// Loop through each level of the mips that require creation and add a dispatch pass per level.
2022-01-07 10:39:08 -05:00
for ( uint8 MipLevel = 1 , MipCount = TextureDesc . NumMips ; MipLevel < MipCount ; + + MipLevel )
2019-05-30 14:48:02 -04:00
{
2020-09-24 00:43:27 -04:00
const FIntPoint DestTextureSize (
FMath : : Max ( TextureDesc . Extent . X > > MipLevel , 1 ) ,
FMath : : Max ( TextureDesc . Extent . Y > > MipLevel , 1 ) ) ;
2019-05-30 14:48:02 -04:00
2024-03-25 12:03:28 -04:00
SRVDesc . MipLevel = ( int8 ) ( MipLevel - 1 ) ;
UAVDesc . MipLevel = ( int8 ) ( MipLevel ) ;
2019-05-30 14:48:02 -04:00
2024-03-25 12:03:28 -04:00
for ( int32 SliceIndex = 0 ; SliceIndex < SliceCount ; + + SliceIndex )
{
SRVDesc . FirstArraySlice = SliceIndex ;
UAVDesc . FirstArraySlice = SliceIndex ;
FGenerateMipsCS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FGenerateMipsCS : : FParameters > ( ) ;
PassParameters - > TexelSize = FVector2f ( 1.0f / DestTextureSize . X , 1.0f / DestTextureSize . Y ) ;
PassParameters - > MipInSRV = GraphBuilder . CreateSRV ( SRVDesc ) ;
PassParameters - > MipOutUAV = GraphBuilder . CreateUAV ( UAVDesc ) ;
PassParameters - > MipSampler = Sampler ;
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " GenerateMips DestMipLevel=%d Slice=%d " , MipLevel , SliceIndex ) ,
ComputeShader ,
PassParameters ,
FComputeShaderUtils : : GetGroupCount ( DestTextureSize , FComputeShaderUtils : : kGolden2DGroupSize ) ) ;
}
2019-05-30 14:48:02 -04:00
}
}
2022-08-18 15:29:29 -04:00
void FGenerateMips : : ExecuteCompute (
FRDGBuilder & GraphBuilder ,
ERHIFeatureLevel : : Type FeatureLevel ,
FRDGTextureRef Texture ,
FRHISamplerState * Sampler ,
FRDGBufferRef ConditionBuffer ,
uint32 Offset )
2021-10-29 12:53:33 -04:00
{
check ( Texture ) ;
check ( Sampler ) ;
2022-08-18 15:29:29 -04:00
FGlobalShaderMap * ShaderMap = GetGlobalShaderMap ( FeatureLevel ) ;
2021-10-29 12:53:33 -04:00
const FRDGTextureDesc & TextureDesc = Texture - > Desc ;
FRDGBufferRef IndirectDispatchArgsBuffer = GraphBuilder . CreateBuffer (
FRDGBufferDesc : : CreateIndirectDesc < FRHIDispatchIndirectParameters > ( FMath : : Max ( TextureDesc . NumMips - 1 , 1 ) ) ,
TEXT ( " IndirectDispatchArgsBuffer " ) ) ;
{
// build the indirect dispatch arguments buffer ( compute the group count on GPU conditionally)
FBuildIndirectDispatchArgsBufferCS : : FParameters * PassParameters =
GraphBuilder . AllocParameters < FBuildIndirectDispatchArgsBufferCS : : FParameters > ( ) ;
PassParameters - > TextureSize = TextureDesc . Extent ;
PassParameters - > Offset = Offset ;
PassParameters - > NumMips = TextureDesc . NumMips ;
PassParameters - > ConditionBuffer = GraphBuilder . CreateSRV ( ConditionBuffer , EPixelFormat : : PF_R32_UINT ) ;
PassParameters - > RWIndirectDispatchArgsBuffer = GraphBuilder . CreateUAV ( IndirectDispatchArgsBuffer , EPixelFormat : : PF_R32_UINT ) ;
2022-08-18 15:29:29 -04:00
TShaderMapRef < FBuildIndirectDispatchArgsBufferCS > ComputeShader ( ShaderMap ) ;
2021-10-29 12:53:33 -04:00
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " GenerateMips BuildIndirectArgs(Mips=%d) " , TextureDesc . NumMips ) ,
ComputeShader ,
PassParameters ,
FIntVector ( FMath : : DivideAndRoundUp ( TextureDesc . NumMips - 1 , FComputeShaderUtils : : kGolden2DGroupSize ) , 1 , 1 ) ) ;
}
// Select compute shader variant (normal vs. sRGB etc.)
bool bMipsSRGB = EnumHasAnyFlags ( TextureDesc . Flags , TexCreate_SRGB ) ;
const bool bMipsSwizzle = false ;
FGenerateMipsIndirectCS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FGenerateMipsIndirectCS : : FGenMipsSRGB > ( bMipsSRGB ) ;
PermutationVector . Set < FGenerateMipsIndirectCS : : FGenMipsSwizzle > ( bMipsSwizzle ) ;
2022-08-18 15:29:29 -04:00
TShaderMapRef < FGenerateMipsIndirectCS > ComputeShader ( ShaderMap , PermutationVector ) ;
2021-10-29 12:53:33 -04:00
// Loop through each level of the mips that require creation and add a dispatch pass per level.
2022-01-07 10:39:08 -05:00
for ( uint8 MipLevel = 1 , MipCount = TextureDesc . NumMips ; MipLevel < MipCount ; + + MipLevel )
2021-10-29 12:53:33 -04:00
{
const FIntPoint DestTextureSize (
FMath : : Max ( TextureDesc . Extent . X > > MipLevel , 1 ) ,
FMath : : Max ( TextureDesc . Extent . Y > > MipLevel , 1 ) ) ;
FGenerateMipsIndirectCS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FGenerateMipsIndirectCS : : FParameters > ( ) ;
2021-11-18 14:37:34 -05:00
PassParameters - > TexelSize = FVector2f ( 1.0f / DestTextureSize . X , 1.0f / DestTextureSize . Y ) ;
2021-10-29 12:53:33 -04:00
PassParameters - > MipInSRV = GraphBuilder . CreateSRV ( FRDGTextureSRVDesc : : CreateForMipLevel ( Texture , MipLevel - 1 ) ) ;
PassParameters - > MipOutUAV = GraphBuilder . CreateUAV ( FRDGTextureUAVDesc ( Texture , MipLevel ) ) ;
PassParameters - > MipSampler = Sampler ;
PassParameters - > IndirectDispatchArgsBuffer = IndirectDispatchArgsBuffer ;
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " GenerateMips DestMipLevel=%d " , MipLevel ) ,
ComputeShader ,
PassParameters ,
IndirectDispatchArgsBuffer , sizeof ( FRHIDispatchIndirectParameters ) * ( MipLevel - 1 ) ) ;
}
}
2021-12-10 20:36:40 -05:00
bool FGenerateMips : : WillFormatSupportCompute ( EPixelFormat InPixelFormat )
{
2024-04-08 10:34:40 -04:00
return UE : : PixelFormat : : HasCapabilities ( InPixelFormat , EPixelFormatCapabilities : : TypedUAVStore ) ;
2021-12-10 20:36:40 -05:00
}
2022-08-18 15:29:29 -04:00
void FGenerateMips : : Execute ( FRDGBuilder & GraphBuilder , ERHIFeatureLevel : : Type FeatureLevel , FRDGTextureRef Texture , FGenerateMipsParams Params , EGenerateMipsPass Pass )
2019-05-30 14:48:02 -04:00
{
2020-09-24 00:43:27 -04:00
if ( Texture - > Desc . NumMips > 1 )
2019-05-30 14:48:02 -04:00
{
2024-04-08 10:34:40 -04:00
FSamplerStateInitializerRHI SamplerInit ( Params . Filter , Params . AddressU , Params . AddressV , Params . AddressW ) ;
FSamplerStateRHIRef Sampler = * GraphBuilder . AllocObject < FSamplerStateRHIRef > ( RHICreateSamplerState ( SamplerInit ) ) ;
Execute ( GraphBuilder , FeatureLevel , Texture , Sampler , Pass ) ;
2019-05-30 14:48:02 -04:00
}
2019-09-14 09:45:25 -04:00
}
2022-08-18 15:29:29 -04:00
void FGenerateMips : : Execute ( FRDGBuilder & GraphBuilder , ERHIFeatureLevel : : Type FeatureLevel , FRDGTextureRef Texture , FRHISamplerState * Sampler , EGenerateMipsPass Pass )
2021-12-10 20:36:40 -05:00
{
2024-04-08 10:34:40 -04:00
# if PLATFORM_WINDOWS || PLATFORM_ANDROID || PLATFORM_LINUX
if ( RHIGetInterfaceType ( ) = = ERHIInterfaceType : : OpenGL )
2021-12-10 20:36:40 -05:00
{
2024-04-08 10:34:40 -04:00
// Special case for OpenGL. We can't use the above compute/pixel shaders due to lack of proper SRV support.
FGenerateMipsRHIImplParameters * PassParameters = GraphBuilder . AllocParameters < FGenerateMipsRHIImplParameters > ( ) ;
PassParameters - > Texture = Texture ;
2021-12-10 20:36:40 -05:00
2024-04-08 10:34:40 -04:00
GraphBuilder . AddPass ( RDG_EVENT_NAME ( " GenerateMips - OpenGL " ) , PassParameters , ERDGPassFlags : : Copy ,
2024-09-05 11:12:23 -04:00
[ Texture ] ( FRDGAsyncTask , FRHICommandList & RHICmdList )
2024-04-08 10:34:40 -04:00
{
RHICmdList . EnqueueLambda ( TEXT ( " GenerateMips - OpenGL " ) , [ Texture = Texture - > GetRHI ( ) ] ( FRHICommandList & )
{
GetIOpenGLDynamicRHI ( ) - > RHIGenerateMips ( Texture ) ;
} ) ;
} ) ;
2021-12-10 20:36:40 -05:00
}
else
2024-04-08 10:34:40 -04:00
# endif
2021-12-10 20:36:40 -05:00
{
2024-04-08 10:34:40 -04:00
if ( Pass = = EGenerateMipsPass : : AutoDetect )
{
// Use compute when the given texture has a UAV-compatible format and UAV create flag, otherwise fallback to raster.
Pass = WillFormatSupportCompute ( Texture - > Desc . Format ) & & EnumHasAnyFlags ( Texture - > Desc . Flags , ETextureCreateFlags : : UAV )
? EGenerateMipsPass : : Compute
: EGenerateMipsPass : : Raster ;
}
if ( Pass = = EGenerateMipsPass : : Compute )
{
ensureMsgf ( EnumHasAllFlags ( Texture - > Desc . Flags , ETextureCreateFlags : : UAV | ETextureCreateFlags : : ShaderResource ) ,
TEXT ( " Texture must be created with ETextureCreateFlags::UAV and ETextureCreateFlags::ShaderResource to be used in compute-based mip generation. " ) ) ;
ExecuteCompute ( GraphBuilder , FeatureLevel , Texture , Sampler ) ;
}
else
{
ensureMsgf ( EnumHasAllFlags ( Texture - > Desc . Flags , ETextureCreateFlags : : RenderTargetable | ETextureCreateFlags : : ShaderResource ) ,
TEXT ( " Texture must be created with ETextureCreateFlags::RenderTargetable and ETextureCreateFlags::ShaderResource to be used in raster-based mip generation. " ) ) ;
ExecuteRaster ( GraphBuilder , FeatureLevel , Texture , Sampler ) ;
}
2021-12-10 20:36:40 -05:00
}
}