@@ -13,8 +13,8 @@
# include "GeometryScript/MeshNormalsFunctions.h"
# include "Materials/MaterialInstanceDynamic.h"
// GPU计算相关
# include "Shaders/ FTemperatureComputeShader.h"
// GPU计算相关(从MiceShaders插件引用)
# include "FTemperatureComputeShader.h"
# include "RHI.h"
# include "RHIResources.h"
# include "RHICommandList.h"
@@ -23,6 +23,8 @@
# include "GlobalShader.h"
# include "ShaderParameterStruct.h"
# include "RHIStaticStates.h"
# include "ShaderCompilerCore.h"
# include "ShaderCore.h"
ADynamicIronBlock : : ADynamicIronBlock ( )
{
@@ -39,7 +41,8 @@ ADynamicIronBlock::ADynamicIronBlock()
void ADynamicIronBlock : : BeginPlay ( )
{
Super : : BeginPlay ( ) ;
// 初始化 Box 网格
InitializeBoxMesh ( ) ;
// 创建GPU缓冲区
if ( bEnableTemperatureSystem & & TemperatureGrid . Num ( ) > 0 )
{
@@ -57,6 +60,12 @@ void ADynamicIronBlock::Tick(float DeltaTime)
return ;
}
// 检查GPU缓冲区是否准备好
if ( ! bGPUBuffersReady . load ( std : : memory_order_acquire ) )
{
return ;
}
// 累积时间
TimeSinceLastUpdate + = DeltaTime ;
@@ -88,7 +97,7 @@ void ADynamicIronBlock::OnConstruction(const FTransform& Transform)
Super : : OnConstruction ( Transform ) ;
// 初始化 Box 网格
InitializeBoxMesh ( ) ;
//InitializeBoxMesh();
}
void ADynamicIronBlock : : InitializeBoxMesh ( )
@@ -684,11 +693,11 @@ void ADynamicIronBlock::CreateGPUBuffers()
ENQUEUE_RENDER_COMMAND ( CreateTemperatureBuffers ) (
[ this , TotalVoxels , BufferSize , FlagsBufferSize ] ( FRHICommandListImmediate & RHICmdList )
{
// 创建温度缓冲A
// 创建温度缓冲A(使用ByteAddressBuffer而非StructuredBuffer)
FRHIBufferCreateDesc TempBufferADesc ;
TempBufferADesc . DebugName = TEXT ( " TemperatureBufferA " ) ;
TempBufferADesc . Size = BufferSize ;
TempBufferADesc . Usage = BUF_StructuredBuffer | BUF_ShaderResource | BUF_UnorderedAccess ;
TempBufferADesc . Usage = BUF_ShaderResource | BUF_UnorderedAccess ;
TempBufferADesc . InitialState = ERHIAccess : : UAVCompute ;
TemperatureBufferA = RHICmdList . CreateBuffer ( TempBufferADesc ) ;
TemperatureUAV_A = RHICmdList . CreateUnorderedAccessView ( TemperatureBufferA , FRHIViewDesc : : CreateBufferUAV ( ) . SetType ( FRHIViewDesc : : EBufferType : : Typed ) . SetFormat ( PF_R32_FLOAT ) ) ;
@@ -698,7 +707,7 @@ void ADynamicIronBlock::CreateGPUBuffers()
FRHIBufferCreateDesc TempBufferBDesc ;
TempBufferBDesc . DebugName = TEXT ( " TemperatureBufferB " ) ;
TempBufferBDesc . Size = BufferSize ;
TempBufferBDesc . Usage = BUF_StructuredBuffer | BUF_ShaderResource | BUF_UnorderedAccess ;
TempBufferBDesc . Usage = BUF_ShaderResource | BUF_UnorderedAccess ;
TempBufferBDesc . InitialState = ERHIAccess : : UAVCompute ;
TemperatureBufferB = RHICmdList . CreateBuffer ( TempBufferBDesc ) ;
TemperatureUAV_B = RHICmdList . CreateUnorderedAccessView ( TemperatureBufferB , FRHIViewDesc : : CreateBufferUAV ( ) . SetType ( FRHIViewDesc : : EBufferType : : Typed ) . SetFormat ( PF_R32_FLOAT ) ) ;
@@ -708,7 +717,7 @@ void ADynamicIronBlock::CreateGPUBuffers()
FRHIBufferCreateDesc PlasticityBufferDesc ;
PlasticityBufferDesc . DebugName = TEXT ( " PlasticityBuffer " ) ;
PlasticityBufferDesc . Size = BufferSize ;
PlasticityBufferDesc . Usage = BUF_StructuredBuffer | BUF_ShaderResource | BUF_UnorderedAccess ;
PlasticityBufferDesc . Usage = BUF_ShaderResource | BUF_UnorderedAccess ;
PlasticityBufferDesc . InitialState = ERHIAccess : : UAVCompute ;
PlasticityBuffer = RHICmdList . CreateBuffer ( PlasticityBufferDesc ) ;
PlasticityUAV = RHICmdList . CreateUnorderedAccessView ( PlasticityBuffer , FRHIViewDesc : : CreateBufferUAV ( ) . SetType ( FRHIViewDesc : : EBufferType : : Typed ) . SetFormat ( PF_R32_FLOAT ) ) ;
@@ -717,18 +726,28 @@ void ADynamicIronBlock::CreateGPUBuffers()
FRHIBufferCreateDesc FlagsBufferDesc ;
FlagsBufferDesc . DebugName = TEXT ( " SurfaceVoxelFlagsBuffer " ) ;
FlagsBufferDesc . Size = FlagsBufferSize ;
FlagsBufferDesc . Usage = BUF_StructuredBuffer | BUF_ShaderResource ;
FlagsBufferDesc . Usage = BUF_ShaderResource ;
FlagsBufferDesc . InitialState = ERHIAccess : : SRVCompute ;
SurfaceVoxelFlagsBuffer = RHICmdList . CreateBuffer ( FlagsBufferDesc ) ;
SurfaceVoxelSRV = RHICmdList . CreateShaderResourceView ( SurfaceVoxelFlagsBuffer , FRHIViewDesc : : CreateBufferSRV ( ) . SetType ( FRHIViewDesc : : EBufferType : : Typed ) . SetFormat ( PF_R32_UINT ) ) ;
UE_LOG ( LogTemp , Log , TEXT ( " DynamicIronBlock: GPU buffers created (%d voxels, %.2f MB) " ) ,
TotalVoxels , ( BufferSize * 3 + FlagsBufferSize ) / ( 1024.0f * 1024.0f ) ) ;
// 通知游戏线程缓冲区已准备好
AsyncTask ( ENamedThreads : : GameThread , [ this ] ( )
{
bGPUBuffersReady . store ( true , std : : memory_order_release ) ;
UE_LOG ( LogTemp , Log , TEXT ( " DynamicIronBlock: GPU buffers ready for use " ) ) ;
} ) ;
} ) ;
}
void ADynamicIronBlock : : ReleaseGPUBuffers ( )
{
// 先标记缓冲区为未准备状态,防止Tick中继续使用
bGPUBuffersReady . store ( false , std : : memory_order_release ) ;
ENQUEUE_RENDER_COMMAND ( ReleaseTemperatureBuffers ) (
[ this ] ( FRHICommandListImmediate & RHICmdList )
{
@@ -840,33 +859,111 @@ void ADynamicIronBlock::DispatchTemperatureCompute(float DeltaTime)
return ;
}
// 准备调度参数
FTemperatureCSDispatchParams Params ;
Params . VoxelResolution = TemperatureResolution ;
Params . ThermalConductivity = ThermalConductivity ;
Params . CoolingRate = CoolingRate ;
Params . AmbientTemperature = AmbientTemperature ;
Params . ForgeTemperatureMin = ForgeTemperatureMin ;
Params . ForgeTemperatureMax = ForgeTemperatureMax ;
Params . DeltaTime = DeltaTime ;
// 准备调度参数(捕获到lambda中)
FIntVector Resolution = TemperatureResolution ;
float Conductivity = ThermalConductivity ;
float Cooling = CoolingRate ;
float Ambient = AmbientTemperature ;
float ForgeMin = ForgeTemperatureMin ;
float ForgeMax = ForgeTemperatureMax ;
// Ping-Pong缓冲区
Params . InputTemperatureBuffer = bUseBufferA ? TemperatureBufferA : TemperatureBufferB ;
Params . OutputTemperatureUAV = bUseBufferA ? TemperatureUAV_B : TemperatureUAV_A ;
Params . SurfaceVoxelFlagsBuffer = SurfaceVoxelFlagsBuffer ;
Params . OutputPlasticityUAV = PlasticityUAV ;
// Ping-Pong缓冲区引用
FBufferRHIRef InputBuffer = bUseBufferA ? TemperatureBufferA : TemperatureBufferB ;
FBufferRHIRef OutputBuffer = bUseBufferA ? TemperatureBufferB : TemperatureBufferA ;
FBufferRHIRef FlagsBuffer = SurfaceVoxelFlagsBuffer ;
FBufferRHIRef PlasticityBuf = PlasticityBuffer ;
// 保存当前bUseBufferA状态用于L ambda
bool bCurrentUseBufferA = bUseBufferA ;
// 创建SRV/UAV(在游戏线程创建,捕获到l ambda)
FShaderResourceViewRHIRef InputSRV = TemperatureSRV_A ;
FShaderResourceViewRHIRef InputSRV_B = TemperatureSRV_B ;
FShaderResourceViewRHIRef FlagsSRV = SurfaceVoxelSRV ;
FUnorderedAccessViewRHIRef OutputUAV_A = TemperatureUAV_A ;
FUnorderedAccessViewRHIRef OutputUAV_B = TemperatureUAV_B ;
FUnorderedAccessViewRHIRef PlasticityUAV_Ref = PlasticityUAV ;
// 切换缓冲区
bool bReadFromA = bUseBufferA ;
// 切换缓冲区(下次Tick使用新的缓冲区)
bUseBufferA = ! bUseBufferA ;
// 调度GPU计算(使 用RDG)
// 调度GPU计算(直接使用RHI,不 用RDG)
ENQUEUE_RENDER_COMMAND ( DispatchTemperatureCS ) (
[ Params , bCurrentUseBufferA ] ( FRHICommandListImmediate & RHICmdList )
[ Resolution , Conductivity , Cooling , Ambient , ForgeMin , ForgeMax , DeltaTime ,
InputBuffer , OutputBuffer , FlagsBuffer , PlasticityBuf ,
InputSRV , InputSRV_B , FlagsSRV , OutputUAV_A , OutputUAV_B , PlasticityUAV_Ref , bReadFromA ]
( FRHICommandListImmediate & RHICmdList )
{
// 暂时简化实现,跳过GPU计算
UE_LOG ( LogTemp , Warning , TEXT ( " DynamicIronBlock: GPU temperature compute temporarily disabled (API compatibility) " ) ) ;
// 检查ShaderMap是否有效
FGlobalShaderMap * ShaderMap = GetGlobalShaderMap ( GMaxRHIFeatureLevel ) ;
if ( ! ShaderMap )
{
UE_LOG ( LogTemp , Error , TEXT ( " DynamicIronBlock: Global ShaderMap is null! " ) ) ;
return ;
}
// 获取Compute Shader并检查是否有效
TShaderMapRef < FTemperatureComputeShader > ComputeShader ( ShaderMap ) ;
if ( ! ComputeShader . IsValid ( ) )
{
UE_LOG ( LogTemp , Error , TEXT ( " DynamicIronBlock: FTemperatureComputeShader not found in ShaderMap! Make sure the shader is compiled. " ) ) ;
return ;
}
// 使用RDG(简化版本 - 创建临时缓冲区)
FRDGBuilder GraphBuilder ( RHICmdList , RDG_EVENT_NAME ( " TemperatureConduction " ) ) ;
// 创建RDG缓冲区描述
FRDGBufferDesc TempBufferDesc = FRDGBufferDesc : : CreateBufferDesc ( sizeof ( float ) , InputBuffer - > GetSize ( ) / sizeof ( float ) ) ;
FRDGBufferDesc FlagsBufferDesc = FRDGBufferDesc : : CreateBufferDesc ( sizeof ( uint32 ) , FlagsBuffer - > GetSize ( ) / sizeof ( uint32 ) ) ;
// 创建RDG缓冲区
FRDGBufferRef InputTempRDG = GraphBuilder . CreateBuffer ( TempBufferDesc , TEXT ( " InputTemperatureBuffer " ) ) ;
FRDGBufferRef OutputTempRDG = GraphBuilder . CreateBuffer ( TempBufferDesc , TEXT ( " OutputTemperatureBuffer " ) ) ;
FRDGBufferRef FlagsRDG = GraphBuilder . CreateBuffer ( FlagsBufferDesc , TEXT ( " SurfaceVoxelFlagsBuffer " ) ) ;
FRDGBufferRef PlasticityRDG = GraphBuilder . CreateBuffer ( TempBufferDesc , TEXT ( " PlasticityBuffer " ) ) ;
// TODO: 添加数据复制Pass(从RHI到RDG)
// 暂时跳过,shader会处理未初始化数据
// 设置Shader参数
FTemperatureComputeShader : : FParameters * PassParameters = GraphBuilder . AllocParameters < FTemperatureComputeShader : : FParameters > ( ) ;
PassParameters - > VoxelResolution = Resolution ;
PassParameters - > ThermalConductivity = Conductivity ;
PassParameters - > CoolingRate = Cooling ;
PassParameters - > AmbientTemperature = Ambient ;
PassParameters - > ForgeTemperatureMin = ForgeMin ;
PassParameters - > ForgeTemperatureMax = ForgeMax ;
PassParameters - > DeltaTime = DeltaTime ;
PassParameters - > InputTemperatureBuffer = GraphBuilder . CreateSRV ( InputTempRDG , PF_R32_FLOAT ) ;
PassParameters - > SurfaceVoxelFlagsBuffer = GraphBuilder . CreateSRV ( FlagsRDG , PF_R32_UINT ) ;
PassParameters - > OutputTemperatureBuffer = GraphBuilder . CreateUAV ( OutputTempRDG , PF_R32_FLOAT ) ;
PassParameters - > OutputPlasticityBuffer = GraphBuilder . CreateUAV ( PlasticityRDG , PF_R32_FLOAT ) ;
// 计算线程组数量
FIntVector GroupSize = FTemperatureComputeShader : : GetGroupSize ( ) ;
FIntVector GroupCount (
FMath : : DivideAndRoundUp ( Resolution . X , GroupSize . X ) ,
FMath : : DivideAndRoundUp ( Resolution . Y , GroupSize . Y ) ,
FMath : : DivideAndRoundUp ( Resolution . Z , GroupSize . Z )
) ;
// 添加计算Pass
FComputeShaderUtils : : AddPass (
GraphBuilder ,
RDG_EVENT_NAME ( " TemperatureConduction " ) ,
ComputeShader ,
PassParameters ,
GroupCount
) ;
// TODO: 添加数据复制Pass(从RDG回RHI)
// 暂时跳过,需要实现正确的缓冲区提取
// 执行RDG
GraphBuilder . Execute ( ) ;
UE_LOG ( LogTemp , Warning , TEXT ( " DynamicIronBlock: Temperature compute dispatched (%d x %d x %d groups) - Data copy not yet implemented " ) ,
GroupCount . X , GroupCount . Y , GroupCount . Z ) ;
} ) ;
}