Hi, there. I need to get the scene depth values, and share through cuda interp to do some post processing.
And I found that cudaGraphicsD3D11RegisterResource
dont support depth or stencil , Surfaces of depth or stencil formats cannot be shared
says in the document, howerver DXGI_FORMAT_R32_FLOAT
is supported.
So my question is:
Is it posible to convert a Depth Texture (returned from GetSceneDepthTexture()
) to a PF_R32_FLOAT
format Texture?
I tried with the following code, but got 0
values all the time.
FIntPoint TextureSize;
float* cpuDataPtr; // Texture深度值数组首地址
TArray<float> mydata; //最终获取色深度值数据
ENQUEUE_RENDER_COMMAND(NeRFGenRHITexureToCUDA)(
[=, _this = this, &TextureSize](FRHICommandListImmediate& RHICmdList) mutable {
FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);
FTexture2DRHIRef RHITexture2D = FSceneRenderTargets::Get(RHICmdList).GetSceneDepthSurface();
if (_this->SceneDepthDevice != nullptr)
{
CUDA_CHECK_LOG(
cudaFree(_this->SceneDepthDevice)
);
}
CUDA_CHECK_LOG(
cudaMallocPitch(
&_this->SceneDepthDevice,
&_this->SceneDepthDevicePitch,
RHITexture2D->GetSizeX() * 1 * sizeof(float),
RHITexture2D->GetSizeY())
);
if (frame_no == 0)
{
UE_LOG(LogNeRF, Log, TEXT("RenderResolution: %f, %f"), RHITexture2D->GetSizeX(), RHITexture2D->GetSizeY());
}
TextureSize = RHITexture2D->GetSizeXY();
FRHIResourceCreateInfo CreateInfo;
FTexture2DRHIRef DepthFloatTexture = RHICmdList.CreateTexture2D(
TextureSize.X,
TextureSize.Y,
PF_R32_FLOAT,
1, 1,
TexCreate_RenderTargetable | TexCreate_ShaderResource,
CreateInfo);
FResolveParams ResolveParams;
//ResolveParams.CubeFace = ECubeFace::CubeFace_MAX;
//ResolveParams.Rect = FResolveRect(0, 0, TextureSize.X, TextureSize.Y);
//ResolveParams.DestRect = ResolveParams.Rect;
//ResolveParams.MipIndex = 0;
//ResolveParams.SourceArrayIndex = 0;
//ResolveParams.DestArrayIndex = 0;
RHICmdList.CopyToResolveTarget(RHITexture2D, DepthFloatTexture, ResolveParams);
mydata.AddUninitialized(TextureSize.X * TextureSize.Y);
uint32 Lolstrid = 0;
cpuDataPtr = (float*)RHILockTexture2D(DepthFloatTexture, 0, RLM_ReadOnly, Lolstrid, true); // 加锁 获取可读depth Texture深度值数组首地址
memcpy(mydata.GetData(), cpuDataPtr, TextureSize.X * TextureSize.Y * sizeof(float)); //复制深度数据
RHIUnlockTexture2D(DepthFloatTexture, 0, true); //解锁
if (!_this->RHICudaBridge.has_init())
{
res = _this->RHICudaBridge.init_resource(
DepthFloatTexture,
RHICmdList,
DXGI_FORMAT_R32_FLOAT,
D3D11_BIND_SHADER_RESOURCE
);
if (!res)
{
UE_LOG(LogNeRF, Error, TEXT("Initialize RHICudaBridge FAILED"));
return;
}
}
_this->RHICudaBridge.execute_from(
_this->SceneDepthDevice,
DepthFloatTexture,
DepthFloatTexture->GetSizeX(),
DepthFloatTexture->GetSizeY(),
//ViewportSize.X,
//ViewportSize.Y,
1,
_this->SceneDepthDevicePitch,
sizeof(float),
nullptr);
FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);
});
FlushRenderingCommands(); //等待渲染线程执行
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
static TSharedPtr<IImageWrapper> imageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::EXR); //EImageFormat::PNG //EImageFormat::JPEG
imageWrapper->SetRaw(mydata.GetData(), mydata.GetAllocatedSize(), TextureSize.X, TextureSize.Y, ERGBFormat::Gray, 32);
const TArray64<uint8>& PngData = imageWrapper->GetCompressed(0);
FFileHelper::SaveArrayToFile(PngData, TEXT("depth.exr"));