调试shader

This commit is contained in:
2025-11-11 00:19:51 +08:00
parent d2b4a90251
commit f12fef4edd
9 changed files with 205 additions and 177 deletions
+4
View File
@@ -8,6 +8,8 @@ public class BladeSmith : ModuleRules
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
// 如果你的模块类型是 Runtime 或 Gameplay 相关的,则添加这行:
// bFasterWithoutUnity = false; // 确保非 Unity 构建也能正确加载
PublicDependencyModuleNames.AddRange(new string[] {
"Core",
"CoreUObject",
@@ -16,11 +18,13 @@ public class BladeSmith : ModuleRules
"EnhancedInput",
"RenderCore",
"RHI",
"RenderCore",
"Renderer",
"PhysicsCore",
"AudioExtensions",
"AudioMixer",
"AudioPlatformConfiguration"
});
}
}
+1 -35
View File
@@ -12,41 +12,7 @@
FThreadSafeDeformationParams GDeformationParams;
// 实现Compute Shader
IMPLEMENT_GLOBAL_SHADER(FDeformationCS, "/Shaders/Private/DeformationCS.usf", "MainCS", SF_Compute);
// 分派函数实现
void FDeformationCS::Dispatch(
FRHICommandListImmediate& RHICmdList,
const FDeformationCSDispatchParams& Params)
{
// 创建参数结构
FParameters Parameters;
Parameters.ImpactPoint = FVector3f(Params.ImpactPoint);
Parameters.ImpactNormal = FVector3f(Params.ImpactNormal);
Parameters.ImpactForce = Params.ImpactForce;
Parameters.DeformationRadius = Params.DeformationRadius;
Parameters.Plasticity = Params.Plasticity;
Parameters.InputTexture = Params.InputTexture;
Parameters.OutputTexture = Params.OutputTexture;
Parameters.TextureSize = Params.TextureSize;
Parameters.UpdateRegionMin = FIntVector(Params.UpdateRegion.Min.X, Params.UpdateRegion.Min.Y, 0);
Parameters.UpdateRegionSize = FIntVector(Params.UpdateRegion.Width(), Params.UpdateRegion.Height(), 1);
// 计算线程组数量
const int32 ThreadGroupSizeX = 8;
const int32 ThreadGroupSizeY = 8;
const int32 ThreadGroupSizeZ = 1;
const int32 GroupCountX = FMath::DivideAndRoundUp(Params.UpdateRegion.Width(), ThreadGroupSizeX);
const int32 GroupCountY = FMath::DivideAndRoundUp(Params.UpdateRegion.Height(), ThreadGroupSizeY);
const int32 GroupCountZ = 1;
// 分派Compute Shader
TShaderMapRef<FDeformationCS> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel));
SetComputePipelineState(RHICmdList, ComputeShader.GetComputeShader());
SetShaderParameters(RHICmdList, ComputeShader, ComputeShader.GetComputeShader(), Parameters);
RHICmdList.DispatchComputeShader(GroupCountX, GroupCountY, GroupCountZ);
}
IMPLEMENT_GLOBAL_SHADER(FDeformComputeShader, "/Engine/Private/MiceCola/DeformationCS.usf", "MainCompute", SF_Compute);
// 线程安全参数管理
void FThreadSafeDeformationParams::AddParams(const FDeformationCSDispatchParams& NewParams)
+32 -22
View File
@@ -1,13 +1,8 @@
#pragma once
#include "GlobalShader.h"
// DeformComputeShader.h
// DeformationCS.h
#pragma once
#include "CoreMinimal.h"
#include "RHI.h"
#include "RHIResources.h"
#include "GlobalShader.h"
#include "ShaderParameterStruct.h"
#include "RenderGraphUtils.h" // 必须包含
// Compute Shader参数结构体
struct FDeformationCSDispatchParams
@@ -52,43 +47,58 @@ extern FThreadSafeDeformationParams GDeformationParams;
// DeformationCS.h (续)
// Compute Shader类
class FDeformationCS : public FGlobalShader
class FDeformComputeShader : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FDeformationCS);
SHADER_USE_PARAMETER_STRUCT(FDeformationCS, FGlobalShader);
DECLARE_GLOBAL_SHADER(FDeformComputeShader);
SHADER_USE_PARAMETER_STRUCT(FDeformComputeShader, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
// 碰撞参数
SHADER_PARAMETER(FVector3f, ImpactPoint)
SHADER_PARAMETER(FVector3f, ImpactNormal)
SHADER_PARAMETER(float, ImpactForce)
SHADER_PARAMETER(FVector3f, ImpactNormal)
SHADER_PARAMETER(float, DeformationRadius)
SHADER_PARAMETER(float, Plasticity)
// 纹理参数
SHADER_PARAMETER_TEXTURE(Texture2D, InputTexture)
SHADER_PARAMETER_UAV(RWTexture2D<float4>, OutputTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, InputTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, OutputTexture)
// 更新区域
SHADER_PARAMETER(FIntVector, TextureSize)
SHADER_PARAMETER(FIntVector, UpdateRegionMin)
SHADER_PARAMETER(FIntVector, UpdateRegionSize)
SHADER_PARAMETER(FIntVector4, UpdateRegionParam)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
return GetMaxSupportedFeatureLevel(Parameters.Platform) >= ERHIFeatureLevel::SM5;
}
// 2. ✨ 修复 Precache 错误的关键:实现 ShouldPrecachePermutation
// 我们告诉引擎:在开发模式下,请始终预缓存这个着色器。
static EShaderPermutationPrecacheRequest ShouldPrecachePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
// 如果你的着色器没有使用任何模板或标志,只需返回 E_DEVELOPMENT 或 E_ALL。
return EShaderPermutationPrecacheRequest::Precached;
}
static bool ShouldCache(EShaderPlatform Platform)
{
return true;
}
// (假设你的 .usf 文件中线程组大小为 8x8x1)
static FIntVector GetGroupSize()
{
return FIntVector(8, 8, 1);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), 8);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), 8);
}
// 分派函数
static void Dispatch(
FRHICommandListImmediate& RHICmdList,
const FDeformationCSDispatchParams& Params);
};
+76 -56
View File
@@ -2,7 +2,9 @@
#include "IronBlock.h"
// 确保包含了 RDG 所需的头文件
#include "RenderGraphBuilder.h"
#include "RenderGraphUtils.h" // FComputeShaderUtils::AddPass
#include "FDeformComputeShader.h" // 确保这个头文件存在且包含了 FDeformationCSDispatchParams
#include "StaticMeshResources.h"
#include "TextureResource.h"
@@ -12,7 +14,6 @@
#include "Materials/MaterialInstanceDynamic.h"
#include "PhysicsEngine/BodySetup.h"
#include "RHICommandList.h"
#include "RenderGraphBuilder.h" // 包含 FRDGBuilder
#include "Engine/Texture.h"
#include "GenericPlatform/GenericPlatformProcess.h"
@@ -328,11 +329,11 @@ void AIronBlock::ExecuteDeformationCS()
// --- 关键修复: 在游戏线程只获取 Input RHI Texture 句柄 ---
FTextureRHIRef InputRHI = GetRenderTargetRHI(ReadTarget);
FTextureRHIRef WriteRHI = GetRenderTargetRHI(WriteTarget); // 必须获取写入目标的RHI
// 检查 Input RHI 和 WriteTarget UObject 是否有效
if (!InputRHI.IsValid() || !WriteTarget)
if (!InputRHI.IsValid() || !WriteRHI.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("Invalid texture RHI resources or WriteTarget UObject!"));
UE_LOG(LogTemp, Error, TEXT("Invalid texture RHI resources!"));
return;
}
@@ -355,68 +356,87 @@ void AIronBlock::ExecuteDeformationCS()
if (UpdateRegion.Min.X >= UpdateRegion.Max.X) UpdateRegion.Max.X = UpdateRegion.Min.X + 1;
if (UpdateRegion.Min.Y >= UpdateRegion.Max.Y) UpdateRegion.Max.Y = UpdateRegion.Min.Y + 1;
// 准备参数
FDeformationCSDispatchParams Params;
Params.ImpactPoint = CurrentImpactPoint; // 确保类型匹配 (FVector -> FVector3f)
Params.ImpactNormal = CurrentImpactNormal;
Params.ImpactForce = CurrentImpactForce;
Params.DeformationRadius = CurrentDeformationRadius;
Params.Plasticity = CurrentPlasticity;
Params.InputTexture = InputRHI;
//Params.OutputTexture = OutputUAV; // **直接使用RT的UAV**
Params.UpdateRegion = UpdateRegion;
Params.TextureSize = FIntVector(TexSize, TexSize, 1);
// 在渲染线程中执行Compute Shader
ENQUEUE_RENDER_COMMAND(ExecuteDeformationCS)(
[Params, WriteTarget](FRHICommandListImmediate& RHICmdList)
// --- 关键修改:使用 RDG ---
ENQUEUE_RENDER_COMMAND(ExecuteDeformationCS_RDG)(
[
// 捕获所有需要的参数
InputRHI,
WriteRHI,
CurrentImpactPoint = this->CurrentImpactPoint, // 拷贝一份
CurrentImpactNormal = this->CurrentImpactNormal,
CurrentImpactForce = this->CurrentImpactForce,
CurrentDeformationRadius = this->CurrentDeformationRadius,
CurrentPlasticity = this->CurrentPlasticity,
UpdateRegion, //
TexSize //
](FRHICommandListImmediate& RHICmdList)
{
// --- 现在我们在渲染线程上 ---
// 1. 创建 RDG Builder
FRDGBuilder builder(RHICmdList);
// 1. 从 UObject 获取 FTextureResource
FTextureResource* RTResource = WriteTarget->GetResource();
if (!RTResource)
// 2. 将我们的外部 RT 注册到 RDG 中
// 注意:我们使用 WriteRHI->GetDesc() 来获取纹理描述
FRDGTextureRef RDGReadTexture = builder.RegisterExternalTexture(
CreateRenderTarget(InputRHI, TEXT("DeformInputTex"))
);
FRDGTextureRef RDGWriteTexture = builder.RegisterExternalTexture(
CreateRenderTarget(WriteRHI, TEXT("DeformOutputTex"))
);
// 3. 分配着色器参数
FDeformComputeShader::FParameters* Params = builder.AllocParameters<FDeformComputeShader::FParameters>();
// 4. 填充 CPU 参数
Params->ImpactPoint = FVector3f(CurrentImpactPoint); // 注意:从 FVector 转为 FVector3f
Params->ImpactNormal = FVector3f(CurrentImpactNormal);
Params->ImpactForce = CurrentImpactForce;
Params->DeformationRadius = CurrentDeformationRadius;
Params->Plasticity = CurrentPlasticity;
Params->UpdateRegionParam = FIntVector4(UpdateRegion.Min.X, UpdateRegion.Min.Y, UpdateRegion.Max.X, UpdateRegion.Max.Y);
Params->TextureSize = FIntVector(TexSize, TexSize, 1);
// 5. ✨ 魔法发生的地方:RDG 为我们创建 SRV 和 UAV
// 这就是解决你 nullptr 问题的核心
Params->InputTexture = builder.CreateSRV(RDGReadTexture);
Params->OutputTexture = builder.CreateUAV(RDGWriteTexture);
// 6. 获取着色器实例
TShaderMapRef<FDeformComputeShader> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel));
if (!ComputeShader.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("Failed to get WriteTarget resource on render thread!"));
UE_LOG(LogTemp, Error, TEXT("FDeformComputeShader is not valid!"));
return;
}
// 2. 转换为 FTextureRenderTargetResource
FTextureRenderTargetResource* WriteRTResource = static_cast<FTextureRenderTargetResource*>(RTResource);
if (!WriteRTResource)
{
UE_LOG(LogTemp, Error, TEXT("Failed to cast to FTextureRenderTargetResource on render thread!"));
return;
}
// 7. 计算线程组数量
// (注意:你的USF需要处理 UpdateRegion,这里我们调度整个区域)
FIntVector NumGroups = FIntVector::DivideAndRoundUp(
FIntVector(UpdateRegion.Width(), UpdateRegion.Height(), 1),
FDeformComputeShader::GetGroupSize()
);
// 如果你的shader总是处理整个纹理,请使用:
// FIntVector NumGroups = FIntVector::DivideAndRoundUp(
// Params->TextureSize, FDeformComputeShader::GetGroupSize()
// );
// 3. ✨ 在渲染线程上调用 GetRenderTargetUAV()
FUnorderedAccessViewRHIRef OutputUAV = WriteRTResource->GetRenderTargetUAV();
// 8. 添加 Compute Pass
FComputeShaderUtils::AddPass(
builder,
RDG_EVENT_NAME("ExecuteDeformationCS"),
ComputeShader,
Params,
NumGroups
);
// 4. 检查是否成功
if (!OutputUAV.IsValid())
{
// 如果在这里仍然失败,说明 bCanCreateUAV=true 没有生效,
// 或者 RHI 后端没有为这个 RT 创建 UAV。
UE_LOG(LogTemp, Error, TEXT("GetRenderTargetUAV() returned null ON RENDER THREAD!"));
return;
}
// 5. 填充参数并调度
FDeformationCSDispatchParams RenderParams = Params;
RenderParams.OutputTexture = OutputUAV;
FDeformationCS::Dispatch(RHICmdList, RenderParams);
// 6. (重要) 添加一个UAV屏障
// 告诉GPU,Compute Shader对UAV的写入操作已完成,
// 在下一帧中,图形管线(材质)可以安全地将其作为 SRV (TextureSample) 读取。
RHICmdList.Transition(FRHITransitionInfo(OutputUAV, ERHIAccess::UAVCompute, ERHIAccess::SRVGraphics));
// 9. 执行 RDG (这会处理所有屏障和调度)
builder.Execute();
});
// 等待渲染命令完成,以便在CPU上读取 (如果需要立即更新碰撞体)
// 注意:这是一个同步点,会影响性能。
// --- 结束 RDG 修改 ---
// 确保渲染命令完成 (如果你需要立即更新碰撞体)
// FlushRenderingCommands();
// UpdateCollisionAsync(UpdateRegion, WriteTarget); // 异步更新碰撞体
// UpdateCollisionAsync(UpdateRegion, WriteTarget);
// --- 关键修复: 更新材质参数,使其下一帧读取我们刚刚写入的纹理 ---
if (DynMaterial)