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.pswp.cn/news/164834.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164834.shtml
英文地址,請注明出處:http://en.pswp.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…