diff --git a/BladeSmith.sln.DotSettings.user b/BladeSmith.sln.DotSettings.user index d87c8ec..7b4f914 100644 --- a/BladeSmith.sln.DotSettings.user +++ b/BladeSmith.sln.DotSettings.user @@ -2,6 +2,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/Content/Maps/Demo.umap b/Content/Maps/Demo.umap index d24cbc5..c9eb402 100644 Binary files a/Content/Maps/Demo.umap and b/Content/Maps/Demo.umap differ diff --git a/Source/BladeSmith/Shaders/FTemperatureComputeShader.cpp b/Plugins/MiceShaders/Source/MiceShaders/Private/FTemperatureComputeShader.cpp similarity index 100% rename from Source/BladeSmith/Shaders/FTemperatureComputeShader.cpp rename to Plugins/MiceShaders/Source/MiceShaders/Private/FTemperatureComputeShader.cpp diff --git a/Source/BladeSmith/Shaders/FTemperatureComputeShader.h b/Plugins/MiceShaders/Source/MiceShaders/Public/FTemperatureComputeShader.h similarity index 92% rename from Source/BladeSmith/Shaders/FTemperatureComputeShader.h rename to Plugins/MiceShaders/Source/MiceShaders/Public/FTemperatureComputeShader.h index fecad12..f7bf1f0 100644 --- a/Source/BladeSmith/Shaders/FTemperatureComputeShader.h +++ b/Plugins/MiceShaders/Source/MiceShaders/Public/FTemperatureComputeShader.h @@ -8,7 +8,7 @@ /** * 温度传导计算着色器的调度参数 */ -struct BLADESMITH_API FTemperatureCSDispatchParams +struct MICESHADERS_API FTemperatureCSDispatchParams { // 体素网格分辨率 FIntVector VoxelResolution; @@ -42,7 +42,7 @@ struct BLADESMITH_API FTemperatureCSDispatchParams /** * 线程安全的温度计算参数队列 */ -struct FThreadSafeTemperatureParams +struct MICESHADERS_API FThreadSafeTemperatureParams { FCriticalSection ParamsCriticalSection; TArray PendingParams; @@ -52,12 +52,12 @@ struct FThreadSafeTemperatureParams }; // 全局参数存储 -extern BLADESMITH_API FThreadSafeTemperatureParams GTemperatureParams; +extern MICESHADERS_API FThreadSafeTemperatureParams GTemperatureParams; /** * 温度传导计算着色器类 */ -class BLADESMITH_API FTemperatureComputeShader : public FGlobalShader +class MICESHADERS_API FTemperatureComputeShader : public FGlobalShader { DECLARE_GLOBAL_SHADER(FTemperatureComputeShader); SHADER_USE_PARAMETER_STRUCT(FTemperatureComputeShader, FGlobalShader); diff --git a/Source/BladeSmith/DynamicIronBlock.cpp b/Source/BladeSmith/DynamicIronBlock.cpp index b3e367f..dae9ba0 100644 --- a/Source/BladeSmith/DynamicIronBlock.cpp +++ b/Source/BladeSmith/DynamicIronBlock.cpp @@ -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状态用于Lambda - bool bCurrentUseBufferA = bUseBufferA; + // 创建SRV/UAV(在游戏线程创建,捕获到lambda) + 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 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(); + 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); }); } diff --git a/Source/BladeSmith/DynamicIronBlock.h b/Source/BladeSmith/DynamicIronBlock.h index ffe82e4..8df2a11 100644 --- a/Source/BladeSmith/DynamicIronBlock.h +++ b/Source/BladeSmith/DynamicIronBlock.h @@ -4,6 +4,7 @@ #include "CoreMinimal.h" #include "DynamicMeshActor.h" +#include #include "DynamicIronBlock.generated.h" /** @@ -258,6 +259,9 @@ private: float TimeSinceLastUpdate = 0.0f; // 距离上次温度更新的时间 float TemperatureUpdateInterval = 0.1f; // 温度更新间隔(秒) + // GPU缓冲区是否已准备好(线程安全标志) + std::atomic bGPUBuffersReady{false}; + /** * 创建GPU缓冲区 */