RDG 纹理、RDG Buffer,即由 RDG 托管 的纹理、Buffer,本质上仅仅是一个名字和一份描述符(尺寸、格式),真正的显存分配发生在你调用 GraphBuilder.Execute() 之后,RDG 会统筹全局,极其聪明地复用显存。
RDG 纹理
创建 RDG 纹理
创建新纹理
// 创建纹理描述
FRDGTextureDesc RDGTextureDesc = FRDGTextureDesc::Create2D(
FIntPoint(SizeX, SizeY), // 纹理大小
EPixelFormat::PF_FloatRGBA, // 像素格式
FClearValueBinding::Black, // 清空时填充的颜色
ETextureCreateFlags::ShaderResource | ETextureCreateFlags::UAV // 创建标识,具体意义看源码的说明
);
// 创建 RDG 纹理
FRDGTextureRef RDGTexture = GraphBuilder.CreateTexture(RDGTextureDesc, TEXT("Name"));可以创建各种纹理描述:
FRDGTextureDesc::Create2DFRDGTextureDesc::Create2DArrayFRDGTextureDesc::Create3DFRDGTextureDesc::CreateCubeFRDGTextureDesc::CreateCubeArray
外部注册
当需要把上一个系统的产物(比如屏幕空间的深度图、或是从游戏线程传进来的 UTexture2D)塞进 RDG 时,使用外部注册。
UTexture *Texture = ... // 各种纹理基本都继承自UTexture
FRDGTextureRef RDGTexture = RegisterExternalTexture(
GraphBuilder,
Texture->GetResource()->GetTexture2DRHI(),
TEXT("Name")
);提示
- 直接使用
GraphBuilder.RegisterExternalTexture()也行,RegisterExternalTexture()本质上是一个对其进行封装的工具函数,具体可查看实现代码。 - 这里的
Texture->GetResource()在游戏线程中获取了再传到渲染线程也行。
RDG 纹理的使用
参考
RDG Buffer
创建 RDG Buffer
TArray<FMyData> MyData;
// 创建 RDGBuffer
FRDGBufferRef RDGMyData = GraphBuilder.CreateBuffer(
FRDGBufferDesc::CreateStructuredDesc(sizeof(FMyData), MyData.Num()),
TEXT("Data Name")
);
// 上传数据
GraphBuilder.QueueBufferUpload(
RDGMyData,
MyData.GetData(),
MyData.Num() * sizeof(FMyData)
);RDG Buffer 的使用
参考
导出 RDG 数据
所有 RDG 纹理、Buffer 在 GraphBuilder.Execute() 后失效,如果需要传到外部使用建议通过外部注册,如果是仅在渲染系统内部使用,例如跨帧调用,也就是这一帧的输出作为下一帧的输入,则需要进行导出。
上一帧
TRefCountPtr<IPooledRenderTarget> OutRT;
GraphBuilder.QueueTextureExtraction(RDGTexture, &OutRT);
TRefCountPtr<FRDGPooledBuffer> OutBuffer;
GraphBuilder.QueueBufferExtraction(RDGBuffer, &OutBuffer);下一帧
// 注意这里用的不是上面用的工具函数`RegisterExternalTexture`
FRDGTextureRef RDGTexture = GraphBuilder.RegisterExternalTexture(OutRT, TEXT("Name"));
FRDGBufferRef RDGBuffer = GraphBuilder.RegisterExternalBuffer(OutBuffer, TEXT("Name"));此外还可以导出到CPU
#include "RHIGPUReadback.h"
FRHIGPUTextureReadback ReadbackTextrue(TEXT("Name"));
FRHIGPUBufferReadback ReadbackBuffer(TEXT("Name"));
{
AddEnqueueCopyPass(GraphBuilder, &ReadbackTextrue, RDGTexture);
AddEnqueueCopyPass(GraphBuilder, &ReadbackBuffer, RDGBuffer, NumBytes);
GraphBuilder.Execute();
}
...
{
if (ReadbackTextrue.IsReady()) {
void* ptr = ReadbackTextrue.Lock(OutRowPitchInPixels);
}
if (ReadbackBuffer.IsReady()) {
void* ptr = ReadbackBuffer.Lock(NumBytes);
}
// 需要根据类型解释指针
}或许有用的函数
- AddCopyTexturePass
- AddCopyBufferPass
- AddClearUAVPass
- AddClearRenderTargetPass