UE5 中的computer shader使用

转载:UE5 中的computer shader使用 - 知乎 (zhihu.com)

目标

  1. 通过蓝图输入参数,经过Compture Shader做矩阵运算

流程

1. 新建插件
2. 插件设置
3. 声明和GPU内存对齐的参数结构
4. 声明Compture Shader结构
5. 参数绑定
6. 着色器实现
7. 分配 work groups
8. 计算和输出
9. 额外添加参数

1. 新建插件

新建空白插件即可,正常插件创建流程,看官方文档,

2. 插件设置

XXX.Build.cs
		PrivateDependencyModuleNames.AddRange(new string[]{"CoreUObject","Engine","Renderer","RenderCore","RHI","Projects"// ... add private dependencies that you statically link with here ...	});
XXX.uplugin
"Modules": [{"Name": "CS_Test","Type": "Runtime","LoadingPhase": "PostConfigInit"}]

3. 声明和GPU内存对齐的参数结构

struct CS_TEST_API FMySimpleComputeShaderDispatchParams
{int X;int Y;int Z;int Input[2];int Output;FMySimpleComputeShaderDispatchParams(int x, int y, int z): X(x), Y(y), Z(z){}
};

4. 声明Compture Shader结构和参数绑定

MySimpleComputeShader.cpp
#include "MySimpleComputeShader.h"
#include "../../../Shaders/Public/MySimpleComputeShader.h"
#include "PixelShaderUtils.h"
#include "RenderCore/Public/RenderGraphUtils.h"
#include "MeshPassProcessor.inl"
#include "StaticMeshResources.h"
#include "DynamicMeshBuilder.h"
#include "RenderGraphResources.h"
#include "GlobalShader.h"
#include "UnifiedBuffer.h"
#include "CanvasTypes.h"
#include "MaterialShader.h"DECLARE_STATS_GROUP(TEXT("MySimpleComputeShader"), STATGROUP_MySimpleComputeShader, STATCAT_Advanced);
DECLARE_CYCLE_STAT(TEXT("MySimpleComputeShader Execute"), STAT_MySimpleComputeShader_Execute, STATGROUP_MySimpleComputeShader);// This class carries our parameter declarations and acts as the bridge between cpp and HLSL.
class CS_TEST_API FMySimpleComputeShader : public FGlobalShader
{
public:DECLARE_GLOBAL_SHADER(FMySimpleComputeShader);SHADER_USE_PARAMETER_STRUCT(FMySimpleComputeShader, FGlobalShader);class FMySimpleComputeShader_Perm_TEST : SHADER_PERMUTATION_INT("TEST", 1);using FPermutationDomain = TShaderPermutationDomain<FMySimpleComputeShader_Perm_TEST>;BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )/** Here's where you define one or more of the input parameters for your shader.* Some examples:*/// SHADER_PARAMETER(uint32, MyUint32) // On the shader side: uint32 MyUint32;// SHADER_PARAMETER(FVector3f, MyVector) // On the shader side: float3 MyVector;// SHADER_PARAMETER_TEXTURE(Texture2D, MyTexture) // On the shader side: Texture2D<float4> MyTexture; (float4 should be whatever you expect each pixel in the texture to be, in this case float4(R,G,B,A) for 4 channels)// SHADER_PARAMETER_SAMPLER(SamplerState, MyTextureSampler) // On the shader side: SamplerState MySampler; // CPP side: TStaticSamplerState<ESamplerFilter::SF_Bilinear>::GetRHI();// SHADER_PARAMETER_ARRAY(float, MyFloatArray, [3]) // On the shader side: float MyFloatArray[3];// SHADER_PARAMETER_UAV(RWTexture2D<FVector4f>, MyTextureUAV) // On the shader side: RWTexture2D<float4> MyTextureUAV;// SHADER_PARAMETER_UAV(RWStructuredBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: RWStructuredBuffer<FMyCustomStruct> MyCustomStructs;// SHADER_PARAMETER_UAV(RWBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: RWBuffer<FMyCustomStruct> MyCustomStructs;// SHADER_PARAMETER_SRV(StructuredBuffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: StructuredBuffer<FMyCustomStruct> MyCustomStructs;// SHADER_PARAMETER_SRV(Buffer<FMyCustomStruct>, MyCustomStructs) // On the shader side: Buffer<FMyCustomStruct> MyCustomStructs;// SHADER_PARAMETER_SRV(Texture2D<FVector4f>, MyReadOnlyTexture) // On the shader side: Texture2D<float4> MyReadOnlyTexture;// SHADER_PARAMETER_STRUCT_REF(FMyCustomStruct, MyCustomStruct)SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<int>, Input)SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, Output)END_SHADER_PARAMETER_STRUCT()public:static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters){const FPermutationDomain PermutationVector(Parameters.PermutationId);return true;}static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment){FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);const FPermutationDomain PermutationVector(Parameters.PermutationId);/** Here you define constants that can be used statically in the shader code.* Example:*/// OutEnvironment.SetDefine(TEXT("MY_CUSTOM_CONST"), TEXT("1"));/** These defines are used in the thread count section of our shader*/OutEnvironment.SetDefine(TEXT("THREADS_X"), NUM_THREADS_MySimpleComputeShader_X);OutEnvironment.SetDefine(TEXT("THREADS_Y"), NUM_THREADS_MySimpleComputeShader_Y);OutEnvironment.SetDefine(TEXT("THREADS_Z"), NUM_THREADS_MySimpleComputeShader_Z);// This shader must support typed UAV load and we are testing if it is supported at runtime using RHIIsTypedUAVLoadSupported//OutEnvironment.CompilerFlags.Add(CFLAG_AllowTypedUAVLoads);// FForwardLightingParameters::ModifyCompilationEnvironment(Parameters.Platform, OutEnvironment);}
private:
};// This will tell the engine to create the shader and where the shader entry point is.
//                            ShaderType                            ShaderPath                     Shader function name    Type
IMPLEMENT_GLOBAL_SHADER(FMySimpleComputeShader, "/Plugin/CS_Test/Private/MySimpleComputeShader.usf", "MySimpleComputeShader", SF_Compute);void FMySimpleComputeShaderInterface::DispatchRenderThread(FRHICommandListImmediate& RHICmdList, FMySimpleComputeShaderDispatchParams Params, TFunction<void(int OutputVal)> AsyncCallback) {FRDGBuilder GraphBuilder(RHICmdList);{SCOPE_CYCLE_COUNTER(STAT_MySimpleComputeShader_Execute);DECLARE_GPU_STAT(MySimpleComputeShader)RDG_EVENT_SCOPE(GraphBuilder, "MySimpleComputeShader");RDG_GPU_STAT_SCOPE(GraphBuilder, MySimpleComputeShader);typename FMySimpleComputeShader::FPermutationDomain PermutationVector;// Add any static permutation options here// PermutationVector.Set<FMySimpleComputeShader::FMyPermutationName>(12345);TShaderMapRef<FMySimpleComputeShader> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel), PermutationVector);bool bIsShaderValid = ComputeShader.IsValid();if (bIsShaderValid) {FMySimpleComputeShader::FParameters* PassParameters = GraphBuilder.AllocParameters<FMySimpleComputeShader::FParameters>();const void* RawData = (void*)Params.Input;int NumInputs = 2;int InputSize = sizeof(int);FRDGBufferRef InputBuffer = CreateUploadBuffer(GraphBuilder, TEXT("InputBuffer"), InputSize, NumInputs, RawData, InputSize * NumInputs);PassParameters->Input = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(InputBuffer, PF_R32_SINT));FRDGBufferRef OutputBuffer = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(int32), 1),TEXT("OutputBuffer"));PassParameters->Output = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(OutputBuffer, PF_R32_SINT));auto GroupCount = FComputeShaderUtils::GetGroupCount(FIntVector(Params.X, Params.Y, Params.Z), FComputeShaderUtils::kGolden2DGroupSize);GraphBuilder.AddPass(RDG_EVENT_NAME("ExecuteMySimpleComputeShader"),PassParameters,ERDGPassFlags::AsyncCompute,[&PassParameters, ComputeShader, GroupCount](FRHIComputeCommandList& RHICmdList){FComputeShaderUtils::Dispatch(RHICmdList, ComputeShader, *PassParameters, GroupCount);});FRHIGPUBufferReadback* GPUBufferReadback = new FRHIGPUBufferReadback(TEXT("ExecuteMySimpleComputeShaderOutput"));AddEnqueueCopyPass(GraphBuilder, GPUBufferReadback, OutputBuffer, 0u);auto RunnerFunc = [GPUBufferReadback, AsyncCallback](auto&& RunnerFunc) -> void {if (GPUBufferReadback->IsReady()) {int32* Buffer = (int32*)GPUBufferReadback->Lock(1);int OutVal = Buffer[0];GPUBufferReadback->Unlock();AsyncTask(ENamedThreads::GameThread, [AsyncCallback, OutVal]() {AsyncCallback(OutVal);});delete GPUBufferReadback;} else {AsyncTask(ENamedThreads::ActualRenderingThread, [RunnerFunc]() {RunnerFunc(RunnerFunc);});}};AsyncTask(ENamedThreads::ActualRenderingThread, [RunnerFunc]() {RunnerFunc(RunnerFunc);});} else {// We silently exit here as we don't want to crash the game if the shader is not found or has an error.}}GraphBuilder.Execute();
}
MySimpleComputeShader.h
#pragma once#include "CoreMinimal.h"
#include "GenericPlatform/GenericPlatformMisc.h"
#include "Kismet/BlueprintAsyncActionBase.h"#include "MySimpleComputeShader.generated.h"struct CS_TEST_API FMySimpleComputeShaderDispatchParams
{int X;int Y;int Z;int Input[2];int Output;FMySimpleComputeShaderDispatchParams(int x, int y, int z): X(x), Y(y), Z(z){}
};// This is a public interface that we define so outside code can invoke our compute shader.
class CS_TEST_API FMySimpleComputeShaderInterface {
public:// Executes this shader on the render threadstatic void DispatchRenderThread(FRHICommandListImmediate& RHICmdList,FMySimpleComputeShaderDispatchParams Params,TFunction<void(int OutputVal)> AsyncCallback);// Executes this shader on the render thread from the game thread via EnqueueRenderThreadCommandstatic void DispatchGameThread(FMySimpleComputeShaderDispatchParams Params,TFunction<void(int OutputVal)> AsyncCallback){ENQUEUE_RENDER_COMMAND(SceneDrawCompletion)([Params, AsyncCallback](FRHICommandListImmediate& RHICmdList){DispatchRenderThread(RHICmdList, Params, AsyncCallback);});}// Dispatches this shader. Can be called from any threadstatic void Dispatch(FMySimpleComputeShaderDispatchParams Params,TFunction<void(int OutputVal)> AsyncCallback){if (IsInRenderingThread()) {DispatchRenderThread(GetImmediateCommandList_ForRenderCommand(), Params, AsyncCallback);}else{DispatchGameThread(Params, AsyncCallback);}}
};DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMySimpleComputeShaderLibrary_AsyncExecutionCompleted, const int, Value);UCLASS() // Change the _API to match your project
class CS_TEST_API UMySimpleComputeShaderLibrary_AsyncExecution : public UBlueprintAsyncActionBase
{GENERATED_BODY()public:// Execute the actual loadvirtual void Activate() override {// Create a dispatch parameters struct and fill it the input array with our argsFMySimpleComputeShaderDispatchParams Params(1, 1, 1);Params.Input[0] = Arg1;Params.Input[1] = Arg2;// Dispatch the compute shader and wait until it completesFMySimpleComputeShaderInterface::Dispatch(Params, [this](int OutputVal) {this->Completed.Broadcast(OutputVal);});}UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", Category = "ComputeShader", WorldContext = "WorldContextObject"))static UMySimpleComputeShaderLibrary_AsyncExecution* ExecuteBaseComputeShader(UObject* WorldContextObject, int Arg1, int Arg2) {UMySimpleComputeShaderLibrary_AsyncExecution* Action = NewObject<UMySimpleComputeShaderLibrary_AsyncExecution>();Action->Arg1 = Arg1;Action->Arg2 = Arg2;Action->RegisterWithGameInstance(WorldContextObject);return Action;}UPROPERTY(BlueprintAssignable)FOnMySimpleComputeShaderLibrary_AsyncExecutionCompleted Completed;int Arg1;int Arg2;};

6. 着色器实现

MySimpleComputeShader.usf
#include "/Engine/Public/Platform.ush"Buffer<int> Input;
RWBuffer<int> Output;[numthreads(THREADS_X, THREADS_Y, THREADS_Z)]
void MySimpleComputeShader(uint3 DispatchThreadId : SV_DispatchThreadID,uint GroupIndex : SV_GroupIndex )
{// Outputs one numberOutput[0] = Input[0] * Input[1];
}

7. 分配 work groups

关于整个解释

https://learnopengl.com/Guest-Articles/2022/Compute-Shaders/Introduction​learnopengl.com/Guest-Articles/2022/Compute-Shaders/Introduction

[numthreads(THREADS_X, THREADS_Y, THREADS_Z)]
是在HLSL中分配计算空间的语法


8. 计算和输出


9. 额外添加参数流程





本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/164834.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VueRouter

路由介绍 1.思考 单页面应用程序&#xff0c;之所以开发效率高&#xff0c;性能好&#xff0c;用户体验好 最大的原因就是&#xff1a;页面按需更新 比如当点击【发现音乐】和【关注】时&#xff0c;只是更新下面部分内容&#xff0c;对于头部是不更新的 要按需更新&#…

Git 基本使用命令

Git 基本使用命令 下面是一些常用的 Git 基本使用命令&#xff1a; 初始化一个新的 Git 仓库&#xff1a; git init克隆&#xff08;Clone&#xff09;一个远程仓库到本地&#xff1a; git clone <repository_url>添加文件或目录到暂存区&#xff08;Staging Area&am…

微信小程序前端环境搭建

搭建微信小程序前端环境 申请小程序测试账号 访问路径 使用微信扫描二维码进行申请&#xff0c;申请成功之后&#xff0c;进入界面&#xff0c;获取小程序ID(AppID)和秘钥(AppSecret) 安装微信web开发者工具 访问路径 选择稳定开发的版本 需要在小程序的设置中将默认关闭…

geoserver发布tif矢量数据图层

cesium加载上传至geoserver的tif矢量数据_cesium加载tiff-CSDN博客 geoserver安装及跨域问题解决方案&#xff1a;geoserver安装及跨域问题解决方案_geoserver 跨域_1 1王的博客-CSDN博客 将TIF上传至geoserver 启动geoserver服务&#xff0c;并进入geoserver主页。 1. 新建…

【物联网产品架构】如何构建物联网产品路线图

面对现实吧。建立物联网产品路线图难度要比为“正常”技术产品制定路线图要困难得多。 这是因为IoT产品是复杂的系统。为了创建一个工作的解决方案&#xff0c;物联网技术栈的所有层 - 设备硬件&#xff0c;设备软件&#xff0c;通信&#xff0c;云平台和云应用都需要一起工作。…

Spring Cloud五大组件

Spring Cloud五大组件 Spring Cloud是分布式微服务架构的一站式解决方案&#xff0c;在Spring Boot基础上能够轻松搭建微服务系统的架构。 现有Spring Cloud有两代实现&#xff1a; 一代&#xff1a;Spring Cloud Netflix&#xff0c;主要由&#xff1a;Eureka、Ribbon、Feig…

【c语言】 逻辑运算符运算规则

1.&&逻辑运算符的坑 int x0&#xff0c;y0&#xff0c;z0; z (x1) && (y2); printf("%d"&#xff0c;y);//y0;今天遇到了同学问的问题&#xff0c;为什么y输出为0. 我第一时间也记不得&#xff0c;工作中一般不会写这种代码&#xff0c;但是却不能…

Vue3 状态管理 - Pinia

1. 什么是Pinia Pinia 是 Vue 的专属的最新状态管理库 &#xff0c;是 Vuex 状态管理工具的替代品 提供更加简单的APl&#xff08;去掉了mutation&#xff0c;Pinia 中对state数据的修改可以直接通过action&#xff0c;Vuex中则是通过mutation)提供符合组合式风格的API&#…

笔记转移:https://www.yuque.com/u32968635/lbk

语雀&#xff1a;https://www.yuque.com/u32968635/lbk

视频剪辑技巧:如何高效批量转码MP4视频为MOV格式

在视频剪辑的过程中&#xff0c;经常会遇到将MP4视频转码为MOV格式的情况。这不仅可以更好地编辑视频&#xff0c;还可以提升视频的播放质量和兼容性。对于大量视频文件的转码操作&#xff0c;如何高效地完成批量转码呢&#xff1f;现在一起来看看云炫AI智剪如何智能转码&#…

Servlte+JSP企业内容管理系统

企业内容管理系统的设计与实现 1&#xff0e;系统概述: 随着企事业单位信息化的建设&#xff0c;内联网和外联网之间的信息交互越来越多,优秀的内容管理系统对企业内部来说&#xff0c;能够很好地做到信息的收集和重复利用及信息的增值利用。对于外联网来说,内容管理系统可使…

6 Go的切片

概述 在上一节的内容中&#xff0c;我们介绍了Go的数组&#xff0c;包括&#xff1a;声明数组、初始化数组、访问数组元素等。在本节中&#xff0c;我们将介绍Go的切片。在Go语言中&#xff0c;数组的长度是固定的&#xff0c;不能改变&#xff0c;这在某些场景下使用不太方便。…

【C++】一文简练总结【多态】及其底层原理&具体应用(21)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.多态的概念二.多态的实现1&#xff…

【C++】:拷贝构造函数与赋值运算符重载的实例应用之日期类的实现

C实现日期类 ├─属性&#xff1a; │ ├─年份 │ ├─月份 │ └─日期 ├─方法&#xff1a; │ ├─构造函数 │ ├─拷贝构造函数 │ ├─析构函数 │ ├─设置年份 │ ├─设置月份 │ ├─设置日期 │ ├─获取年份 │ ├─获取月份 │ ├─获取日期 │ ├…

websocket和mqtt

WebSocket是一种通信协议&#xff0c;它允许在浏览器和服务器之间建立持久连接&#xff0c;并允许双向传递数据。MQTT则是一种轻量级的发布/订阅消息传输协议&#xff0c;常用于物联网(IoT)设备之间的通信。 &#xff08;1&#xff09;js能直接实现mqtt吗&#xff0c;还是需…

已解决java.lang.IllegalStateException: Duplicate key

已解决java.lang.IllegalStateException: Duplicate key 文章目录 报错问题解决思路解决方法交流 报错问题 java.lang.IllegalStateException: Duplicate key 解决思路 java.lang.IllegalStateException: Duplicate key 是由于在使用 Map 或 Set 时&#xff0c;试图将一个已经…

十、sdl显示yuv图片

前言 SDL中内置加载BMP的API&#xff0c;使用起来会更加简单&#xff0c;便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片&#xff0c;可以使用第三方库&#xff1a;SDL_image 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…

redis的性能管理和雪崩

redis的性能管理 redis的数据是缓存在内存当中的 系统巡检&#xff1a; 硬件巡检、数据库、nginx、redis、docker、k8s 运维人员必须要关注的redis指标 在日常巡检中需要经常查看这些指标使用情况 info memory #查看redis使用内存的指标 used_memory:11285512 #数据占用的…

最简单的简历练习

代码&#xff1a; <!DOCTYPE html> <html> <head> <title>我的简历</title> <style> body { background-image: url(https://picsum.photos/id/1018/1000/1000); background-size: cover; …

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法,亲测有效!!!

已解决java.lang.RuntimeException: java.io.IOException: invalid constant type: 18异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 文章目录 报错问题解决方法交流 报错问题 java.lang.RuntimeException: java.io.IOException: invalid cons…