Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/VT/VirtualTextureFeedbackBuffer.cpp
Jeremy Moore 22b4699cb8 #jira UE-157497
Add settings to FSceneViewFamily.
bOverrideVirtualTextureThrottle will disable the virtual texture page throttling.
VirtualTextureFeedbackFactor will set the feedback factor and defaults to r.vt.FeedbackFactor.
MRQ disables the virtual texture throttling and could override feedback factor based on some user setting.
#rnx
#preflight 630e9030e112483775620130

[CL 21714249 by Jeremy Moore in ue5-main branch]
2022-08-30 20:49:30 -04:00

124 lines
4.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "VT/VirtualTextureFeedbackBuffer.h"
#include "RenderGraphUtils.h"
#include "SceneView.h"
#include "VT/VirtualTextureFeedback.h"
int32 GetVirtualTextureFeedbackScale(FSceneViewFamily const* InViewFamily)
{
// Round to nearest power of two to ensure that shader maths is efficient and sampling sequence logic is simple.
const int32 VirtualTextureFeedbackFactor = InViewFamily ? InViewFamily->VirtualTextureFeedbackFactor : 0;
return FMath::RoundUpToPowerOfTwo(FMath::Max(VirtualTextureFeedbackFactor, 1));
}
FIntPoint GetVirtualTextureFeedbackBufferSize(FSceneViewFamily const* InViewFamily, FIntPoint InSceneTextureExtent)
{
return FIntPoint::DivideAndRoundUp(InSceneTextureExtent, GetVirtualTextureFeedbackScale(InViewFamily));
}
uint32 SampleVirtualTextureFeedbackSequence(FSceneViewFamily const* InViewFamily, uint32 InFrameIndex)
{
const uint32 TileSize = GetVirtualTextureFeedbackScale(InViewFamily);
const uint32 TileSizeLog2 = FMath::CeilLogTwo(TileSize);
const uint32 SequenceSize = FMath::Square(TileSize);
const uint32 PixelIndex = InFrameIndex % SequenceSize;
const uint32 PixelAddress = ReverseBits(PixelIndex) >> (32U - 2 * TileSizeLog2);
const uint32 X = FMath::ReverseMortonCode2(PixelAddress);
const uint32 Y = FMath::ReverseMortonCode2(PixelAddress >> 1);
const uint32 PixelSequenceIndex = X + Y * TileSize;
return PixelSequenceIndex;
}
void FVirtualTextureFeedbackBufferDesc::Init(int32 InBufferSize)
{
BufferSize = FIntPoint(InBufferSize, 1);
NumRects = 0;
TotalReadSize = InBufferSize;
}
void FVirtualTextureFeedbackBufferDesc::Init2D(FIntPoint InBufferSize)
{
BufferSize = InBufferSize;
NumRects = 0;
TotalReadSize = BufferSize.X * BufferSize.Y;
}
void FVirtualTextureFeedbackBufferDesc::Init2D(FIntPoint InUnscaledBufferSize, TArrayView<FIntRect> const& InUnscaledViewRects, int32 InBufferScale)
{
const int32 BufferScale = FMath::Max(InBufferScale, 1);
BufferSize = FIntPoint::DivideAndRoundUp(InUnscaledBufferSize, BufferScale);
NumRects = 0;
TotalReadSize = BufferSize.X * BufferSize.Y;
if (InUnscaledViewRects.Num() > 0 && InUnscaledViewRects[0].Size() != InUnscaledBufferSize)
{
NumRects = FMath::Min((int32)MaxRectPerTransfer, InUnscaledViewRects.Num());
TotalReadSize = 0;
for (int32 RectIndex = 0; RectIndex < NumRects; ++RectIndex)
{
FIntRect const& Rect = InUnscaledViewRects[RectIndex];
Rects[RectIndex].Min = FIntPoint::DivideAndRoundDown(Rect.Min, BufferScale);
Rects[RectIndex].Max = FIntPoint::DivideAndRoundUp(Rect.Max, BufferScale);
TotalReadSize += Rects[RectIndex].Area();
}
}
}
void FVirtualTextureFeedbackBuffer::Begin(FRDGBuilder& GraphBuilder, const FVirtualTextureFeedbackBufferDesc& InDesc)
{
// NOTE: Transitions and allocations are handled manually right now, because the VT feedback UAV is used by
// the view uniform buffer, which is not an RDG uniform buffer. If it can be factored out into its own RDG
// uniform buffer (or put on the pass uniform buffers), then the resource can be fully converted to RDG.
Desc = InDesc;
FRDGBufferDesc BufferDesc(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), Desc.BufferSize.X * Desc.BufferSize.Y));
BufferDesc.Usage |= BUF_SourceCopy;
if (AllocatePooledBuffer(BufferDesc, PooledBuffer, TEXT("VirtualTextureFeedbackGPU")))
{
FRDGBufferUAVDesc UAVDesc;
UAVDesc.Format = PF_R32_UINT;
UAV = PooledBuffer->GetOrCreateUAV(UAVDesc);
}
AddPass(GraphBuilder, RDG_EVENT_NAME("VirtualTextureClear"), [this](FRHICommandListImmediate& RHICmdList)
{
// Clear virtual texture feedback to default value
RHICmdList.Transition(FRHITransitionInfo(UAV, ERHIAccess::Unknown, ERHIAccess::UAVCompute));
RHICmdList.ClearUAVUint(UAV, FUintVector4(~0u, ~0u, ~0u, ~0u));
RHICmdList.Transition(FRHITransitionInfo(UAV, ERHIAccess::UAVCompute, ERHIAccess::UAVGraphics));
RHICmdList.BeginUAVOverlap(UAV);
});
}
void FVirtualTextureFeedbackBuffer::End(FRDGBuilder& GraphBuilder)
{
AddPass(GraphBuilder, RDG_EVENT_NAME("VirtualTextureFeedbackCopy"), [this](FRHICommandListImmediate& RHICmdList)
{
RHICmdList.EndUAVOverlap(UAV);
RHICmdList.Transition(FRHITransitionInfo(UAV, ERHIAccess::UAVGraphics, ERHIAccess::CopySrc));
SubmitVirtualTextureFeedbackBuffer(RHICmdList, PooledBuffer->GetRHI(), Desc);
});
}
void FVirtualTextureFeedbackBuffer::ReleaseRHI()
{
PooledBuffer = nullptr;
UAV = nullptr;
}
void SubmitVirtualTextureFeedbackBuffer(FRHICommandListImmediate& RHICmdList, FBufferRHIRef const& InBuffer, FVirtualTextureFeedbackBufferDesc const& InDesc)
{
GVirtualTextureFeedback.TransferGPUToCPU(RHICmdList, InBuffer, InDesc);
}
void SubmitVirtualTextureFeedbackBuffer(class FRDGBuilder& GraphBuilder, FRDGBuffer* InBuffer, FVirtualTextureFeedbackBufferDesc const& InDesc)
{
GVirtualTextureFeedback.TransferGPUToCPU(GraphBuilder, InBuffer, InDesc);
}