Hi, I’m so puzzled with compute shader recently, And I don’t know how to copy the result calculated from compute_shader. I try to copy the TextureRHI resource to a render target. But operation is always failed. could you give me some help? thank you very much.
static void UseComputeShader_RenderThread(
FRHICommandListImmediate& RHICmdList,
FTextureRenderTargetResource* OutputRenderTargetResource,
ERHIFeatureLevel::Type FeatureLevel
)
{
check(IsInRenderingThread());
TShaderMapRef<FMyComputeShader> ComputeShader(GetGlobalShaderMap(FeatureLevel));
RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
//ComputeShader->SetSurfaces(RHICmdList,)
int32 SizeX = OutputRenderTargetResource->GetSizeX();
int32 SizeY = OutputRenderTargetResource->GetSizeY();
FRHIResourceCreateInfo CreateInfo;
FTexture2DRHIRef Texture = RHICreateTexture2D(SizeX, SizeY, PF_A32B32G32R32F, 1, 1, TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
FUnorderedAccessViewRHIRef TextureUAV = RHICreateUnorderedAccessView(Texture);
ComputeShader->SetSurfaces(RHICmdList, TextureUAV);
DispatchComputeShader(RHICmdList, *ComputeShader, SizeX/32, SizeY/32, 1);
ComputeShader->UnbindBuffers(RHICmdList);
// Resolve render target.
RHICmdList.CopyToResolveTarget(
Texture,
OutputRenderTargetResource->TextureRHI,
true, FResolveParams());
//create a bitmap
TArray<FColor> Bitmap;
//To access our resource we do a custom read using lockrect
uint32 LolStride = 0;
char* TextureDataPtr = (char*)RHICmdList.LockTexture2D(Texture, 0, EResourceLockMode::RLM_ReadOnly, LolStride, false);
for (uint32 Row = 0; Row < Texture->GetSizeY(); ++Row)
{
uint32* PixelPtr = (uint32*)TextureDataPtr;
//Since we are using our custom UINT format, we need to unpack it here to access the actual colors
for (uint32 Col = 0; Col < Texture->GetSizeX(); ++Col)
{
uint32 EncodedPixel = *PixelPtr;
uint8 r = (EncodedPixel & 0x000000FF);
uint8 g = (EncodedPixel & 0x0000FF00) >> 8;
uint8 b = (EncodedPixel & 0x00FF0000) >> 16;
uint8 a = (EncodedPixel & 0xFF000000) >> 24;
Bitmap.Add(FColor(r, g, b, a));
PixelPtr++;
}
// move to next row:
TextureDataPtr += LolStride;
}
RHICmdList.UnlockTexture2D(Texture, 0, false);
// if the format and texture type is supported
if (Bitmap.Num())
{
// Create screenshot folder if not already present.
IFileManager::Get().MakeDirectory(*FPaths::ScreenShotDir(), true);
const FString ScreenFileName(FPaths::ScreenShotDir() / TEXT(“VisualizeTexture”));
uint32 ExtendXWithMSAA = Bitmap.Num() / Texture->GetSizeY();
// Save the contents of the array to a bitmap file. (24bit only so alpha channel is dropped)
FFileHelper::CreateBitmap(*ScreenFileName, ExtendXWithMSAA, Texture->GetSizeY(), Bitmap.GetData());
UE_LOG(LogConsoleResponse, Display, TEXT(“Content was saved to “%s””), *FPaths::ScreenShotDir());
}
else
{
UE_LOG(LogConsoleResponse, Error, TEXT(“Failed to save BMP, format or texture type is not supported”));
}
}