2022-12-02 15:09:41 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "RayTracingGeometry.h"
|
2023-06-01 18:13:20 -04:00
|
|
|
#include "RHICommandList.h"
|
2023-01-27 14:17:39 -05:00
|
|
|
#include "HAL/IConsoleManager.h"
|
2023-11-16 11:28:36 -05:00
|
|
|
#include "RayTracingGeometryManagerInterface.h"
|
2022-12-02 15:09:41 -05:00
|
|
|
#include "RenderUtils.h"
|
2024-02-13 05:28:36 -05:00
|
|
|
#include "RHIResourceReplace.h"
|
2023-01-27 14:54:10 -05:00
|
|
|
#include "RHITextureReference.h" // IWYU pragma: keep
|
2022-12-02 15:09:41 -05:00
|
|
|
|
2023-11-16 11:28:36 -05:00
|
|
|
#if RHI_RAYTRACING
|
|
|
|
|
|
|
|
|
|
IRayTracingGeometryManager* GRayTracingGeometryManager = nullptr;
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-08-31 17:40:48 -04:00
|
|
|
static TAutoConsoleVariable<int32> CVarDebugForceRuntimeBLAS(
|
2022-12-02 15:09:41 -05:00
|
|
|
TEXT("r.Raytracing.DebugForceRuntimeBLAS"),
|
2023-08-31 17:40:48 -04:00
|
|
|
0,
|
2022-12-02 15:09:41 -05:00
|
|
|
TEXT("Force building BLAS at runtime."),
|
|
|
|
|
ECVF_ReadOnly);
|
|
|
|
|
|
2024-02-27 11:57:07 -05:00
|
|
|
PRAGMA_DISABLE_DEPRECATION_WARNINGS // Remove this in UE 5.6 once RayTracingGeometryRHI is made private
|
|
|
|
|
|
2022-12-02 15:09:41 -05:00
|
|
|
#if RHI_RAYTRACING
|
|
|
|
|
|
2024-02-13 05:28:36 -05:00
|
|
|
void FRayTracingGeometry::InitRHIForStreaming(FRHIRayTracingGeometry* IntermediateGeometry, FRHIResourceReplaceBatcher& Batcher)
|
2022-12-07 00:05:42 -05:00
|
|
|
{
|
2024-06-14 04:16:57 -04:00
|
|
|
checkf(IntermediateGeometry,
|
|
|
|
|
TEXT("IntermediateGeometry should be valid when streaming-in ray tracing geometry.\n")
|
|
|
|
|
TEXT("This will result in FRayTracingGeometry not being correctly initialized.\n")
|
2023-10-17 11:52:48 -04:00
|
|
|
);
|
|
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
checkf(RayTracingGeometryRHI, TEXT("RayTracingGeometryRHI must be valid when InitRHIForStreaming is called.\n"));
|
|
|
|
|
|
2023-10-17 11:52:48 -04:00
|
|
|
Initializer.Type = ERayTracingGeometryInitializerType::Rendering;
|
|
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
Batcher.EnqueueReplace(RayTracingGeometryRHI, IntermediateGeometry);
|
|
|
|
|
|
|
|
|
|
EnumAddFlags(GeometryState, EGeometryStateFlags::Valid);
|
2022-12-07 00:05:42 -05:00
|
|
|
EnumAddFlags(GeometryState, EGeometryStateFlags::StreamedIn);
|
|
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
GRayTracingGeometryManager->RefreshRegisteredGeometry(RayTracingGeometryHandle);
|
2022-12-07 00:05:42 -05:00
|
|
|
}
|
|
|
|
|
|
2024-02-13 05:28:36 -05:00
|
|
|
void FRayTracingGeometry::ReleaseRHIForStreaming(FRHIResourceReplaceBatcher& Batcher)
|
2022-12-07 00:05:42 -05:00
|
|
|
{
|
2023-09-19 14:34:30 -04:00
|
|
|
RemoveBuildRequest();
|
|
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
checkf(RayTracingGeometryRHI, TEXT("RayTracingGeometryRHI must be valid when ReleaseRHIForStreaming is called.\n"));
|
|
|
|
|
|
2022-12-07 00:05:42 -05:00
|
|
|
EnumRemoveFlags(GeometryState, EGeometryStateFlags::StreamedIn);
|
2023-09-19 14:34:30 -04:00
|
|
|
EnumRemoveFlags(GeometryState, EGeometryStateFlags::Valid);
|
2022-12-07 00:05:42 -05:00
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
Batcher.EnqueueReplace(RayTracingGeometryRHI, nullptr);
|
2023-10-17 11:52:48 -04:00
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
Initializer.Type = ERayTracingGeometryInitializerType::StreamingDestination;
|
2024-05-10 15:16:02 -04:00
|
|
|
|
|
|
|
|
GRayTracingGeometryManager->RefreshRegisteredGeometry(RayTracingGeometryHandle);
|
2022-12-07 00:05:42 -05:00
|
|
|
}
|
|
|
|
|
|
2024-03-15 10:56:24 -04:00
|
|
|
void FRayTracingGeometry::RequestBuildIfNeeded(FRHICommandListBase& RHICmdList, ERTAccelerationStructureBuildPriority InBuildPriority)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
if (GetRequiresBuild())
|
|
|
|
|
{
|
2023-11-29 17:09:38 -05:00
|
|
|
RayTracingBuildRequestIndex = GRayTracingGeometryManager->RequestBuildAccelerationStructure(this, InBuildPriority);
|
2022-12-02 15:09:41 -05:00
|
|
|
SetRequiresBuild(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 14:26:10 -04:00
|
|
|
void FRayTracingGeometry::MakeResident(FRHICommandList& RHICmdList)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
2023-10-18 14:26:10 -04:00
|
|
|
check(EnumHasAllFlags(GeometryState, EGeometryStateFlags::Evicted) && RayTracingGeometryRHI == nullptr);
|
2024-06-14 04:16:57 -04:00
|
|
|
checkf(!EnumHasAllFlags(GeometryState, EGeometryStateFlags::StreamedIn),
|
|
|
|
|
TEXT("Evicted FRayTracingGeometry shouldn't have StreamedIn flag set."));
|
2024-05-07 08:58:33 -04:00
|
|
|
|
|
|
|
|
if (!ensureMsgf(DynamicGeometrySharedBufferGenerationID == NonSharedVertexBuffers,
|
|
|
|
|
TEXT("Cannot call MakeResident(...) on FRayTracingGeometry using shared vertex buffers.\n")
|
|
|
|
|
TEXT("Dynamic geometry should be rebuilt instead.")))
|
|
|
|
|
{
|
|
|
|
|
// if geometry is using shared buffers those buffers might not be valid at this point
|
|
|
|
|
// instead of being made resident here, dynamic geometries need to be manually updated as necessary
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-18 14:26:10 -04:00
|
|
|
EnumRemoveFlags(GeometryState, EGeometryStateFlags::Evicted);
|
2022-12-02 15:09:41 -05:00
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
InitRHI(RHICmdList);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
2023-09-15 15:31:24 -04:00
|
|
|
void FRayTracingGeometry::Evict()
|
|
|
|
|
{
|
2023-10-18 14:26:10 -04:00
|
|
|
check(!EnumHasAllFlags(GeometryState, EGeometryStateFlags::Evicted) && RayTracingGeometryRHI != nullptr);
|
2024-06-14 04:16:57 -04:00
|
|
|
|
2023-09-15 15:31:24 -04:00
|
|
|
RemoveBuildRequest();
|
|
|
|
|
RayTracingGeometryRHI.SafeRelease();
|
2023-10-18 14:26:10 -04:00
|
|
|
EnumAddFlags(GeometryState, EGeometryStateFlags::Evicted);
|
2024-06-10 15:29:33 -04:00
|
|
|
|
2024-06-14 04:16:57 -04:00
|
|
|
if (EnumHasAllFlags(GeometryState, EGeometryStateFlags::StreamedIn))
|
2024-06-10 15:29:33 -04:00
|
|
|
{
|
2024-06-14 04:16:57 -04:00
|
|
|
EnumRemoveFlags(GeometryState, EGeometryStateFlags::StreamedIn);
|
|
|
|
|
EnumRemoveFlags(GeometryState, EGeometryStateFlags::Valid);
|
|
|
|
|
|
|
|
|
|
Initializer.Type = ERayTracingGeometryInitializerType::StreamingDestination;
|
2024-06-10 15:29:33 -04:00
|
|
|
}
|
2024-05-10 15:16:02 -04:00
|
|
|
|
|
|
|
|
GRayTracingGeometryManager->RefreshRegisteredGeometry(RayTracingGeometryHandle);
|
|
|
|
|
|
2024-05-07 12:39:27 -04:00
|
|
|
if (GroupHandle != INDEX_NONE)
|
|
|
|
|
{
|
|
|
|
|
GRayTracingGeometryManager->RequestUpdateCachedRenderState(GroupHandle);
|
|
|
|
|
}
|
2023-09-15 15:31:24 -04:00
|
|
|
}
|
|
|
|
|
|
2023-11-29 17:09:38 -05:00
|
|
|
void FRayTracingGeometry::CreateRayTracingGeometry(FRHICommandListBase& RHICmdList, ERTAccelerationStructureBuildPriority InBuildPriority)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
// Release previous RHI object if any
|
|
|
|
|
ReleaseRHI();
|
|
|
|
|
|
|
|
|
|
if (RawData.Num())
|
|
|
|
|
{
|
2023-08-31 17:40:48 -04:00
|
|
|
check(Initializer.OfflineData == nullptr);
|
2022-12-02 15:09:41 -05:00
|
|
|
Initializer.OfflineData = &RawData;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-31 17:40:48 -04:00
|
|
|
if (CVarDebugForceRuntimeBLAS.GetValueOnAnyThread() && Initializer.OfflineData != nullptr)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
Initializer.OfflineData->Discard();
|
|
|
|
|
Initializer.OfflineData = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool bAllSegmentsAreValid = Initializer.Segments.Num() > 0 || Initializer.OfflineData;
|
|
|
|
|
for (const FRayTracingGeometrySegment& Segment : Initializer.Segments)
|
|
|
|
|
{
|
|
|
|
|
if (!Segment.VertexBuffer)
|
|
|
|
|
{
|
|
|
|
|
bAllSegmentsAreValid = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bAllSegmentsAreValid)
|
|
|
|
|
{
|
2023-09-21 11:59:18 -04:00
|
|
|
// Geometries with StreamingDestination type are initially created in invalid state until they are streamed in (see InitRHIForStreaming).
|
|
|
|
|
const bool bWithNativeResource = Initializer.Type != ERayTracingGeometryInitializerType::StreamingDestination;
|
|
|
|
|
if (bWithNativeResource)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
EnumAddFlags(GeometryState, EGeometryStateFlags::Valid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsRayTracingEnabled())
|
|
|
|
|
{
|
2023-06-19 13:56:56 -04:00
|
|
|
RayTracingGeometryRHI = RHICmdList.CreateRayTracingGeometry(Initializer);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
2023-10-18 14:26:10 -04:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
EnumAddFlags(GeometryState, EGeometryStateFlags::Evicted);
|
|
|
|
|
}
|
2022-12-02 15:09:41 -05:00
|
|
|
|
|
|
|
|
if (Initializer.OfflineData == nullptr)
|
|
|
|
|
{
|
|
|
|
|
// Request build if not skip
|
|
|
|
|
if (InBuildPriority != ERTAccelerationStructureBuildPriority::Skip)
|
|
|
|
|
{
|
2023-10-18 14:26:10 -04:00
|
|
|
if (RayTracingGeometryRHI)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
2023-11-29 17:09:38 -05:00
|
|
|
RayTracingBuildRequestIndex = GRayTracingGeometryManager->RequestBuildAccelerationStructure(this, InBuildPriority);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
SetRequiresBuild(false);
|
|
|
|
|
}
|
2024-06-10 15:29:33 -04:00
|
|
|
else if (bWithNativeResource)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
SetRequiresBuild(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-07-24 20:01:35 -04:00
|
|
|
if (RayTracingGeometryRHI && RayTracingGeometryRHI->IsCompressed())
|
|
|
|
|
{
|
2023-11-29 17:09:38 -05:00
|
|
|
RayTracingBuildRequestIndex = GRayTracingGeometryManager->RequestBuildAccelerationStructure(this, InBuildPriority);
|
2023-07-24 20:01:35 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-02 15:09:41 -05:00
|
|
|
SetRequiresBuild(false);
|
|
|
|
|
|
|
|
|
|
// Offline data ownership is transferred to the RHI, which discards it after use.
|
|
|
|
|
// It is no longer valid to use it after this point.
|
|
|
|
|
Initializer.OfflineData = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-10 15:16:02 -04:00
|
|
|
|
|
|
|
|
GRayTracingGeometryManager->RefreshRegisteredGeometry(RayTracingGeometryHandle);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FRayTracingGeometry::IsValid() const
|
|
|
|
|
{
|
2023-10-18 14:26:10 -04:00
|
|
|
// can't check IsInitialized() because current implementation of hair ray tracing support doesn't initialize resource
|
|
|
|
|
//check(IsInitialized());
|
|
|
|
|
|
2024-04-25 13:33:16 -04:00
|
|
|
const bool bIsValid = EnumHasAllFlags(GeometryState, EGeometryStateFlags::Valid);
|
2023-10-18 14:26:10 -04:00
|
|
|
|
2024-04-25 13:33:16 -04:00
|
|
|
if (bIsValid)
|
2023-10-18 14:26:10 -04:00
|
|
|
{
|
2024-04-25 13:33:16 -04:00
|
|
|
check(Initializer.TotalPrimitiveCount > 0);
|
|
|
|
|
check(RayTracingGeometryRHI != nullptr || EnumHasAllFlags(GeometryState, EGeometryStateFlags::Evicted));
|
2023-10-18 14:26:10 -04:00
|
|
|
}
|
|
|
|
|
|
2024-04-25 13:33:16 -04:00
|
|
|
return bIsValid;
|
2023-10-18 14:26:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FRayTracingGeometry::IsEvicted() const
|
|
|
|
|
{
|
|
|
|
|
// can't check IsInitialized() because current implementation of hair ray tracing support doesn't initialize resource
|
|
|
|
|
//check(IsInitialized());
|
|
|
|
|
|
|
|
|
|
const bool bIsEvicted = EnumHasAllFlags(GeometryState, EGeometryStateFlags::Evicted);
|
|
|
|
|
|
|
|
|
|
if (bIsEvicted)
|
|
|
|
|
{
|
|
|
|
|
check(RayTracingGeometryRHI == nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bIsEvicted;
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
2023-06-19 13:56:56 -04:00
|
|
|
void FRayTracingGeometry::InitRHI(FRHICommandListBase& RHICmdList)
|
2022-12-02 15:09:41 -05:00
|
|
|
{
|
|
|
|
|
if (!IsRayTracingAllowed())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ERTAccelerationStructureBuildPriority BuildPriority = Initializer.Type != ERayTracingGeometryInitializerType::Rendering
|
|
|
|
|
? ERTAccelerationStructureBuildPriority::Skip
|
|
|
|
|
: ERTAccelerationStructureBuildPriority::Normal;
|
2023-11-29 17:09:38 -05:00
|
|
|
CreateRayTracingGeometry(RHICmdList, BuildPriority);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FRayTracingGeometry::ReleaseRHI()
|
|
|
|
|
{
|
|
|
|
|
RemoveBuildRequest();
|
|
|
|
|
RayTracingGeometryRHI.SafeRelease();
|
2023-09-21 11:59:18 -04:00
|
|
|
GeometryState = EGeometryStateFlags::Invalid;
|
2024-08-22 15:24:21 -04:00
|
|
|
|
|
|
|
|
GRayTracingGeometryManager->RefreshRegisteredGeometry(RayTracingGeometryHandle);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FRayTracingGeometry::RemoveBuildRequest()
|
|
|
|
|
{
|
|
|
|
|
if (HasPendingBuildRequest())
|
|
|
|
|
{
|
2023-11-16 11:28:36 -05:00
|
|
|
GRayTracingGeometryManager->RemoveBuildRequest(RayTracingBuildRequestIndex);
|
2022-12-02 15:09:41 -05:00
|
|
|
RayTracingBuildRequestIndex = INDEX_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 13:55:57 -04:00
|
|
|
void FRayTracingGeometry::InitResource(FRHICommandListBase& RHICmdList)
|
|
|
|
|
{
|
2023-09-15 12:02:44 -04:00
|
|
|
ensureMsgf(IsRayTracingAllowed(), TEXT("FRayTracingGeometry should only be initialized when Ray Tracing is allowed."));
|
2023-09-04 13:55:57 -04:00
|
|
|
|
|
|
|
|
FRenderResource::InitResource(RHICmdList);
|
2023-09-14 14:36:39 -04:00
|
|
|
|
2023-09-15 12:02:44 -04:00
|
|
|
if (RayTracingGeometryHandle == INDEX_NONE)
|
|
|
|
|
{
|
2023-11-16 11:28:36 -05:00
|
|
|
RayTracingGeometryHandle = GRayTracingGeometryManager->RegisterRayTracingGeometry(this);
|
2023-09-15 12:02:44 -04:00
|
|
|
}
|
2023-09-04 13:55:57 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-02 15:09:41 -05:00
|
|
|
void FRayTracingGeometry::ReleaseResource()
|
|
|
|
|
{
|
2023-09-15 12:02:44 -04:00
|
|
|
ensureMsgf(IsRayTracingAllowed() || !IsInitialized(), TEXT("FRayTracingGeometry should only be initialized when Ray Tracing is allowed."));
|
2023-09-04 13:55:57 -04:00
|
|
|
|
2023-09-14 14:36:39 -04:00
|
|
|
if (RayTracingGeometryHandle != INDEX_NONE)
|
|
|
|
|
{
|
2023-11-16 11:28:36 -05:00
|
|
|
GRayTracingGeometryManager->ReleaseRayTracingGeometryHandle(RayTracingGeometryHandle);
|
2023-09-14 14:36:39 -04:00
|
|
|
RayTracingGeometryHandle = INDEX_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-25 10:51:24 -04:00
|
|
|
FRenderResource::ReleaseResource();
|
|
|
|
|
|
2022-12-02 15:09:41 -05:00
|
|
|
// Release any resource references held by the initializer.
|
|
|
|
|
// This includes index and vertex buffers used for building the BLAS.
|
|
|
|
|
Initializer = FRayTracingGeometryInitializer{};
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-25 12:03:10 -04:00
|
|
|
bool FRayTracingGeometry::HasPendingBuildRequest() const
|
|
|
|
|
{
|
|
|
|
|
const bool bHasPendingBuildRequest = RayTracingBuildRequestIndex != INDEX_NONE;
|
|
|
|
|
|
|
|
|
|
if (bHasPendingBuildRequest)
|
|
|
|
|
{
|
2024-04-25 13:33:16 -04:00
|
|
|
ensure(IsValid() && !IsEvicted());
|
2024-04-25 12:03:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bHasPendingBuildRequest;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 15:09:41 -05:00
|
|
|
void FRayTracingGeometry::BoostBuildPriority(float InBoostValue) const
|
|
|
|
|
{
|
|
|
|
|
check(HasPendingBuildRequest());
|
2023-11-16 11:28:36 -05:00
|
|
|
GRayTracingGeometryManager->BoostPriority(RayTracingBuildRequestIndex, InBoostValue);
|
2022-12-02 15:09:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // RHI_RAYTRACING
|
2024-02-27 11:57:07 -05:00
|
|
|
|
|
|
|
|
PRAGMA_ENABLE_DEPRECATION_WARNINGS
|