304 lines
7.7 KiB
C++
304 lines
7.7 KiB
C++
/*
|
|
* gpu-instancing.cpp - GPU Instancing for UI Elements
|
|
*
|
|
* Production-ready example demonstrating:
|
|
* - GPU instancing for batch UI rendering
|
|
* - Shared material batches
|
|
* - Efficient VR/AR UI rendering
|
|
* - Low-latency UI updates
|
|
* - DOTS-style data-oriented UI architecture
|
|
*
|
|
* © 2026 - Agent Guardrails Template
|
|
*/
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "RenderCore/GPUInstancer.h"
|
|
#include "CommonUI/CommonUserWidget.h"
|
|
#include "Spatial/VolumetricRenderer.h"
|
|
#include "DDA/DDAManager.h"
|
|
|
|
namespace AgentGuardrails::UnrealUI
|
|
{
|
|
|
|
/**
|
|
* GPU Instancing Manager for UI Elements
|
|
* Batch renders UI components with shared materials
|
|
* Efficient rendering for VR/AR environments
|
|
*/
|
|
class UGPUInstancingManager : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
private:
|
|
GPUInstancer* gpuInstancer;
|
|
VolumetricRenderer* volumetricRenderer;
|
|
DDAManager* ddaManager;
|
|
|
|
TArray<UIInstance> uiInstances;
|
|
UMaterialInstance* sharedMaterial;
|
|
|
|
public:
|
|
void Initialize()
|
|
{
|
|
gpuInstancer = GPUInstancer::GetInstance();
|
|
volumetricRenderer = VolumetricRenderer::GetInstance();
|
|
ddaManager = DDAManager::GetInstance();
|
|
|
|
// Create shared material for UI instancing
|
|
sharedMaterial = CreateMaterialInstance("UISharedMaterial");
|
|
}
|
|
|
|
/**
|
|
* Batch renders UI elements through GPU instancing
|
|
* Efficient rendering for large UI hierarchies
|
|
*/
|
|
void RenderUIBatch(TArray<UCommonUserWidget*> widgets)
|
|
{
|
|
// Build instancing data
|
|
uiInstances.Reset();
|
|
for (auto* widget : widgets)
|
|
{
|
|
UIInstance instance;
|
|
instance.Position = widget->GetPosition();
|
|
instance.Scale = widget->GetScale();
|
|
instance.Color = widget->GetColor();
|
|
instance.Depth = widget->GetDepth();
|
|
instance.Material = sharedMaterial;
|
|
|
|
uiInstances.Add(instance);
|
|
}
|
|
|
|
// Submit batch to GPU instancer
|
|
gpuInstancer->RenderBatch(sharedMaterial, uiInstances);
|
|
}
|
|
|
|
/**
|
|
* Creates UI instance data for GPU rendering
|
|
*/
|
|
UIInstance CreateUIInstance(UCommonUserWidget* widget)
|
|
{
|
|
UIInstance instance;
|
|
instance.Position = widget->GetPosition();
|
|
instance.Scale = widget->GetScale();
|
|
instance.Color = widget->GetColor();
|
|
instance.Depth = widget->GetDepth();
|
|
instance.Material = sharedMaterial;
|
|
instance.IsVolumetric = widget->IsVolumetric();
|
|
instance.IsHolographic = widget->IsHolographic();
|
|
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Enables GPU instancing for widget
|
|
* Batch rendering optimization
|
|
*/
|
|
void EnableGPUInstancing(UCommonUserWidget* widget)
|
|
{
|
|
widget->EnableGPUInstancing(true);
|
|
widget->SetMaterial(sharedMaterial);
|
|
}
|
|
|
|
/**
|
|
* Updates instanced UI based on DDA tier
|
|
* Reduces batch complexity for stressed players
|
|
*/
|
|
void UpdateForDDATier(DDAManager::EDifficultyTier tier)
|
|
{
|
|
switch (tier)
|
|
{
|
|
case DDAManager::EDifficultyTier::Difficult:
|
|
// Stressed players: reduce batch count
|
|
SetBatchCount(50);
|
|
SetVolumetricIntensity(0.5f);
|
|
break;
|
|
|
|
case DDAManager::EDifficultyTier::Normal:
|
|
// Standard batch count
|
|
SetBatchCount(100);
|
|
SetVolumetricIntensity(1.0f);
|
|
break;
|
|
|
|
case DDAManager::EDifficultyTier::Relaxed:
|
|
// Engaged players: enhanced batching
|
|
SetBatchCount(200);
|
|
SetVolumetricIntensity(1.2f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets batch count for GPU instancing
|
|
*/
|
|
void SetBatchCount(int32 count)
|
|
{
|
|
gpuInstancer->SetMaxBatchCount(count);
|
|
}
|
|
|
|
/**
|
|
* Sets volumetric intensity for instanced widgets
|
|
*/
|
|
void SetVolumetricIntensity(float intensity)
|
|
{
|
|
volumetricRenderer->SetIntensity(intensity);
|
|
}
|
|
|
|
/**
|
|
* Prefetches UI instances for upcoming scene
|
|
* Predictive batching for performance
|
|
*/
|
|
void PrefetchUIInstances(int32 predictedCount)
|
|
{
|
|
uiInstances.Reserve(predictedCount);
|
|
for (int32 i = 0; i < predictedCount; i++)
|
|
{
|
|
UIInstance instance;
|
|
instance.Position = FVector::Zero();
|
|
instance.Scale = FVector2D::Zero();
|
|
instance.Color = FColor::Transparent;
|
|
instance.IsPrefetched = true;
|
|
|
|
uiInstances.Add(instance);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clears prefetched instances
|
|
* Memory cleanup after scene transition
|
|
*/
|
|
void ClearPrefetchedInstances()
|
|
{
|
|
uiInstances.RemoveAll([](const UIInstance& instance) {
|
|
return instance.IsPrefetched == true;
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* UI Instance data structure for GPU instancing
|
|
*/
|
|
USTRUCT()
|
|
struct UIInstance
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
FVector Position; // World position
|
|
FVector2D Scale; // UI scale
|
|
FColor Color; // Tint color
|
|
float Depth; // Z-depth for volumetric
|
|
UMaterialInstance* Material; // Shared material
|
|
bool IsVolumetric; // Volumetric rendering enabled
|
|
bool IsHolographic; // Holographic rendering enabled
|
|
bool IsPrefetched; // Prefetched instance
|
|
};
|
|
|
|
/**
|
|
* GPU Instancer for batch UI rendering
|
|
*/
|
|
class GPUInstancer
|
|
{
|
|
private:
|
|
static GPUInstancer* instance;
|
|
int32 maxBatchCount = 100;
|
|
|
|
public:
|
|
static GPUInstancer* GetInstance()
|
|
{
|
|
if (!instance)
|
|
{
|
|
instance = new GPUInstancer();
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Renders batch of UI instances
|
|
* Single GPU call for all elements
|
|
*/
|
|
void RenderBatch(UMaterialInstance* material, TArray<UIInstance>& instances)
|
|
{
|
|
// Create command buffer for batch render
|
|
auto* commandBuffer = new FRenderCommandBuffer();
|
|
|
|
// Submit instanced draw call
|
|
commandBuffer->DrawInstanced(
|
|
material,
|
|
instances,
|
|
instances.Size()
|
|
);
|
|
|
|
// Execute command buffer
|
|
commandBuffer->Execute();
|
|
}
|
|
|
|
/**
|
|
* Sets maximum batch count
|
|
*/
|
|
void SetMaxBatchCount(int32 count)
|
|
{
|
|
maxBatchCount = count;
|
|
}
|
|
|
|
/**
|
|
* Gets current batch count
|
|
*/
|
|
int32 GetMaxBatchCount() const
|
|
{
|
|
return maxBatchCount;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Material instance factory for UI instancing
|
|
*/
|
|
UMaterialInstance* CreateMaterialInstance(const FString& materialName)
|
|
{
|
|
auto* material = LoadObject<UMaterial>(nullptr, materialName);
|
|
return material->CreateMaterialInstance();
|
|
}
|
|
|
|
/**
|
|
* Batch UI rendering utilities
|
|
*/
|
|
namespace GPUInstancingUtils
|
|
{
|
|
/**
|
|
* Creates batch render command
|
|
*/
|
|
FRenderCommandBuffer* CreateBatchRenderCommand(
|
|
UMaterialInstance* material,
|
|
TArray<UIInstance>& instances
|
|
)
|
|
{
|
|
auto* commandBuffer = new FRenderCommandBuffer();
|
|
commandBuffer->DrawInstanced(material, instances, instances.Size());
|
|
return commandBuffer;
|
|
}
|
|
|
|
/**
|
|
* Validates instance data for GPU rendering
|
|
*/
|
|
bool ValidateInstance(const UIInstance& instance)
|
|
{
|
|
return instance.Material != nullptr &&
|
|
instance.Color.Alpha > 0.0f;
|
|
}
|
|
|
|
/**
|
|
* Optimizes instance array for batching
|
|
*/
|
|
void OptimizeInstanceArray(TArray<UIInstance>& instances)
|
|
{
|
|
// Remove invalid instances
|
|
instances.RemoveAll([](const UIInstance& instance) {
|
|
return !ValidateInstance(instance);
|
|
});
|
|
|
|
// Sort by material for efficient batching
|
|
instances.SortBy([](const UIInstance& instance) {
|
|
return instance.Material->GetUniqueID();
|
|
});
|
|
}
|
|
}
|
|
|
|
} // namespace AgentGuardrails::UnrealUI
|