Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 94 additions & 27 deletions trinity/Eve/EveSpaceScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,24 @@ bool EveSpaceScene::OnPrepareResources()
return true;
}

#if TBB_ENABLED
extern size_t g_currentThreadCount;
#endif

namespace
{
// Blocks of up to maxGrainSize objects, but never fewer than four tasks per thread so small scenes still spread out.
size_t GrainSize( size_t count, size_t maxGrainSize )
{
#if TBB_ENABLED
size_t grain = count / ( 4 * std::max<size_t>( g_currentThreadCount, 1 ) );
return std::clamp<size_t>( grain, 1, maxGrainSize );
#else
return maxGrainSize;
#endif
}
}

void EveSpaceScene::Update( Be::Time realTime, Be::Time simTime )
{
TRINITY_STATS_ZONE( __FUNCTION__ );
Expand Down Expand Up @@ -572,12 +590,12 @@ void EveSpaceScene::Update( Be::Time realTime, Be::Time simTime )
Tr2ParallelTaskGroup taskGroup = {};
m_updateContext.SetTaskGroup( &taskGroup );

for( auto& object : m_objects )
{
taskGroup.run( [object, this] {
object->UpdateAsyncronous( m_updateContext );
} );
}
Tr2ParallelFor( Tr2BlockedRange<size_t>( 0, m_objects.size(), GrainSize( m_objects.size(), 32 ) ), [&]( Tr2BlockedRange<size_t> range ) {
for( size_t i = range.begin(); i != range.end(); ++i )
{
m_objects[i]->UpdateAsyncronous( m_updateContext );
}
} );
for( auto& object : m_uiObjects )
{
taskGroup.run( [object, this] {
Expand Down Expand Up @@ -883,6 +901,15 @@ void GetBatchesFromRenderables( ITr2Renderable** const objectRenderables, const
}
}

namespace
{
enum PerObjectFlags : uint8_t
{
PER_OBJECT_DEFERRED = 1,
PER_OBJECT_TRANSPARENT = 2,
};
}

void GetBatchesFromRenderables(
ITr2Renderable** const objectRenderables,
const unsigned renderableCount,
Expand All @@ -895,27 +922,54 @@ void GetBatchesFromRenderables(
{
TRINITY_STATS_ZONE( __FUNCTION__ );

std::vector<Tr2PerObjectData*> perObjectData;
perObjectData.reserve( renderableCount );
std::vector<Tr2PerObjectData*> perObjectData( renderableCount, nullptr );
std::vector<uint8_t> flags( renderableCount, 0 );
ITriRenderBatchAccumulator* const opaqueBatches = batches[TRIBATCHTYPE_OPAQUE];
const bool wantTransparencies = objectsWithTransparencies != nullptr;

{
TRINITY_STATS_ZONE( "PerObjectData" );

Tr2ParallelFor( Tr2BlockedRange<unsigned>( 0, renderableCount, unsigned( GrainSize( renderableCount, 64 ) ) ), [&]( Tr2BlockedRange<unsigned> range ) {
for( unsigned i = range.begin(); i != range.end(); ++i )
{
ITr2Renderable* r = objectRenderables[i];
if( !r->SupportsParallelPerObjectData() )
{
flags[i] = PER_OBJECT_DEFERRED;
continue;
}
perObjectData[i] = r->GetPerObjectData( opaqueBatches );
if( wantTransparencies && r->HasTransparentBatches() )
{
flags[i] = PER_OBJECT_TRANSPARENT;
}
}
} );
for( unsigned i = 0; i != renderableCount; ++i )
{
if( flags[i] != PER_OBJECT_DEFERRED )
{
continue;
}
ITr2Renderable* r = objectRenderables[i];

perObjectData.push_back( r->GetPerObjectData( batches[TRIBATCHTYPE_OPAQUE] ) );
perObjectData[i] = r->GetPerObjectData( opaqueBatches );
flags[i] = wantTransparencies && r->HasTransparentBatches() ? PER_OBJECT_TRANSPARENT : 0;
}
}
{
TRINITY_STATS_ZONE( "GetBatches" );

Tr2EnumerableThreadSpecific<EveSpaceScene::PerThreadAccumulator>* threadBatches[TRIBATCHTYPE_COUNT_OF_BATCH_TYPES];
for( unsigned type = 0; type != batchTypeCount; ++type )
{
threadBatches[type] = &perThreadBatches[batchTypes[type]];
}
Tr2ParallelFor( unsigned( 0 ), renderableCount, [&]( unsigned i ) {
ITr2Renderable* r = objectRenderables[i];
for( unsigned type = 0; type != batchTypeCount; ++type )
{
r->GetBatches( &perThreadBatches[batchTypes[type]].local(), batchTypes[type], perObjectData[i], reason );
r->GetBatches( &threadBatches[type]->local(), batchTypes[type], perObjectData[i], reason );
}
} );
}
Expand All @@ -935,13 +989,11 @@ void GetBatchesFromRenderables(
{
TRINITY_STATS_ZONE( "Transparencies" );

objectsWithTransparencies->reserve( renderableCount );

for( unsigned i = 0; i != renderableCount; ++i )
{
ITr2Renderable* r = objectRenderables[i];
if( r->HasTransparentBatches() )
if( flags[i] == PER_OBJECT_TRANSPARENT )
{
ITr2Renderable* r = objectRenderables[i];
ITr2RenderableEntry entry;
entry.m_object = r;
entry.m_distance = r->GetSortValue();
Expand Down Expand Up @@ -1440,8 +1492,11 @@ void EveSpaceScene::GatherBatches( bool includeDistortions, Tr2RenderContext& re

{
TRINITY_STATS_ZONE( "UpdateVisibility" );
Tr2ParallelDo( m_objects.begin(), m_objects.end(), [&]( IEveSpaceObject2* obj ) {
obj->UpdateVisibility( m_updateContext, identity );
Tr2ParallelFor( Tr2BlockedRange<size_t>( 0, m_objects.size(), GrainSize( m_objects.size(), 32 ) ), [&]( Tr2BlockedRange<size_t> range ) {
for( size_t i = range.begin(); i != range.end(); ++i )
{
m_objects[i]->UpdateVisibility( m_updateContext, identity );
}
} );

m_cameraAttachmentParent->SetTransform( Tr2Renderer::GetInverseViewTransform() );
Expand Down Expand Up @@ -1540,9 +1595,15 @@ void EveSpaceScene::PrepareRaytracedShadows( Tr2RenderContext& renderContext )
ProcessOutdatedRTAnimations( renderContext );

auto& shadowCasters = m_componentRegistry->GetComponents<IEveShadowCaster>();
Tr2ParallelDo( begin( shadowCasters ), end( shadowCasters ), [&]( auto caster ) {
caster->PushRtGeometry( *m_rtManager );
} );
{
TRINITY_STATS_ZONE( "PushRtGeometry" );
Tr2ParallelFor( Tr2BlockedRange<size_t>( 0, shadowCasters.size(), GrainSize( shadowCasters.size(), 32 ) ), [&]( Tr2BlockedRange<size_t> range ) {
for( size_t i = range.begin(); i != range.end(); ++i )
{
shadowCasters[i]->PushRtGeometry( *m_rtManager );
}
} );
}

Tr2RtShaderTableDescriptionAL* shaderTableDescs[3];
Tr2RaytracingPipelineStateManager* pipelineManagers[3];
Expand Down Expand Up @@ -2391,9 +2452,9 @@ void EveSpaceScene::RenderIntoCloudShadowMap( Tr2RenderContext& renderContext, c
{
TRINITY_STATS_ZONE( "get shadowbatches for volumetrics" );
auto shadowFrustum = TriShadowOrthoFrustum( cloudShadowInformation->shadowFrustum, cloudShadowInformation->shadowMapSize, m_sunData.DirWorld );
float sizeInShadow = 0.0f;
for( auto& caster : shadowCasters )
{
float sizeInShadow = 0.0f;
caster->IsCastingShadow( frustum, shadowFrustum, TR2RENDERREASON_NORMAL, sizeInShadow );
// special threshold check
if( sizeInShadow > 5.0f )
Expand Down Expand Up @@ -2517,9 +2578,9 @@ void EveSpaceScene::RenderShadowMapForSpotLight(
shadowFrustum.DeriveFrustum( &view, &lightPosition, &projection, renderContext.m_esm.GetViewport() );
{
TRINITY_STATS_ZONE( "get shadowbatches for light" );
float sizeInShadow = 0.0f;
for( auto& caster : shadowCasters )
{
float sizeInShadow = 0.0f;
caster->IsCastingShadow( m_updateContext.GetFrustum(), TriShadowFrustum( shadowFrustum ), TR2RENDERREASON_NORMAL, sizeInShadow );
// special threshold check
if( sizeInShadow > 5.0f )
Expand Down Expand Up @@ -4183,6 +4244,7 @@ void EveSpaceScene::GetLightMatrices( const Tr2LightManager::PerLightData& light

void EveSpaceScene::ProcessOutdatedRTAnimations( Tr2RenderContext& renderContext )
{
TRINITY_STATS_ZONE( __FUNCTION__ );
TriFrustumOrtho sunShadowFrustum;
auto sunDir = m_sunData.DirWorld;

Expand Down Expand Up @@ -4245,15 +4307,20 @@ void EveSpaceScene::ProcessOutdatedRTAnimations( Tr2RenderContext& renderContext
}

// Find all casters and mark those that are casting shadows as dirty so RT can rebuild it
m_componentRegistry->ProcessComponents<IEveShadowCaster>( [&]( IEveShadowCaster* caster ) -> void {
const TriFrustum& cameraFrustum = m_updateContext.GetFrustum();
const TriShadowOrthoFrustum sunOrthoFrustum( sunShadowFrustum, SHADOW_MAP_SIZE, sunDir );
std::vector<TriShadowFrustum> spotShadowFrustums( begin( spotLightFrustums ), end( spotLightFrustums ) );

auto& casters = m_componentRegistry->GetComponents<IEveShadowCaster>();
Tr2ParallelDo( begin( casters ), end( casters ), [&]( IEveShadowCaster* caster ) {
if( caster->IsShadowCastingDirty() )
{
return;
}

{
float radius;
if( caster->IsCastingShadow( m_updateContext.GetFrustum(), TriShadowOrthoFrustum( sunShadowFrustum, SHADOW_MAP_SIZE, sunDir ), TR2RENDERREASON_NORMAL, radius ) )
if( caster->IsCastingShadow( cameraFrustum, sunOrthoFrustum, TR2RENDERREASON_NORMAL, radius ) )
{
caster->MarkRtDirty();
return;
Expand All @@ -4263,17 +4330,17 @@ void EveSpaceScene::ProcessOutdatedRTAnimations( Tr2RenderContext& renderContext

for( auto lightData : pointsLightDatas )
{
if( caster->IsCastingShadow( m_updateContext.GetFrustum(), lightData->position, lightData->radius, TR2RENDERREASON_NORMAL ) )
if( caster->IsCastingShadow( cameraFrustum, lightData->position, lightData->radius, TR2RENDERREASON_NORMAL ) )
{
caster->MarkRtDirty();
return;
}
}

for( const auto& shadowFrustum : spotLightFrustums )
for( const auto& shadowFrustum : spotShadowFrustums )
Comment thread
JohnGreenFC marked this conversation as resolved.
{
float sizeInShadow = 0.0f;
caster->IsCastingShadow( m_updateContext.GetFrustum(), TriShadowFrustum( shadowFrustum ), TR2RENDERREASON_NORMAL, sizeInShadow );
caster->IsCastingShadow( cameraFrustum, shadowFrustum, TR2RENDERREASON_NORMAL, sizeInShadow );
Comment thread
JohnGreenFC marked this conversation as resolved.
// special threshold check
if( sizeInShadow > 5.0f )
{
Expand Down
4 changes: 4 additions & 0 deletions trinity/Eve/SpaceObject/Children/EveChildMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ BLUE_CLASS( EveChildMesh ) :
void GetBatchesFromOverlayVector( ITriRenderBatchAccumulator * batches, const Tr2PerObjectData* perObjectData, TriBatchType batchType );
virtual float GetSortValue();
virtual Tr2PerObjectData* GetPerObjectData( ITriRenderBatchAccumulator * accumulator );
bool SupportsParallelPerObjectData() const override
{
return true;
}
virtual bool IsVisible( const EveUpdateContext& updateContext ) const override;

/////////////////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions trinity/Eve/SpaceObject/EveSpaceObject2.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ BLUE_CLASS( EveSpaceObject2 ) :
virtual void GetBatches( ITriRenderBatchAccumulator * batches, TriBatchType batchType, const Tr2PerObjectData* perObjectData, Tr2RenderReason reason = TR2RENDERREASON_NORMAL );
virtual float GetSortValue();
virtual Tr2PerObjectData* GetPerObjectData( ITriRenderBatchAccumulator * accumulator );
bool SupportsParallelPerObjectData() const override
{
return true;
}
virtual bool IsVisible( const EveUpdateContext& updateContext ) const override;

/////////////////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 6 additions & 0 deletions trinity/ITr2Renderable.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ BLUE_INTERFACE( ITr2Renderable ) :
virtual float GetSortValue() = 0;

virtual Tr2PerObjectData* GetPerObjectData( ITriRenderBatchAccumulator * accumulator ) = 0;

// True when GetPerObjectData and HasTransparentBatches only touch this object's own state and may run on worker threads.
virtual bool SupportsParallelPerObjectData() const
{
return false;
}
};
REGISTER_COMPONENT_TYPE( "ReflectionRenderable", ITr2Renderable );

Expand Down
14 changes: 12 additions & 2 deletions trinity/Tr2RingBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ uint32_t Tr2RingBuffer::UploadTransforms( const T* data, uint32_t dataCount )

void Tr2RingBuffer::PrepareBuffer( Tr2RenderContext& renderContext )
{
if( m_gpuBufferStale )
{
CreateGpuBuffer( renderContext.GetPrimaryRenderContext() );
}
for( auto& region : m_dirtyRegions )
{
if( region.size )
Expand Down Expand Up @@ -102,10 +106,14 @@ void Tr2RingBuffer::Resize( uint32_t size )
m_head = m_size;
m_size = size;
m_tail = m_size;
m_gpuBufferStale = true;
}

USE_MAIN_THREAD_RENDER_CONTEXT();
m_buffer.Create( m_stride, size, Tr2GpuUsage::SHADER_RESOURCE, Tr2CpuUsage::WRITE_OFTEN | Tr2CpuUsage::NON_SYNCRONIZED_WRITE, nullptr, renderContext );
void Tr2RingBuffer::CreateGpuBuffer( Tr2PrimaryRenderContextAL& renderContext )
{
m_buffer.Create( m_stride, m_size, Tr2GpuUsage::SHADER_RESOURCE, Tr2CpuUsage::WRITE_OFTEN | Tr2CpuUsage::NON_SYNCRONIZED_WRITE, nullptr, renderContext );
m_buffer.SetName( m_name.c_str() );
m_gpuBufferStale = false;
}

template <typename T>
Expand All @@ -120,6 +128,7 @@ Tr2RingBuffer& Tr2RingBuffer::GetInstance()
self->m_stride = sizeof( T );
self->SetFrameNumbers( renderContext.GetRecordingFrameNumber(), renderContext.GetRenderedFrameNumber() );
self->Resize( INITIAL_SIZE );
self->CreateGpuBuffer( renderContext );
}

CCP_ASSERT_M( sizeof( T ) == self->m_stride, "Stride has to match size of datatype!" );
Expand Down Expand Up @@ -147,6 +156,7 @@ bool Tr2RingBuffer::OnPrepareResources()
USE_MAIN_THREAD_RENDER_CONTEXT();
m_buffer.Create( m_stride, m_size, Tr2GpuUsage::SHADER_RESOURCE, Tr2CpuUsage::WRITE_OFTEN | Tr2CpuUsage::NON_SYNCRONIZED_WRITE, m_mirror.data(), renderContext );
m_buffer.SetName( m_name.c_str() );
m_gpuBufferStale = false;
}
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions trinity/Tr2RingBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ BLUE_CLASS( Tr2RingBuffer ) :
void ReleaseResources( TriStorage s ) override;
bool OnPrepareResources() override;

// UploadTransforms may run on worker threads, so Resize only grows the mirror;
// the GPU buffer is recreated in PrepareBuffer on the main thread.
void Resize( uint32_t size );
void CreateGpuBuffer( Tr2PrimaryRenderContextAL & renderContext );

std::string m_name;

uint32_t m_stride;
std::mutex m_mutex;
Tr2BufferAL m_buffer;
bool m_gpuBufferStale = false;
std::vector<uint8_t> m_mirror;

uint64_t m_frame = 0;
Expand Down
Loading
Loading