RDG 纹理、RDG Buffer,即由 RDG 托管 的纹理、Buffer,本质上仅仅是一个名字和一份描述符(尺寸、格式),真正的显存分配发生在你调用 GraphBuilder.Execute() 之后,RDG 会统筹全局,极其聪明地复用显存。

RDG 纹理

创建 RDG 纹理

创建新纹理

CPP
// 创建纹理描述
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::Create2D
  • FRDGTextureDesc::Create2DArray
  • FRDGTextureDesc::Create3D
  • FRDGTextureDesc::CreateCube
  • FRDGTextureDesc::CreateCubeArray

外部注册

当需要把上一个系统的产物(比如屏幕空间的深度图、或是从游戏线程传进来的 UTexture2D)塞进 RDG 时,使用外部注册。

CPP
UTexture *Texture = ... // 各种纹理基本都继承自UTexture
FRDGTextureRef RDGTexture = RegisterExternalTexture(
	GraphBuilder,
	Texture->GetResource()->GetTexture2DRHI(),
	TEXT("Name")
);
点击展开查看更多

RDG 纹理的使用

参考

RDG Buffer

创建 RDG Buffer

CPP
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()失效,如果需要传到外部使用建议通过外部注册,如果是仅在渲染系统内部使用,例如跨帧调用,也就是这一帧的输出作为下一帧的输入,则需要进行导出上一帧

CPP
TRefCountPtr<IPooledRenderTarget> OutRT;
GraphBuilder.QueueTextureExtraction(RDGTexture, &OutRT);
TRefCountPtr<FRDGPooledBuffer> OutBuffer;
GraphBuilder.QueueBufferExtraction(RDGBuffer, &OutBuffer);
点击展开查看更多

下一帧

CPP
// 注意这里用的不是上面用的工具函数`RegisterExternalTexture`
FRDGTextureRef RDGTexture = GraphBuilder.RegisterExternalTexture(OutRT, TEXT("Name"));
FRDGBufferRef RDGBuffer = GraphBuilder.RegisterExternalBuffer(OutBuffer, TEXT("Name"));
点击展开查看更多

此外还可以导出到CPU

CPP
#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

版权声明

作者: Cheyne Xie

链接: https://chaim.eu.org/posts/7034ce61/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键