From 64a8574bca3e670b2226f49f1d021779d424e9ab Mon Sep 17 00:00:00 2001 From: breki Date: Fri, 24 Jul 2026 16:19:52 +0000 Subject: [PATCH 01/23] first iteration of filling in evechildturret and fix some typoes in eveturretset and update clang format to never wrap --- .clang-format | 5 +- trinity/CMakeLists.txt | 3 + .../Eve/SpaceObject/Children/EveChildMesh.h | 6 +- .../SpaceObject/Children/EveChildTurret.cpp | 1108 +++++++++++++++++ .../Eve/SpaceObject/Children/EveChildTurret.h | 194 +++ .../Children/EveChildTurret_Blue.cpp | 13 + trinity/Eve/Turret/EveTurretSet.cpp | 18 +- 7 files changed, 1334 insertions(+), 13 deletions(-) create mode 100644 trinity/Eve/SpaceObject/Children/EveChildTurret.cpp create mode 100644 trinity/Eve/SpaceObject/Children/EveChildTurret.h create mode 100644 trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp diff --git a/.clang-format b/.clang-format index 039810cca..db9ae9ed3 100644 --- a/.clang-format +++ b/.clang-format @@ -113,7 +113,10 @@ BreakBeforeBraces: Custom BreakBeforeTernaryOperators: false BreakConstructorInitializers: AfterColon BreakStringLiterals: false -ColumnLimit: 120 +# Kept at 0 to match the Cpp section: some tools (e.g. CLion's ClangFormat +# integration) misclassify C++ .h files as ObjC and would otherwise re-wrap +# lines at the column limit. +ColumnLimit: 0 CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 diff --git a/trinity/CMakeLists.txt b/trinity/CMakeLists.txt index dc0e9c6e0..fe753d463 100644 --- a/trinity/CMakeLists.txt +++ b/trinity/CMakeLists.txt @@ -569,6 +569,9 @@ set(_SOURCES Eve/SpaceObject/Children/EveChildSpherePin_Blue.cpp Eve/SpaceObject/Children/EveChildTransform.cpp Eve/SpaceObject/Children/EveChildTransform.cpp + Eve/SpaceObject/Children/EveChildTurret.cpp + Eve/SpaceObject/Children/EveChildTurret.h + Eve/SpaceObject/Children/EveChildTurret_Blue.cpp Eve/SpaceObject/Children/EveCloudEditableVolume.cpp Eve/SpaceObject/Children/EveCloudEditableVolume.h Eve/SpaceObject/Children/EveCloudEditableVolume_Blue.cpp diff --git a/trinity/Eve/SpaceObject/Children/EveChildMesh.h b/trinity/Eve/SpaceObject/Children/EveChildMesh.h index 54d5e1b52..70c7e738c 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildMesh.h +++ b/trinity/Eve/SpaceObject/Children/EveChildMesh.h @@ -84,8 +84,8 @@ BLUE_CLASS( EveChildMesh ) : void UpdateVisibility( const EveUpdateContext& updateContext, const Matrix& parentTransform, Tr2Lod parentLod ); void GetRenderables( std::vector & renderables ); bool GetBoundingSphere( Vector4 & sphere, BoundingSphereQuery query = EVE_BOUNDS_NORMAL ) const; - void UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ); - void UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ); + void UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; + void UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; void GetLocalToWorldTransform( Matrix & transform ) const; void ChangeLOD( Tr2Lod lod ) override; virtual void Setup( const Vector3* scale, const Quaternion* rotation, const Vector3* translation, Tr2Lod lowestLodVisible ); @@ -193,7 +193,7 @@ BLUE_CLASS( EveChildMesh ) : virtual void ReleaseResources( TriStorage s ); virtual bool OnPrepareResources(); - void InitializeAnimation(); + virtual void InitializeAnimation(); bool ShouldReflect() const; bool DisplayDecals() const; diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp new file mode 100644 index 000000000..004ed80c5 --- /dev/null +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -0,0 +1,1108 @@ +// Copyright © 2026 Fenris Creations ehf. + +#include "StdAfx.h" +#include "EveChildTurret.h" +#include "Eve/Turret/EveTurretFiringFX.h" +#include "Tr2MeshBase.h" +#include "TriMath.h" +#include "TriObserverLocal.h" + +// names of system bones like they are in the granny file +static std::string s_systemBoneSkeletonNames[] = { + "invalid", // SYSBONE_INVALID + "Sys_Rotation_Arm", // SYSBONE_ROTATION + "Sys_Rotation_Arm01", // SYSBONE_ROTATION1 + "Sys_Rotation_Arm02", // SYSBONE_ROTATION2 + "Sys_CounterRotation", // SYSBONE_COUNTER_ROTATION + "Sys_Pitch_Barrel", // SYSBONE_PITCH + "Sys_Pitch_Barrel1", // SYSBONE_PITCH1 + "Sys_Pitch_Barrel2", // SYSBONE_PITCH2 + "Sys_Height", // SYSBONE_SCALED_HEIGHT + "Sys_Pitch_Arm01", // SYSBONE_SCALED_PITCH01 + "Sys_Pitch_Arm02", // SYSBONE_SCALED_PITCH02 + "Sys_Pitch_Arm03", // SYSBONE_SCALED_PITCH03 + "Sys_Pitch_Arm04", // SYSBONE_SCALED_PITCH04 + "Sys_Pitch_Arm05", // SYSBONE_SCALED_PITCH05 + "Sys_Pitch_Arm06", // SYSBONE_SCALED_PITCH06 +}; + +// invalids +const unsigned int INVALID_BONE_INDEX = 0xffffffff; +const unsigned int INVALID_TURRET_INDEX = 0xffffffff; + +// some very static timings, no need to confuse artists by exposing them +const float TRACKING_FADE_TIME = 1.f; + +EveChildTurret::EveChildTurret( IRoot* lockobj ) : + EveChildMesh( lockobj ) +// TODO: init rest of variables +{ + m_target.CreateInstance(); + + PrepareResources(); +} + +EveChildTurret::~EveChildTurret() +{ + if( m_firingEffect ) + { + m_firingEffect->CleanUp(); + } + + m_skeleton = nullptr; + m_skeletonBoneIndices.clear(); + m_boneBounds.clear(); + + ReleaseResources( TRISTORAGE_ALL ); +} +bool EveChildTurret::Initialize() +{ + // pass down some user-defined data into sub-modules we don't save out + // TODO: keep or discard + // m_target->SetBehaviour( m_laserMissBehaviour, m_projectileMissBehaviour, m_impactSize, m_impactBehaviour ); + + return EveChildMesh::Initialize(); +} +bool EveChildTurret::OnModified( Be::Var* value ) +{ + /* + if( IsMatch( value, m_laserMissBehaviour ) || IsMatch( value, m_projectileMissBehaviour ) || IsMatch( value, m_impactSize ) || IsMatch( value, m_impactBehaviour ) ) + { + // TODO: keep or discard + m_target->SetBehaviour( m_laserMissBehaviour, m_projectileMissBehaviour, m_impactSize, m_impactBehaviour ); + } + */ + return EveChildMesh::OnModified( value ); +} +void EveChildTurret::RegisterComponents() +{ + EveChildMesh::RegisterComponents(); + const auto registry = GetComponentRegistry(); + if( registry && m_display ) + { + if( EveEntityPtr entity = BlueCastPtr( m_firingEffect ) ) + { + entity->Register( registry ); + } + } +} +void EveChildTurret::UnRegisterComponents() +{ + EveChildMesh::UnRegisterComponents(); + const auto registry = this->GetComponentRegistry(); + if( registry ) + { + if( EveEntityPtr entity = BlueCastPtr( m_firingEffect ) ) + { + entity->UnRegister( registry ); + } + } +} +void EveChildTurret::GetDebugOptions( Tr2DebugRendererOptions& options ) +{ + EveChildMesh::GetDebugOptions( options ); + + if( m_firingEffect ) + { + m_firingEffect->GetDebugOptions( options ); + } + + if( m_turretMovementObserver ) + { + m_turretMovementObserver->GetDebugOptions( options ); + } +} +void EveChildTurret::RenderDebugInfo( ITr2DebugRenderer2& renderer ) +{ + EveChildMesh::RenderDebugInfo( renderer ); + + if( m_firingEffect ) + { + m_firingEffect->RenderDebugInfo( renderer ); + } + + if( m_turretMovementObserver && m_playMovementSound ) + { + m_turretMovementObserver->RenderDebugInfo( renderer ); + } +} + +void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) +{ + float deltaT = updateContext.GetDeltaT(); + + /* + // TODO: LODs needed? + // LODing + if( UpdateLOD( updateContext ) ) + { + // LOD change, so just call ::InitializeGeometryResource(), takes care of everything + InitializeGeometryResource(); + + // LOD change: toggle source dest effect of the attached firingFX + if( m_firingEffect ) + { + switch( m_lodLevel ) + { + case LOD_DISABLED: + case LOD_HIGHEST: + m_firingEffect->SetDisplaySourceObject( true ); + break; + default: + m_firingEffect->SetDisplaySourceObject( false ); + break; + } + } + } + */ + + if( m_sequencer ) + { + m_sequencer->RemoveFinishedAnimations( Tr2Renderer::GetAnimationTime() ); + } + + // setup and update attached firing effect + if( m_firingEffect ) + { + // if the attached firing effect is looping, then we must recheck if active turret is still the best, + if( m_firingEffect->IsLooping() ) + { + if( m_state == STATE_FIRING ) + { + // don't do it every frame, cause this will result in popping + m_recheckTimeLeft -= deltaT; + if( m_recheckTimeLeft < 0.f ) + { + Vector3 source = m_worldTransform.GetTranslation(); + Vector3 position = source; + if( int closestLocator = m_target->FindClosestLocator( &source, &position ) ) + { + if( closestLocator != m_target->GetLocator() ) + { + // Set up the firing states correctly + SetupFiringState(); + } + } + // recheck every 2 seconds + m_recheckTimeLeft = 2.f; + } + } + } + m_firingEffect->UpdateSynchronous( updateContext ); + } + + // update the target locator position + // TODO: probably wrong + Vector3 position = m_parentData.transform.GetTranslation(); + if( m_firingEffect ) + { + m_firingEffect->GetStartPosition( position ); + } + + m_target->Update( deltaT, &position ); + + if( m_mesh && m_turretMovementObserver != nullptr ) + { + // TODO: new turret movementObserver prob needed + // m_turretMovementObserver->Update( m_singleTurrets[0].worldMatrix ); + } + EveChildMesh::UpdateSyncronous( updateContext, params ); +} + +void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) +{ + + // TODO: prob some freakyness in here + float deltaT = updateContext.GetDeltaT(); + // handle fading of turret tracking + if( m_trackingInfluenceDelta != 0.f ) + { + m_trackingInfluence += m_trackingInfluenceDelta * deltaT; + if( m_trackingInfluence > m_maxTrackingTime ) + { + m_trackingInfluence = m_maxTrackingTime; + m_trackingInfluenceDelta = 0.f; + } + else if( m_trackingInfluence < 0.f ) + { + m_trackingInfluence = 0.f; + m_trackingInfluenceDelta = 0.f; + } + } + + if( m_delayToFadeOutTracking > 0.f ) + { + m_delayToFadeOutTracking -= deltaT; + if( m_delayToFadeOutTracking <= 0.f ) + { + m_delayToFadeOutTracking = 0.f; + m_trackingInfluenceDelta = -1.f / TRACKING_FADE_TIME; + } + } + + if( m_delayToFadeInTracking > 0.f ) + { + m_delayToFadeInTracking -= deltaT; + if( m_delayToFadeInTracking <= 0.f ) + { + m_delayToFadeInTracking = 0.f; + m_trackingInfluenceDelta = 1.f / TRACKING_FADE_TIME; + } + } + + // TODO: does this have to happen after the timing stuff over there ^ + // Should handle all the mesh data and transforms + EveChildMesh::UpdateAsyncronous( updateContext, params ); + + // setup and update attached firing effect + if( m_firingEffect ) + { + // TODO: is this a valid replacement of if( m_activeTurret != INVALID_TURRET_INDEX ) + if( m_mesh ) + { + // update all muzzle points in the firing effect + for( unsigned int i = 0; i < m_firingEffect->GetPerMuzzleEffectCount(); ++i ) + { + // get world transform of this muzzle bone + Matrix matrix = GetFiringBoneWorldTransform( i ); + // and set it to the muzzle + m_firingEffect->SetMuzzleTransform( i, &matrix ); + } + m_firingEffectMuzzlePosSet = true; + } + + m_firingEffect->SetEndPosition( m_target->GetTargetPosition() ); + + // time update (return value tells us if effect is ready to fire!) + if( m_firingEffect->UpdateAsynchronous( updateContext ) ) + { + // if we haven't initialised muzzle positions, do it now + // this can happen, and if we don't do this all effects originate from + // the player ship until turret geometry is loaded and muzzle positions + // properly set + if( !m_firingEffectMuzzlePosSet ) + { + for( unsigned int i = 0; i < m_firingEffect->GetPerMuzzleEffectCount(); ++i ) + { + // use something relatively sensible, even absent geometry + m_firingEffect->SetMuzzleTransform( i, &m_parentData.transform ); + } + + m_firingEffectMuzzlePosSet = true; + } + m_firingEffect->SetDisplayDestObject( m_target->ShowDestObject() ); + } + } +} + +void EveChildTurret::ReleaseCachedData( BlueAsyncRes* resource ) +{ + // TODO: for now duplicates destructor + m_skeleton = nullptr; + m_skeletonBoneIndices.clear(); + m_boneBounds.clear(); +} + +void EveChildTurret::RebuildCachedData( BlueAsyncRes* resource ) +{ + const auto geometryResource = m_mesh->GetGeometryResource(); + if( resource == geometryResource ) + { + // finished loading the turret geometry resource, so grab vertex decl and bounding sphere + if( geometryResource->GetMeshCount() ) + { + if( const TriGeometryResMeshData* meshData = geometryResource->GetMeshData( 0 ) ) + { + + // get a bounding box for visibility detection, if this is not already set in the redfile + // TODO: might not be needed + if( m_worldBoundingSphere.radius == 0.f ) + { + geometryResource->RecalculateBoundingSphere(); + Vector4 boundingSphere; + geometryResource->GetBoundingSphere( 0, boundingSphere ); + m_worldBoundingSphere = CcpMath::Sphere( boundingSphere ); + } + } + } + + if( geometryResource->GetSkeletonCount() ) + { + if( TriGeometryResSkeletonData* skeletonData = geometryResource->GetSkeletonData( 0 ) ) + { + for( int i = 0; i < SYSBONE_MAX; ++i ) + { + // in case we don't find system bone, ::FindJoint() returns 0xffffffff + m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i].c_str() ); + } + + InitializeFiringEffect(); + } + } + + InitializeAnimation(); + + if( !m_animationQueue.empty() ) + { + std::vector pending; + pending.swap( m_animationQueue ); + for( const auto& [animName, animNameIdle] : pending ) + { + PlayAnimation( animName, animNameIdle ); + } + } + else + { + // force an anim based on a state + ForceIdleAnimation(); + } + } +} + +void EveChildTurret::EnterStateDeactive() +{ + switch( m_state ) + { + case STATE_DEACTIVE: + // do nothing if we are already in this state + break; + case STATE_IDLE: + case STATE_RELOADING: + // no fadeout of tracking, just play deactive anim and then the deactive loop + m_trackingInfluence = 0.f; + PlayAnimation( "Pack", "Inactive" ); + m_delayToFadeOutTracking = 0.f; + break; + case STATE_FIRING: + // stop shooting + if( m_firingEffect ) + { + m_firingEffect->StopFiring(); + } + // DON'T break, just continue with stopping things: + case STATE_TARGETING: + // fadeout the tracking, play deactive anim and then the deactive loop + m_delayToFadeOutTracking = 0.0001f; + m_target->StopFireAtLocator(); + + PlayAnimation( "Pack", "Inactive", TRACKING_FADE_TIME ); + break; + + default: + break; + } + m_state = STATE_DEACTIVE; +} + +void EveChildTurret::EnterStateIdle() +{ + // TODO: might want to remove this state + // if( !m_isOnline ) + // { + // return; + // } + + switch( m_state ) + { + case STATE_INVALID: + case STATE_RELOADING: + // just play active loop + PlayAnimation( "", "Active" ); + break; + case STATE_DEACTIVE: + // start unpack animation, disable tracking and then into active loop + PlayAnimation( "Deploy", "Active" ); + m_trackingInfluence = 0.f; + break; + case STATE_IDLE: + // do nothing here + break; + case STATE_TARGETING: + case STATE_FIRING: + // stop shooting, fadeout tracking, then into active loop + m_delayToFadeOutTracking = 0.0001f; + m_target->StopFireAtLocator(); + if( m_firingEffect ) + { + m_firingEffect->StopFiring(); + } + PlayAnimation( "", "Active", TRACKING_FADE_TIME ); + + if( m_playMovementSound && !m_targetingToIdleMovementAudioEvent.empty() ) + { + SendEventToAudEmitter( m_turretMovementObserver, m_targetingToIdleMovementAudioEvent ); + } + break; + } + m_state = STATE_IDLE; +} + +void EveChildTurret::EnterStateTargeting() +{ + float animLength = 0.f; + // TODO: might want to remove this state + // if( !m_isOnline ) + // { + // return; + // } + + // what state are we in? + switch( m_state ) + { + case STATE_DEACTIVE: + // play deploy anim, then active loop and fade in tracking + animLength = PlayAnimation( "Deploy", "Active", TRACKING_FADE_TIME ); + // fade in tracking + m_delayToFadeInTracking = animLength + 0.0001f; + break; + case STATE_IDLE: + case STATE_RELOADING: + // fadein tracking, play active loop + m_delayToFadeInTracking = 0.0001f; + PlayAnimation( "", "Active", TRACKING_FADE_TIME ); + break; + case STATE_TARGETING: + break; + case STATE_FIRING: + // stop shooting, then into active loop + m_target->StopFireAtLocator(); + if( m_firingEffect ) + { + m_firingEffect->StopFiring(); + } + PlayAnimation( "", "Active", 0.f ); + break; + + default: + break; + } + m_state = STATE_TARGETING; +} + +void EveChildTurret::EnterStateFiring() +{ + if( !SetupFiringState() ) + { + return; + } + + // only if we are in firing mode, call ::StopFiring() on the effect right before + // we call ::PrepareFiring(), it'll clean things up in the effect + if( m_firingEffect && m_state == STATE_FIRING ) + { + if( m_firingEffect->IsLooping() ) + { + // We don't want to start and stop the curves when the turret is looping and firing + m_firingEffect->PrepareFiringEffectMoveObjects(); + return; + } + m_firingEffect->StopFiring(); + } + + // We're starting a firing sequence, we need to set up our firing effect time-delays + if( m_firingEffect ) + { + // TODO: random firing delay yay or nay + //if( m_maxCyclingFirePos > 1 ) + //{ + // m_firingEffect->PrepareFiring( m_randomFiringDelay, m_currentCyclingFiresPos, m_cyclingFireGroupCount ); + //} + //else + //{ + float randomFiringDelay = 0.f; + m_firingEffect->PrepareFiring( randomFiringDelay ); + //} + + if( m_target != nullptr ) + { + m_firingEffect->SetImpactConfiguration( m_target->GetImpactConfiguration() ); + } + } + + // finally, we can set state + m_state = STATE_FIRING; +} + +bool EveChildTurret::SetupFiringState() +{ + if( m_state == STATE_DEACTIVE ) + { + // this state change is forbidden! + CCP_LOGERR( "EveTurretSet %s wants to fire but is in deactive state.", m_name.c_str() ); + return false; + } + int closestLocator = -1; + { + Vector3 source = m_worldTransform.GetTranslation(); + Vector3 position = source; + closestLocator = m_target->FindClosestLocator( &source, &position ); + } + + // TODO: remove or keep? + // if this turret is set to cycle through the muzzles for firing, do it here + /* + if( m_maxCyclingFirePos > 1 ) + { + m_currentCyclingFiresPos += m_cyclingFireGroupCount; + if( m_currentCyclingFiresPos >= m_maxCyclingFirePos * m_cyclingFireGroupCount ) + { + m_currentCyclingFiresPos = 0; + } + } + */ + + // timing: apply a randomized fire delay + // TODO: remove? + // CalcRandomDelay(); + float m_randomFiringDelay = 0.f; // TODO: temp value + + // timing: is the length of the firing effect known? + float effectTotalTime = m_firingEffect ? m_firingEffect->GetFiringDuration() : 0.f; + float effectPeakTime = m_firingEffect ? m_firingEffect->GetFiringPeakTime() : 0.f; + + Vector3 source = m_parentData.transform.GetTranslation(); + + // what state are we in? + switch( m_state ) + { + case STATE_IDLE: + case STATE_RELOADING: + // and delay the effect until we are facing target + m_randomFiringDelay += m_maxTrackingTime; + // fadein tracking, play fire anim (only one the firing turret!) and then the active anim + m_delayToFadeInTracking = 0.0001f; + + PlayAnimation( GetFireAnimationName(), "Active", m_randomFiringDelay ); + // assign locator and turret + m_target->StartFireAtLocator( closestLocator, m_randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + break; + case STATE_FIRING: + case STATE_TARGETING: + PlayAnimation( GetFireAnimationName(), "Active", m_randomFiringDelay ); + m_target->StartFireAtLocator( closestLocator, m_randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + break; + + default: + break; + } + + return true; +} + +void EveChildTurret::EnterStateReloading() +{ + // what state are we in? + switch( m_state ) + { + case STATE_DEACTIVE: + // ignore this state change: when the turret is inactive, no reload state can be shown! + break; + case STATE_INVALID: + case STATE_IDLE: + case STATE_RELOADING: + // just play reloading anim and then loop + PlayAnimation( "Reload", "Active", 0.f ); + break; + case STATE_TARGETING: + case STATE_FIRING: + // stop shooting, fadeout tracking, then into active loop + m_delayToFadeOutTracking = 0.0001f; + m_target->StopFireAtLocator(); + if( m_firingEffect ) + { + m_firingEffect->StopFiring(); + } + + PlayAnimation( "Reload", "Active", TRACKING_FADE_TIME ); + break; + + default: + break; + } + m_state = STATE_RELOADING; +} + +void EveChildTurret::ForceStateDeactive() +{ + // turn it all off + m_trackingInfluence = 0.f; + m_delayToFadeOutTracking = 0.f; + m_target->StopFireAtLocator(); + if( m_firingEffect ) + { + m_firingEffect->StopFiring(); + } + // finally, we can set state + m_state = STATE_DEACTIVE; + + // now force-play the deactive anim for this state + ForceIdleAnimation(); +} + +void EveChildTurret::ForceIdleAnimation() +{ + std::string idleAnimName = ""; + // what state? + switch( m_state ) + { + case STATE_DEACTIVE: + idleAnimName = "Inactive"; + break; + case STATE_IDLE: + case STATE_TARGETING: + case STATE_FIRING: + idleAnimName = "Active"; + break; + + default: + break; + } + + // set it to all turrets in this set + if( idleAnimName.length() > 0 ) + { + PlayAnimation( "", idleAnimName, 0.f ); + } +} + +void EveChildTurret::ForceStateTargeting() +{ + m_trackingInfluence = m_maxTrackingTime; + m_trackingInfluenceDelta = 0.f; + + m_state = STATE_TARGETING; + + // now force-play the deactive anim for this state + PlayAnimation( "", "Active", 0.f ); +} + +Matrix EveChildTurret::GetFiringBoneWorldTransform( unsigned int muzzle ) const +{ + if( !m_mesh ) + { + return m_parentData.transform; + } + + Matrix matrix = m_worldTransform; + + // get the boneID for that muzzle from firing effect + if( !m_firingEffect ) + { + return matrix; + } + unsigned int boneID = m_firingEffect->GetPerMuzzleBoneID( muzzle ); + return GetTurretBoneTransform( boneID ); +} + +void EveChildTurret::InitializeFiringEffect() +{ + if( !m_firingEffect ) + { + return; + } + m_firingEffect->RegisterWithQuadRenderer( *Tr2QuadRenderer::Instance() ); + + auto geometryResource = m_mesh->GetGeometryResource(); + if( geometryResource && geometryResource->GetSkeletonCount() ) + { + if( TriGeometryResSkeletonData* skeletonData = geometryResource->GetSkeletonData( 0 ) ) + { + const auto muzzleCount = m_firingEffect->GetPerMuzzleEffectCount(); + if( muzzleCount > EveTurretFiringFX::MUZZLECOUNT_MAX ) + { + CCP_LOGERR( "Upper limit of firing bones is %d, this turret has %d", EveTurretFiringFX::MUZZLECOUNT_MAX, muzzleCount ); + } + + const unsigned int boneCount = std::min( muzzleCount, static_cast( EveTurretFiringFX::MUZZLECOUNT_MAX ) ); + // firing bones should always be on the format Pos_FireXX where XX can range form 01 to 99 + for( unsigned int i = 0; i < boneCount; ++i ) + { + char boneName[32]; + int boneNameIndex = i + 1; + snprintf( boneName, sizeof boneName, "%s%02u", m_firingEffect->GetFiringBoneName(), boneNameIndex ); + + // in case we don't find positional bone, ::FindJoint() returns 0xffffffff + m_firingEffect->SetMuzzleBoneID( i, skeletonData->FindJoint( boneName ) ); + } + } + } +} + +void EveChildTurret::InitializeAnimation() +{ + EveChildMesh::InitializeAnimation(); + if( const auto geometryResource = m_mesh->GetGeometryResource() ) + { + // get a model, a meshbinding and animation stuff from the resource + const cmf::Data* cmfData = geometryResource->GetCMFData(); + if( cmfData && cmfData->skeletons.size() ) + { + const auto mesh = std::find_if( cmfData->meshes.begin(), cmfData->meshes.end(), []( const cmf::Mesh& m ) { + return m.skeleton == 0; + } ); + + if( mesh != cmfData->meshes.end() && mesh->boneBindings.size() ) + { + if( m_skeletonBoneIndices.empty() ) + { + m_skeleton = &cmfData->skeletons[0]; + + + if( !m_sequencer ) + { + m_sequencer = std::make_unique( *m_skeleton ); + cmf::RestPose( m_pose, *m_skeleton ); + } + + m_skeletonBoneIndices = Tr2GrannyAnimationUtils::CreateMapping( *m_skeleton, mesh->boneBindings, static_cast( mesh->boneBindings.size() ) ); + } + } + } + } +} + +void EveChildTurret::ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const +{ + switch( bone ) + { + case SYSBONE_INVALID: + break; + case SYSBONE_ROTATION: + case SYSBONE_ROTATION01: + case SYSBONE_ROTATION02: { + // rotation of turret 360 degrees, alpha is between -pi and pi + float alpha = atan2( target->x, target->z ); + // never forget do apply influence! + alpha *= m_trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + // TODO: cmf_transform ? + // 3rd: make granny_transform from quat + rotation = quat; + } + break; + case SYSBONE_COUNTER_ROTATION: { + // inverse(!!) rotation of turret 360 degress, alpha is between -pi and pi + float alpha = -atan2( target->x, target->z ); + // never forget do apply influence! + alpha *= m_trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + // 3rd: make granny_transform from quat + rotation = quat; + } + break; + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: { + CalcTransformForPitchBone( target, XMConvertToRadians( m_sysBonePitchMin ), XMConvertToRadians( m_sysBonePitchMax ), bone, localTransform, rotation ); + } + break; + case SYSBONE_SCALED_HEIGHT: { + // pitch of barrel 90 degrees + Vector3 directionNormal = Normalize( *target ); + float height = TriClamp( directionNormal.y, 0.f, 1.f ); + // never forget do apply influence! + height *= m_trackingInfluence; + // it's a pos extension with a scale + Vector3 pos = Vector3( 0.f, height * m_sysBoneHeight, 0.f ) + position; + position = pos; + } + break; + case SYSBONE_SCALED_PITCH01: + case SYSBONE_SCALED_PITCH02: + case SYSBONE_SCALED_PITCH03: + case SYSBONE_SCALED_PITCH04: + case SYSBONE_SCALED_PITCH05: + case SYSBONE_SCALED_PITCH06: { + CalcTransformForPitchBone( target, 0.f, XMConvertToRadians( m_sysBonePitchMax ), bone, nullptr, rotation ); + } + break; + default: + break; + } +} + +void EveChildTurret::CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const +{ + float pitchOffset = GetBonePitchOffset( boneIndex ); + float pitchFactor = GetBonePitchFactor( boneIndex ); + // pitch of barrel 90 degrees + Vector3 bone_position( 0.f, 0.f, 0.f ); + + if( localTransform ) + { + bone_position = localTransform->GetTranslation(); + } + + Vector3 relTarget = *target - bone_position; + Vector3 dirNrm = Normalize( relTarget ); + float radians = asinf( dirNrm.y ); + + if( localTransform ) + { + Vector3 bone_direction = Normalize( bone_position ); + float d = Dot( bone_direction, *target ); + if( d < Length( bone_position ) ) + { + // Assuming up is enough for now to avoid cross products + radians = TriFloatSign( relTarget.y ) * XM_PI - radians; + } + } + + float alpha = TriClamp( radians, minPitch, maxPitch ); + // modify! + alpha = pitchFactor * alpha + XMConvertToRadians( pitchOffset ); + // never forget do apply influence! + alpha *= m_trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( 0.f, -alpha, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + // 2nd: make granny_transform from quat + rotation = quat; +} + +float EveChildTurret::GetBonePitchFactor( unsigned int boneIndex ) const +{ + switch( boneIndex ) + { + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: + return m_sysBonePitchFactor; + case SYSBONE_SCALED_PITCH01: + return m_sysBonePitch01Factor; + case SYSBONE_SCALED_PITCH02: + return m_sysBonePitch02Factor; + case SYSBONE_SCALED_PITCH03: + return m_sysBonePitch03Factor; + default: + return 1.0f; + } +} + +float EveChildTurret::GetBonePitchOffset( unsigned int boneIndex ) const +{ + switch( boneIndex ) + { + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: + return m_sysBonePitchOffset; + case SYSBONE_SCALED_PITCH01: + return m_sysBonePitch01Offset; + case SYSBONE_SCALED_PITCH02: + return m_sysBonePitch02Offset; + case SYSBONE_SCALED_PITCH03: + return m_sysBonePitch03Offset; + default: + return 0.0f; + } +} +Matrix EveChildTurret::GetTurretBoneTransform( uint32_t boneID ) const +{ + Matrix matrix = m_worldTransform; + + if( boneID == INVALID_BONE_INDEX ) + { + // TODO: should support lowLodTransform? prob yes + // return lowLodTransform * matrix; + return matrix; + } + if( m_animationUpdater ) + { + const auto& worldTransforms = m_animationUpdater->GetWorldTransforms(); + if( !worldTransforms.empty() ) + { + return worldTransforms[boneID] * matrix; + } + } + // TODO: port rest of function? + return matrix; +} + +float EveChildTurret::PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay ) +{ + if( !m_animationUpdater ) + { + return 0.f; + } + float animLength = 0.f; + + auto cmfData = m_mesh->GetGeometryResource()->GetCMFData(); + if( cmfData ) + { + // there can be more animations in one res, so find right one + size_t animIx = cmfData->animations.size(); + if( !animName.empty() ) + { + auto animation = std::find_if( cmfData->animations.begin(), cmfData->animations.end(), [&animName]( const cmf::Animation& anim ) { + return cmf::ToStdStringView( anim.name ) == animName; + } ); + if( animation == cmfData->animations.end() ) + { + return 0.f; + } + animIx = std::distance( cmfData->animations.begin(), animation ); + } + + size_t idleIx = cmfData->animations.size(); + if( !animNameIdle.empty() ) + { + auto animation = std::find_if( cmfData->animations.begin(), cmfData->animations.end(), [&animNameIdle]( const cmf::Animation& anim ) { + return cmf::ToStdStringView( anim.name ) == animNameIdle; + } ); + if( animation == cmfData->animations.end() ) + { + return 0.f; + } + idleIx = std::distance( cmfData->animations.begin(), animation ); + } + + // stop all animation + StopAnimation( delay ); + + if( m_animationUpdater ) + { + // granny, play first anim once, if provided & found + if( animIx != cmfData->animations.size() ) + { + auto& animation = cmfData->animations[animIx]; + animLength = animation.duration; + + // ( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ) + std::string animationName = cmf::ToStdString( animation.name ); + bool replace = false; // TODO: correct? + int loopCount = 1; + float speed = 1.f; + m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); + // TODO: set start/stop time seems different from ^ + // player->SetStartTime( delay + Tr2Renderer::GetAnimationTime() ); + // player->SetStopTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); + } + + // then play idle anim on loop (after delay), if provided & found + if( idleIx != cmfData->animations.size() ) + { + auto& animation = cmfData->animations[idleIx]; + std::string animationName = cmf::ToStdString( animation.name ); + bool replace = false; // TODO: correct? + int loopCount = 0; + float speed = 1.f; + + m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); + // TODO: set start time seems different from ^ + // player->SetStartTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); + } + } + } + + return animLength; +} + +void EveChildTurret::StopAnimation( float delay ) +{ + // TODO: prob not needed and can just use animation class function instead of this probably useless middleman + auto geometryResource = m_mesh->GetGeometryResource(); + // if we don't have a geometry, animation is useless and probably unwanted + if( !geometryResource ) + { + return; + } + + // empty queue, so no more buffered requests + m_animationQueue.clear(); + + // stop + if( m_animationUpdater ) + { + /* + // TODO: find correct functions + m_animationUpdater->EnumerateAnimations( [&]( const std::shared_ptr& player ) { + player->SetStopTime( delay + Tr2Renderer::GetAnimationTime() ); + } ); + + m_animationUpdater->RemoveFinishedAnimations( Tr2Renderer::GetAnimationTime() ); + */ + } +} + +std::string EveChildTurret::GetFireAnimationName() const +{ + /* + // TODO: idk if this is useful skipping for now + // if m_currentCyclingFiresPos is 0, it's just "Fire" + std::string res = "Fire"; + if( m_currentCyclingFiresPos > 0 ) + { + res.push_back( '0' ); + res.push_back( '0' + m_currentCyclingFiresPos / m_cyclingFireGroupCount ); + } + + return res; + */ + return ""; +} + +EveTurretFiringFXPtr EveChildTurret::GetFiringEffect() +{ + return m_firingEffect; +} + +void EveChildTurret::SetFiringEffect( const EveTurretFiringFXPtr& firingEffect ) +{ + auto registry = GetComponentRegistry(); + if( EveEntityPtr entity = BlueCastPtr( m_firingEffect ) ) + { + entity->UnRegister( registry ); + } + m_firingEffect = firingEffect; + if( EveEntityPtr entity = BlueCastPtr( m_firingEffect ) ) + { + entity->Register( registry ); + } + InitializeFiringEffect(); +} + +void EveChildTurret::SetTargetObject( IRoot* target ) +{ + if( !target ) + { + return; + } + ITriTargetablePtr oldTargetPtr = m_target->GetTargetable(); + + // attach to target + m_target->SetTargetable( target ); + + if( m_playMovementSound && !m_idleToTargetingMovementAudioEvent.empty() ) + { + // Always trigger movement sounds if coming from IDLE state, otherwise trigger it only if you're targeting a new object. + if( m_state == STATE_IDLE || !oldTargetPtr.IsEqualObject( m_target->GetTargetable() ) ) + { + SendEventToAudEmitter( m_turretMovementObserver, m_idleToTargetingMovementAudioEvent ); + } + } + + // update the firing effect we have one + SetTargetScale(); +} + +ITriTargetablePtr EveChildTurret::GetTargetObject() +{ + return m_target->GetTargetable(); +} + +void EveChildTurret::SetTargetScale() +{ + if( m_firingEffect ) + { + float radius = m_target->GetRadius(); + m_firingEffect->SetScaleByRadius( radius ); + } +} diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h new file mode 100644 index 000000000..d1520a4e1 --- /dev/null +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -0,0 +1,194 @@ +// Copyright © 2026 Fenris Creations ehf. + +#pragma once +#ifndef EveChildTurret_H +#define EveChildTurret_H + +#include "EveChildMesh.h" +#include "Eve/Turret/EveTurretTarget.h" + +BLUE_DECLARE( EveTurretFiringFX ); +BLUE_DECLARE( EveTurretTarget ); +BLUE_DECLARE( EveTurretTarget ); +BLUE_DECLARE( EveChildInstanceContainer ); + +BLUE_CLASS( EveChildTurret ) : public EveChildMesh, public IBlueAsyncResNotifyTarget +{ +public: + EXPOSE_TO_BLUE(); + + EveChildTurret( IRoot* lockobj = nullptr ); + ~EveChildTurret(); + + bool Initialize() override; + bool OnModified( Be::Var * value ) override; + void RegisterComponents() override; + void UnRegisterComponents() override; + + void GetDebugOptions( Tr2DebugRendererOptions & options ) override; + void RenderDebugInfo( ITr2DebugRenderer2 & renderer ) override; + + // EveSpaceObjectChild + void UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; + void UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; + + // IBlueAsyncResNotifyTarget + void ReleaseCachedData( BlueAsyncRes * resource ) override; + void RebuildCachedData( BlueAsyncRes * resource ) override; + + // action + void EnterStateDeactive(); + void EnterStateIdle(); + void EnterStateTargeting(); + void EnterStateFiring(); + bool SetupFiringState(); + void EnterStateReloading(); + + void ForceStateDeactive(); + void ForceIdleAnimation(); + void ForceStateTargeting(); + + Matrix GetFiringBoneWorldTransform( unsigned int muzzle ) const; + + // turret set states + enum State + { + STATE_INVALID = 0, + STATE_DEACTIVE, + STATE_IDLE, + STATE_TARGETING, + STATE_FIRING, + STATE_RELOADING, + }; + +protected: + // system-controlled bones + // TODO: needed? + enum SystemBones + { + SYSBONE_INVALID = 0, + SYSBONE_ROTATION, + SYSBONE_ROTATION01, + SYSBONE_ROTATION02, + SYSBONE_COUNTER_ROTATION, + SYSBONE_PITCH, + SYSBONE_PITCH1, + SYSBONE_PITCH2, + SYSBONE_SCALED_HEIGHT, + SYSBONE_SCALED_PITCH01, + SYSBONE_SCALED_PITCH02, + SYSBONE_SCALED_PITCH03, + SYSBONE_SCALED_PITCH04, + SYSBONE_SCALED_PITCH05, + SYSBONE_SCALED_PITCH06, + SYSBONE_MAX, + }; + + // setup the attached firing effect + void InitializeFiringEffect(); + + void InitializeAnimation() override; + + // TODO: Need update LOD ? + + // set transform for tracking + void ModifySystemBoneTransform( + SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) + const; + + // Calculates the pitch for a bone based on the parameters + void CalcTransformForPitchBone( const Vector3* target, + float minPitch, + float maxPitch, + unsigned int boneIndex, + const Matrix* localTransform, + Quaternion& rotation ) const; + + // Returns the correct pitch factor for a specific bone index + float GetBonePitchFactor( unsigned int boneIndex ) const; + // Returns the correct pitch offset for a specific bone index + float GetBonePitchOffset( unsigned int boneIndex ) const; + + Matrix GetTurretBoneTransform( uint32_t boneID ) const; + + // animation + float PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay = 0.f ); + void StopAnimation( float delay = 0.f ); + std::string GetFireAnimationName() const; + + EveTurretFiringFXPtr GetFiringEffect(); + void SetFiringEffect( const EveTurretFiringFXPtr& firingEffect ); + + // TODO: rename GrannyBoneBindingBounds? + std::vector m_boneBounds; + + // Assign the target object + void SetTargetObject( IRoot * target ); + ITriTargetablePtr GetTargetObject(); + void SetTargetScale(); + + // target (object we are tracking) + EveTurretTargetPtr m_target; + + // impacts + float m_impactSize; + ImpactBehaviour::Type m_impactBehaviour; + + // tracking + float m_trackingInfluence; + float m_trackingInfluenceDelta; + float m_delayToFadeOutTracking; + float m_delayToFadeInTracking; + float m_maxTrackingTime; + + // animation + // TODO: needed? + struct AnimationRequest + { + std::string animName; + std::string animNameIdle; + }; + std::vector m_animationQueue; + const cmf::Skeleton* m_skeleton; + std::vector m_skeletonBoneIndices; + std::unique_ptr m_sequencer; + cmf::SkeletonPose m_pose; + + // system bones + unsigned int m_systemBoneID[SYSBONE_MAX]; + // specific system bone values + float m_sysBoneHeight; + float m_sysBonePitchOffset; + float m_sysBonePitchFactor; + float m_sysBonePitchMin; + float m_sysBonePitchMax; + float m_sysBonePitch01Offset; + float m_sysBonePitch01Factor; + float m_sysBonePitch02Offset; + float m_sysBonePitch02Factor; + float m_sysBonePitch03Offset; + float m_sysBonePitch03Factor; + + // state of turret set + State m_state; + + float m_recheckTimeLeft; + + // firing effect redfile path + std::string m_firingEffectResPath; + + // TODO: move firing effect into its own class? + // firing effect + EveTurretFiringFXPtr m_firingEffect; + bool m_firingEffectMuzzlePosSet; + + // Audio specific attributes + bool m_playMovementSound; + TriObserverLocalPtr m_turretMovementObserver; + std::wstring m_idleToTargetingMovementAudioEvent; + std::wstring m_targetingToIdleMovementAudioEvent; +}; + +TYPEDEF_BLUECLASS( EveChildTurret ); + +#endif diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp new file mode 100644 index 000000000..c05c72697 --- /dev/null +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -0,0 +1,13 @@ +// Copyright © 2026 Fenris Creations ehf. + +#include "StdAfx.h" +#include "EveChildTurret.h" + +BLUE_DEFINE( EveChildTurret ); + +const Be::ClassInfo* EveChildTurret::ExposeToBlue() +{ + EXPOSURE_BEGIN( EveChildTurret, "" ) + MAP_INTERFACE( EveChildTurret ) + EXPOSURE_CHAINTO( EveChildMesh ) +} diff --git a/trinity/Eve/Turret/EveTurretSet.cpp b/trinity/Eve/Turret/EveTurretSet.cpp index 87efc0812..151c7f0ff 100644 --- a/trinity/Eve/Turret/EveTurretSet.cpp +++ b/trinity/Eve/Turret/EveTurretSet.cpp @@ -67,9 +67,9 @@ bool IsUsingCMF( TriGeometryRes* geometryResource ) // -------------------------------------------------------------------------------- // Description: -// Initialize data members, set everything to inlavid/empty and call -// ::PrepareResouce(), which will create a vertex decleration and a -// special istance buffer for the instance rendering. Also load the +// Initialize data members, set everything to invalid/empty and call +// ::PrepareResource(), which will create a vertex declaration and a +// special instance buffer for the instance rendering. Also load the // shader for shadow generation // -------------------------------------------------------------------------------- EveTurretSet::EveTurretSet( IRoot* lockobj ) : @@ -1419,7 +1419,7 @@ void EveTurretSet::UpdateSingleTurrets() // First thing to do is to keep the world-matrices of all turrets up to date, // cause most likely the ship has moved. Then sample the granny animation // for each single turret of this set, cause they are animated independently. -// Just before collapsing the skeleton matrices, sneek in a bone modification +// Just before collapsing the skeleton matrices, sneak in a bone modification // for the auto tracking. // Also smoothly do some fading between states and tracking positions. // SeeAlso: @@ -1564,7 +1564,7 @@ void EveTurretSet::UpdateTurretTransforms( const Matrix* turretTransformMatrix ) // -------------------------------------------------------------------------------- Matrix EveTurretSet::GetFiringBoneWorldTransform( unsigned int muzzle ) const { - // there MUST be an avtive turret aka a "firing turret"! + // there MUST be an active turret aka a "firing turret"! unsigned int closestTurret = m_activeTurret; // so if we don't have one, calc one temporarily if( closestTurret == INVALID_TURRET_INDEX ) @@ -1735,7 +1735,7 @@ void EveTurretSet::ModifySystemBoneTransform( SystemBones bone, const Vector3* t case SYSBONE_ROTATION: case SYSBONE_ROTATION01: case SYSBONE_ROTATION02: { - // rotation of turret 360 degress, alpha is between -pi and pi + // rotation of turret 360 degrees, alpha is between -pi and pi float alpha = atan2( target->x, target->z ); // never forget do apply influence! alpha *= m_trackingInfluence; @@ -2918,7 +2918,7 @@ void EveTurretSet::EnterStateIdle() break; case STATE_TARGETING: case STATE_FIRING: - // stop shooting, fadout tracking, then into active loop + // stop shooting, fadeout tracking, then into active loop m_delayToFadeOutTracking = 0.0001f; m_activeTurret = INVALID_TURRET_INDEX; m_target->StopFireAtLocator(); @@ -3178,7 +3178,7 @@ void EveTurretSet::EnterStateReloading() switch( m_state ) { case STATE_DEACTIVE: - // ingnore this state change: when the turret is inactive, no reload state can be shown! + // ignore this state change: when the turret is inactive, no reload state can be shown! break; case STATE_INVALID: case STATE_IDLE: @@ -3191,7 +3191,7 @@ void EveTurretSet::EnterStateReloading() break; case STATE_TARGETING: case STATE_FIRING: - // stop shooting, fadout tracking, then into active loop + // stop shooting, fadeout tracking, then into active loop m_delayToFadeOutTracking = 0.0001f; m_activeTurret = INVALID_TURRET_INDEX; m_target->StopFireAtLocator(); From 3565268d60052be7cd98f5eef967763af3a12f78 Mon Sep 17 00:00:00 2001 From: breki Date: Fri, 24 Jul 2026 16:24:27 +0000 Subject: [PATCH 02/23] fix formatting --- trinity/Eve/SpaceObject/Children/EveChildTurret.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index d1520a4e1..db4a64380 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -12,7 +12,8 @@ BLUE_DECLARE( EveTurretTarget ); BLUE_DECLARE( EveTurretTarget ); BLUE_DECLARE( EveChildInstanceContainer ); -BLUE_CLASS( EveChildTurret ) : public EveChildMesh, public IBlueAsyncResNotifyTarget +BLUE_CLASS( EveChildTurret ) : + public EveChildMesh, public IBlueAsyncResNotifyTarget { public: EXPOSE_TO_BLUE(); @@ -92,17 +93,10 @@ BLUE_CLASS( EveChildTurret ) : public EveChildMesh, public IBlueAsyncResNotifyTa // TODO: Need update LOD ? // set transform for tracking - void ModifySystemBoneTransform( - SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) - const; + void ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const; // Calculates the pitch for a bone based on the parameters - void CalcTransformForPitchBone( const Vector3* target, - float minPitch, - float maxPitch, - unsigned int boneIndex, - const Matrix* localTransform, - Quaternion& rotation ) const; + void CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const; // Returns the correct pitch factor for a specific bone index float GetBonePitchFactor( unsigned int boneIndex ) const; From add33a3828fc9e2eaf2f26c6e818dc8d5fddc005 Mon Sep 17 00:00:00 2001 From: breki Date: Mon, 27 Jul 2026 14:16:18 +0000 Subject: [PATCH 03/23] initalize turret variable and setup _blue file and fix compile error --- .../SpaceObject/Children/EveChildTurret.cpp | 10 ++- .../Eve/SpaceObject/Children/EveChildTurret.h | 52 ++++++------- .../Children/EveChildTurret_Blue.cpp | 76 +++++++++++++++++++ 3 files changed, 108 insertions(+), 30 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 004ed80c5..22fcde315 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -35,8 +35,12 @@ const float TRACKING_FADE_TIME = 1.f; EveChildTurret::EveChildTurret( IRoot* lockobj ) : EveChildMesh( lockobj ) -// TODO: init rest of variables { + for( unsigned int i = 0; i < SYSBONE_MAX; ++i ) + { + m_systemBoneID[i] = INVALID_BONE_INDEX; + } + m_target.CreateInstance(); PrepareResources(); @@ -1049,12 +1053,12 @@ std::string EveChildTurret::GetFireAnimationName() const return ""; } -EveTurretFiringFXPtr EveChildTurret::GetFiringEffect() +EveTurretFiringFX* EveChildTurret::GetFiringEffect() { return m_firingEffect; } -void EveChildTurret::SetFiringEffect( const EveTurretFiringFXPtr& firingEffect ) +void EveChildTurret::SetFiringEffect( EveTurretFiringFX* firingEffect ) { auto registry = GetComponentRegistry(); if( EveEntityPtr entity = BlueCastPtr( m_firingEffect ) ) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index db4a64380..cc85f8ec2 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -9,8 +9,6 @@ BLUE_DECLARE( EveTurretFiringFX ); BLUE_DECLARE( EveTurretTarget ); -BLUE_DECLARE( EveTurretTarget ); -BLUE_DECLARE( EveChildInstanceContainer ); BLUE_CLASS( EveChildTurret ) : public EveChildMesh, public IBlueAsyncResNotifyTarget @@ -110,8 +108,8 @@ BLUE_CLASS( EveChildTurret ) : void StopAnimation( float delay = 0.f ); std::string GetFireAnimationName() const; - EveTurretFiringFXPtr GetFiringEffect(); - void SetFiringEffect( const EveTurretFiringFXPtr& firingEffect ); + EveTurretFiringFX* GetFiringEffect(); + void SetFiringEffect( EveTurretFiringFX* firingEffect ); // TODO: rename GrannyBoneBindingBounds? std::vector m_boneBounds; @@ -125,15 +123,15 @@ BLUE_CLASS( EveChildTurret ) : EveTurretTargetPtr m_target; // impacts - float m_impactSize; - ImpactBehaviour::Type m_impactBehaviour; + float m_impactSize = 0.f; + ImpactBehaviour::Type m_impactBehaviour = ImpactBehaviour::DAMAGE_LOCATOR; // tracking - float m_trackingInfluence; - float m_trackingInfluenceDelta; - float m_delayToFadeOutTracking; - float m_delayToFadeInTracking; - float m_maxTrackingTime; + float m_trackingInfluence = 0.f; + float m_trackingInfluenceDelta = 0.f; + float m_delayToFadeOutTracking = 0.f; + float m_delayToFadeInTracking = 0.f; + float m_maxTrackingTime = 1.f; // animation // TODO: needed? @@ -143,7 +141,7 @@ BLUE_CLASS( EveChildTurret ) : std::string animNameIdle; }; std::vector m_animationQueue; - const cmf::Skeleton* m_skeleton; + const cmf::Skeleton* m_skeleton = nullptr; std::vector m_skeletonBoneIndices; std::unique_ptr m_sequencer; cmf::SkeletonPose m_pose; @@ -151,22 +149,22 @@ BLUE_CLASS( EveChildTurret ) : // system bones unsigned int m_systemBoneID[SYSBONE_MAX]; // specific system bone values - float m_sysBoneHeight; - float m_sysBonePitchOffset; - float m_sysBonePitchFactor; - float m_sysBonePitchMin; - float m_sysBonePitchMax; - float m_sysBonePitch01Offset; - float m_sysBonePitch01Factor; - float m_sysBonePitch02Offset; - float m_sysBonePitch02Factor; - float m_sysBonePitch03Offset; - float m_sysBonePitch03Factor; + float m_sysBoneHeight = 1.f; + float m_sysBonePitchOffset = 0.f; + float m_sysBonePitchFactor = 1.f; + float m_sysBonePitchMin = 0.f; + float m_sysBonePitchMax = 90.f; + float m_sysBonePitch01Offset = 0.f; + float m_sysBonePitch01Factor = 1.f; + float m_sysBonePitch02Offset = 0.f; + float m_sysBonePitch02Factor = 1.f; + float m_sysBonePitch03Offset = 0.f; + float m_sysBonePitch03Factor = 1.f; // state of turret set - State m_state; + State m_state = STATE_IDLE; - float m_recheckTimeLeft; + float m_recheckTimeLeft = -1.f; // firing effect redfile path std::string m_firingEffectResPath; @@ -174,10 +172,10 @@ BLUE_CLASS( EveChildTurret ) : // TODO: move firing effect into its own class? // firing effect EveTurretFiringFXPtr m_firingEffect; - bool m_firingEffectMuzzlePosSet; + bool m_firingEffectMuzzlePosSet = false; // Audio specific attributes - bool m_playMovementSound; + bool m_playMovementSound = true; TriObserverLocalPtr m_turretMovementObserver; std::wstring m_idleToTargetingMovementAudioEvent; std::wstring m_targetingToIdleMovementAudioEvent; diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index c05c72697..3b3bb0251 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -2,12 +2,88 @@ #include "StdAfx.h" #include "EveChildTurret.h" +#include "Eve/Turret/EveTurretFiringFX.h" BLUE_DEFINE( EveChildTurret ); +extern Be::VarChooser ImpactBehaviourChooser[]; + const Be::ClassInfo* EveChildTurret::ExposeToBlue() { EXPOSURE_BEGIN( EveChildTurret, "" ) MAP_INTERFACE( EveChildTurret ) + MAP_ATTRIBUTE( "trackingInfluence", m_trackingInfluence, "How much tracking is allowed?", Be::READ ) + MAP_ATTRIBUTE( "maxTrackingTime", m_maxTrackingTime, "How long does tracking take?", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "state", m_state, "State of the turret", Be::READ | Be::PERSIST ) + + MAP_PROPERTY( "targetObject", GetTargetObject, SetTargetObject, "object this turret will track" ) + MAP_ATTRIBUTE( "target", m_target, "Info on the target", Be::READ ) + + MAP_ATTRIBUTE( "sysBoneHeight", m_sysBoneHeight, "System bone HEIGHT extension factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchFactor", m_sysBonePitchFactor, "main pitch factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchOffset", m_sysBonePitchOffset, "main pitch offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMin", m_sysBonePitchMin, "main pitch minimum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMax", m_sysBonePitchMax, "main pitch maximum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Factor", m_sysBonePitch01Factor, "pitch 01 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Offset", m_sysBonePitch01Offset, "pitch 01 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Factor", m_sysBonePitch02Factor, "pitch 02 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Offset", m_sysBonePitch02Offset, "pitch 02 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Factor", m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Offset", m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + + MAP_ATTRIBUTE( "firingEffect", m_firingEffect, "", Be::HIDDEN ) // Needed to make Graphite able to detect bindings inside of the firing effect. + MAP_PROPERTY( "firingEffect", GetFiringEffect, SetFiringEffect, "The module for the firing effect of this turret" ) + MAP_ATTRIBUTE( "firingEffectResPath", m_firingEffectResPath, "A res path to the redfile containing the primary firing effect", Be::READWRITE | Be::PERSIST ) + + MAP_ATTRIBUTE( "impactSize", m_impactSize, "Size of impacts. No impact if size is 0 or less", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE_WITH_CHOOSER( "impactBehaviour", m_impactBehaviour, "What do we want to hit? ", Be::READWRITE | Be::NOTIFY | Be::PERSIST | Be::ENUM, ImpactBehaviourChooser ) + + MAP_ATTRIBUTE( "turretMovementObserver", m_turretMovementObserver, "The observer for turret movement sounds. Note: the positioning of this observer is automatic.", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "playMovementSound", m_playMovementSound, "If true this turret set will play its mechanical movement sounds if movement audio events are defined.", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "idleToTargetingMovementAudioEvent", m_idleToTargetingMovementAudioEvent, "The event to send to the audio engine for mechanical noise when a turret moves from idle to targeting.", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "targetingToIdleMovementAudioEvent", m_targetingToIdleMovementAudioEvent, "The event to send to the audio engine for mechanical noise when a turret moves from targeting to idle.", Be::READWRITE | Be::PERSIST ) + + MAP_METHOD_AND_WRAP( + "EnterStateDeactive", + EnterStateDeactive, + "Go into state deactive: play deactive anim and stay inside ship. \n:jessica-placement: TOOLBAR\n:jessica-icon: fa-bed\n" ) + + MAP_METHOD_AND_WRAP( + "EnterStateIdle", + EnterStateIdle, + "Go into state idle: play idle anim and face cannons forward. \n:jessica-placement: TOOLBAR\n:jessica-icon: fa-male\n" ) + + MAP_METHOD_AND_WRAP( + "EnterStateTargeting", + EnterStateTargeting, + "Go into state targeting: face cannons towards enemy. \n:jessica-placement: TOOLBAR\n:jessica-icon: fa-crosshairs\n" ) + + MAP_METHOD_AND_WRAP( + "EnterStateFiring", + EnterStateFiring, + "Go into state fire: play fire anim and face cannons towards enemy.\n:jessica-placement: TOOLBAR\n:jessica-icon: fa-fire-alt\n" ) + + MAP_METHOD_AND_WRAP( + "EnterStateReloading", + EnterStateReloading, + "Go into state reloading: play reload anim and then idle. \n:jessica-placement: TOOLBAR\n:jessica-icon: fa-sync\n" ) + + MAP_METHOD_AND_WRAP( + "ForceStateDeactive", + ForceStateDeactive, + "Force into state deactive: no anim, no transition, just flip." ) + + MAP_METHOD_AND_WRAP( + "ForceStateTargeting", + ForceStateTargeting, + "Force into state targeting: no anim, no transition, just flip." ) + + MAP_METHOD_AND_WRAP( + "GetFiringBoneWorldTransform", + GetFiringBoneWorldTransform, + "Returns the world transform matrix of the specfified firing bone in the currently firing turret." + "\n:param idx: index of the firing bone in the current model." + "\n:returns: The world transform matrix." ) + EXPOSURE_CHAINTO( EveChildMesh ) } From 2462b9abc8b9db8bb65198183b6c00a861c48d44 Mon Sep 17 00:00:00 2001 From: breki Date: Mon, 27 Jul 2026 14:38:07 +0000 Subject: [PATCH 04/23] add validation guards --- .../SpaceObject/Children/EveChildTurret.cpp | 115 +++++++++--------- .../Eve/SpaceObject/Children/EveChildTurret.h | 2 + 2 files changed, 58 insertions(+), 59 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 22fcde315..ec00ede56 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -8,7 +8,7 @@ #include "TriObserverLocal.h" // names of system bones like they are in the granny file -static std::string s_systemBoneSkeletonNames[] = { +constexpr const char* s_systemBoneSkeletonNames[] = { "invalid", // SYSBONE_INVALID "Sys_Rotation_Arm", // SYSBONE_ROTATION "Sys_Rotation_Arm01", // SYSBONE_ROTATION1 @@ -27,11 +27,11 @@ static std::string s_systemBoneSkeletonNames[] = { }; // invalids -const unsigned int INVALID_BONE_INDEX = 0xffffffff; -const unsigned int INVALID_TURRET_INDEX = 0xffffffff; +constexpr unsigned int INVALID_BONE_INDEX = 0xffffffff; +constexpr unsigned int INVALID_TURRET_INDEX = 0xffffffff; // some very static timings, no need to confuse artists by exposing them -const float TRACKING_FADE_TIME = 1.f; +constexpr float TRACKING_FADE_TIME = 1.f; EveChildTurret::EveChildTurret( IRoot* lockobj ) : EveChildMesh( lockobj ) @@ -309,15 +309,14 @@ void EveChildTurret::ReleaseCachedData( BlueAsyncRes* resource ) void EveChildTurret::RebuildCachedData( BlueAsyncRes* resource ) { - const auto geometryResource = m_mesh->GetGeometryResource(); + const auto geometryResource = GetGeometryRes(); if( resource == geometryResource ) { // finished loading the turret geometry resource, so grab vertex decl and bounding sphere if( geometryResource->GetMeshCount() ) { - if( const TriGeometryResMeshData* meshData = geometryResource->GetMeshData( 0 ) ) + if( geometryResource->GetMeshData( 0 ) ) { - // get a bounding box for visibility detection, if this is not already set in the redfile // TODO: might not be needed if( m_worldBoundingSphere.radius == 0.f ) @@ -337,7 +336,7 @@ void EveChildTurret::RebuildCachedData( BlueAsyncRes* resource ) for( int i = 0; i < SYSBONE_MAX; ++i ) { // in case we don't find system bone, ::FindJoint() returns 0xffffffff - m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i].c_str() ); + m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i] ); } InitializeFiringEffect(); @@ -532,7 +531,7 @@ bool EveChildTurret::SetupFiringState() if( m_state == STATE_DEACTIVE ) { // this state change is forbidden! - CCP_LOGERR( "EveTurretSet %s wants to fire but is in deactive state.", m_name.c_str() ); + CCP_LOGERR( "EveChildTurret %s wants to fire but is in deactive state.", m_name.c_str() ); return false; } int closestLocator = -1; @@ -558,7 +557,7 @@ bool EveChildTurret::SetupFiringState() // timing: apply a randomized fire delay // TODO: remove? // CalcRandomDelay(); - float m_randomFiringDelay = 0.f; // TODO: temp value + float randomFiringDelay = 0.f; // TODO: temp value // timing: is the length of the firing effect known? float effectTotalTime = m_firingEffect ? m_firingEffect->GetFiringDuration() : 0.f; @@ -572,18 +571,18 @@ bool EveChildTurret::SetupFiringState() case STATE_IDLE: case STATE_RELOADING: // and delay the effect until we are facing target - m_randomFiringDelay += m_maxTrackingTime; + randomFiringDelay += m_maxTrackingTime; // fadein tracking, play fire anim (only one the firing turret!) and then the active anim m_delayToFadeInTracking = 0.0001f; - PlayAnimation( GetFireAnimationName(), "Active", m_randomFiringDelay ); + PlayAnimation( GetFireAnimationName(), "Active", randomFiringDelay ); // assign locator and turret - m_target->StartFireAtLocator( closestLocator, m_randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + m_target->StartFireAtLocator( closestLocator, randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); break; case STATE_FIRING: case STATE_TARGETING: - PlayAnimation( GetFireAnimationName(), "Active", m_randomFiringDelay ); - m_target->StartFireAtLocator( closestLocator, m_randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + PlayAnimation( GetFireAnimationName(), "Active", randomFiringDelay ); + m_target->StartFireAtLocator( closestLocator, randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); break; default: @@ -706,7 +705,7 @@ void EveChildTurret::InitializeFiringEffect() } m_firingEffect->RegisterWithQuadRenderer( *Tr2QuadRenderer::Instance() ); - auto geometryResource = m_mesh->GetGeometryResource(); + auto geometryResource = GetGeometryRes(); if( geometryResource && geometryResource->GetSkeletonCount() ) { if( TriGeometryResSkeletonData* skeletonData = geometryResource->GetSkeletonData( 0 ) ) @@ -735,7 +734,7 @@ void EveChildTurret::InitializeFiringEffect() void EveChildTurret::InitializeAnimation() { EveChildMesh::InitializeAnimation(); - if( const auto geometryResource = m_mesh->GetGeometryResource() ) + if( const auto geometryResource = GetGeometryRes() ) { // get a model, a meshbinding and animation stuff from the resource const cmf::Data* cmfData = geometryResource->GetCMFData(); @@ -912,16 +911,13 @@ Matrix EveChildTurret::GetTurretBoneTransform( uint32_t boneID ) const { Matrix matrix = m_worldTransform; - if( boneID == INVALID_BONE_INDEX ) - { - // TODO: should support lowLodTransform? prob yes - // return lowLodTransform * matrix; - return matrix; - } + + // TODO: should support lowLodTransform? prob yes + // return lowLodTransform * matrix; if( m_animationUpdater ) { const auto& worldTransforms = m_animationUpdater->GetWorldTransforms(); - if( !worldTransforms.empty() ) + if( boneID < worldTransforms.size() ) { return worldTransforms[boneID] * matrix; } @@ -930,16 +926,21 @@ Matrix EveChildTurret::GetTurretBoneTransform( uint32_t boneID ) const return matrix; } +TriGeometryRes* EveChildTurret::GetGeometryRes() const +{ + return m_mesh ? m_mesh->GetGeometryResource() : nullptr; +} + float EveChildTurret::PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay ) { - if( !m_animationUpdater ) + auto geometryRes = GetGeometryRes(); + if( !m_animationUpdater || !geometryRes ) { return 0.f; } float animLength = 0.f; - auto cmfData = m_mesh->GetGeometryResource()->GetCMFData(); - if( cmfData ) + if( auto cmfData = geometryRes->GetCMFData() ) { // there can be more animations in one res, so find right one size_t animIx = cmfData->animations.size(); @@ -971,38 +972,35 @@ float EveChildTurret::PlayAnimation( const std::string& animName, const std::str // stop all animation StopAnimation( delay ); - if( m_animationUpdater ) + // granny, play first anim once, if provided & found + if( animIx != cmfData->animations.size() ) { - // granny, play first anim once, if provided & found - if( animIx != cmfData->animations.size() ) - { - auto& animation = cmfData->animations[animIx]; - animLength = animation.duration; - - // ( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ) - std::string animationName = cmf::ToStdString( animation.name ); - bool replace = false; // TODO: correct? - int loopCount = 1; - float speed = 1.f; - m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); - // TODO: set start/stop time seems different from ^ - // player->SetStartTime( delay + Tr2Renderer::GetAnimationTime() ); - // player->SetStopTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); - } + auto& animation = cmfData->animations[animIx]; + animLength = animation.duration; + + // ( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ) + std::string animationName = cmf::ToStdString( animation.name ); + bool replace = false; // TODO: correct? + int loopCount = 1; + float speed = 1.f; + m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); + // TODO: set start/stop time seems different from ^ + // player->SetStartTime( delay + Tr2Renderer::GetAnimationTime() ); + // player->SetStopTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); + } - // then play idle anim on loop (after delay), if provided & found - if( idleIx != cmfData->animations.size() ) - { - auto& animation = cmfData->animations[idleIx]; - std::string animationName = cmf::ToStdString( animation.name ); - bool replace = false; // TODO: correct? - int loopCount = 0; - float speed = 1.f; - - m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); - // TODO: set start time seems different from ^ - // player->SetStartTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); - } + // then play idle anim on loop (after delay), if provided & found + if( idleIx != cmfData->animations.size() ) + { + auto& animation = cmfData->animations[idleIx]; + std::string animationName = cmf::ToStdString( animation.name ); + bool replace = false; // TODO: correct? + int loopCount = 0; + float speed = 1.f; + + m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); + // TODO: set start time seems different from ^ + // player->SetStartTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); } } @@ -1012,9 +1010,8 @@ float EveChildTurret::PlayAnimation( const std::string& animName, const std::str void EveChildTurret::StopAnimation( float delay ) { // TODO: prob not needed and can just use animation class function instead of this probably useless middleman - auto geometryResource = m_mesh->GetGeometryResource(); // if we don't have a geometry, animation is useless and probably unwanted - if( !geometryResource ) + if( !GetGeometryRes() ) { return; } diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index cc85f8ec2..e2eb3ecda 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -103,6 +103,8 @@ BLUE_CLASS( EveChildTurret ) : Matrix GetTurretBoneTransform( uint32_t boneID ) const; + TriGeometryRes* GetGeometryRes() const; + // animation float PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay = 0.f ); void StopAnimation( float delay = 0.f ); From f82b14d1de3ec332c52282ef11be047e371bc918 Mon Sep 17 00:00:00 2001 From: breki Date: Mon, 27 Jul 2026 15:49:48 +0000 Subject: [PATCH 05/23] fix async loading --- .../SpaceObject/Children/EveChildTurret.cpp | 105 +++++++++--------- .../Eve/SpaceObject/Children/EveChildTurret.h | 19 ++-- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index ec00ede56..0faab14d1 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -53,6 +53,7 @@ EveChildTurret::~EveChildTurret() m_firingEffect->CleanUp(); } + m_cachedGeometryRes = nullptr; m_skeleton = nullptr; m_skeletonBoneIndices.clear(); m_boneBounds.clear(); @@ -160,6 +161,8 @@ void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, co } */ + UpdateCachedGeometryData(); + if( m_sequencer ) { m_sequencer->RemoveFinishedAnimations( Tr2Renderer::GetAnimationTime() ); @@ -298,68 +301,66 @@ void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, c } } } - -void EveChildTurret::ReleaseCachedData( BlueAsyncRes* resource ) +void EveChildTurret::UpdateCachedGeometryData() { - // TODO: for now duplicates destructor - m_skeleton = nullptr; - m_skeletonBoneIndices.clear(); - m_boneBounds.clear(); + auto* geometryRes = GetGeometryRes(); + if( geometryRes == m_cachedGeometryRes ) + { + return; + } + ReleaseCachedGeometryData(); + if( geometryRes && geometryRes->IsGood() ) + { + BuildCachedGeometryData( *geometryRes ); + m_cachedGeometryRes = geometryRes; + } } - -void EveChildTurret::RebuildCachedData( BlueAsyncRes* resource ) +void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) { - const auto geometryResource = GetGeometryRes(); - if( resource == geometryResource ) + // finished loading the turret geometry resource, so grab vertex decl and bounding sphere + if( geometryRes.GetMeshCount() ) { - // finished loading the turret geometry resource, so grab vertex decl and bounding sphere - if( geometryResource->GetMeshCount() ) + if( geometryRes.GetMeshData( 0 ) ) { - if( geometryResource->GetMeshData( 0 ) ) + // get a bounding box for visibility detection, if this is not already set in the redfile + // TODO: might not be needed + if( m_worldBoundingSphere.radius == 0.f ) { - // get a bounding box for visibility detection, if this is not already set in the redfile - // TODO: might not be needed - if( m_worldBoundingSphere.radius == 0.f ) - { - geometryResource->RecalculateBoundingSphere(); - Vector4 boundingSphere; - geometryResource->GetBoundingSphere( 0, boundingSphere ); - m_worldBoundingSphere = CcpMath::Sphere( boundingSphere ); - } + geometryRes.RecalculateBoundingSphere(); + Vector4 boundingSphere; + geometryRes.GetBoundingSphere( 0, boundingSphere ); + m_worldBoundingSphere = CcpMath::Sphere( boundingSphere ); } } + } - if( geometryResource->GetSkeletonCount() ) + if( geometryRes.GetSkeletonCount() ) + { + if( TriGeometryResSkeletonData* skeletonData = geometryRes.GetSkeletonData( 0 ) ) { - if( TriGeometryResSkeletonData* skeletonData = geometryResource->GetSkeletonData( 0 ) ) + for( int i = 0; i < SYSBONE_MAX; ++i ) { - for( int i = 0; i < SYSBONE_MAX; ++i ) - { - // in case we don't find system bone, ::FindJoint() returns 0xffffffff - m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i] ); - } - - InitializeFiringEffect(); + // in case we don't find system bone, ::FindJoint() returns 0xffffffff + m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i] ); } - } - - InitializeAnimation(); - if( !m_animationQueue.empty() ) - { - std::vector pending; - pending.swap( m_animationQueue ); - for( const auto& [animName, animNameIdle] : pending ) - { - PlayAnimation( animName, animNameIdle ); - } - } - else - { - // force an anim based on a state - ForceIdleAnimation(); + InitializeFiringEffect(); } } + + InitializeAnimation(); + + // TODO: forceXAnimation based on m_state? + ForceIdleAnimation(); +} + +void EveChildTurret::ReleaseCachedGeometryData() +{ + // TODO: for now duplicates destructor + m_cachedGeometryRes = nullptr; + m_skeleton = nullptr; + m_skeletonBoneIndices.clear(); + m_boneBounds.clear(); } void EveChildTurret::EnterStateDeactive() @@ -931,6 +932,13 @@ TriGeometryRes* EveChildTurret::GetGeometryRes() const return m_mesh ? m_mesh->GetGeometryResource() : nullptr; } +// TODO: heavily refactor once animation ownership is decided (m_animationUpdater vs m_sequencer). +// Known defects for the rewrite: +// - a missing anim name aborts the whole request instead of playing what was found +// - the idle anim starts at `delay` instead of after the one-shot finishes +// (original sequenced via player SetStartTime/SetStopTime, no equivalent wired here) +// - StopAnimation is a stub, so the "stop all animation" call below does nothing +// - duplicated find_if lookups float EveChildTurret::PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay ) { auto geometryRes = GetGeometryRes(); @@ -1016,9 +1024,6 @@ void EveChildTurret::StopAnimation( float delay ) return; } - // empty queue, so no more buffered requests - m_animationQueue.clear(); - // stop if( m_animationUpdater ) { diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index e2eb3ecda..7b71a120b 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -11,7 +11,7 @@ BLUE_DECLARE( EveTurretFiringFX ); BLUE_DECLARE( EveTurretTarget ); BLUE_CLASS( EveChildTurret ) : - public EveChildMesh, public IBlueAsyncResNotifyTarget + public EveChildMesh { public: EXPOSE_TO_BLUE(); @@ -31,9 +31,9 @@ BLUE_CLASS( EveChildTurret ) : void UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; void UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; - // IBlueAsyncResNotifyTarget - void ReleaseCachedData( BlueAsyncRes * resource ) override; - void RebuildCachedData( BlueAsyncRes * resource ) override; + void UpdateCachedGeometryData(); + void BuildCachedGeometryData( TriGeometryRes & geometryRes ); + void ReleaseCachedGeometryData(); // action void EnterStateDeactive(); @@ -111,7 +111,7 @@ BLUE_CLASS( EveChildTurret ) : std::string GetFireAnimationName() const; EveTurretFiringFX* GetFiringEffect(); - void SetFiringEffect( EveTurretFiringFX* firingEffect ); + void SetFiringEffect( EveTurretFiringFX * firingEffect ); // TODO: rename GrannyBoneBindingBounds? std::vector m_boneBounds; @@ -136,13 +136,6 @@ BLUE_CLASS( EveChildTurret ) : float m_maxTrackingTime = 1.f; // animation - // TODO: needed? - struct AnimationRequest - { - std::string animName; - std::string animNameIdle; - }; - std::vector m_animationQueue; const cmf::Skeleton* m_skeleton = nullptr; std::vector m_skeletonBoneIndices; std::unique_ptr m_sequencer; @@ -181,6 +174,8 @@ BLUE_CLASS( EveChildTurret ) : TriObserverLocalPtr m_turretMovementObserver; std::wstring m_idleToTargetingMovementAudioEvent; std::wstring m_targetingToIdleMovementAudioEvent; + + TriGeometryResPtr m_cachedGeometryRes; }; TYPEDEF_BLUECLASS( EveChildTurret ); From e58b0bf3cedd4f828df9843a24c49b12210a81b3 Mon Sep 17 00:00:00 2001 From: breki Date: Mon, 27 Jul 2026 16:09:59 +0000 Subject: [PATCH 06/23] cleanup more todos --- .../SpaceObject/Children/EveChildTurret.cpp | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 0faab14d1..1822365c7 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -53,10 +53,7 @@ EveChildTurret::~EveChildTurret() m_firingEffect->CleanUp(); } - m_cachedGeometryRes = nullptr; - m_skeleton = nullptr; - m_skeletonBoneIndices.clear(); - m_boneBounds.clear(); + ReleaseCachedGeometryData(); ReleaseResources( TRISTORAGE_ALL ); } @@ -264,7 +261,6 @@ void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, c // setup and update attached firing effect if( m_firingEffect ) { - // TODO: is this a valid replacement of if( m_activeTurret != INVALID_TURRET_INDEX ) if( m_mesh ) { // update all muzzle points in the firing effect @@ -356,7 +352,6 @@ void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) void EveChildTurret::ReleaseCachedGeometryData() { - // TODO: for now duplicates destructor m_cachedGeometryRes = nullptr; m_skeleton = nullptr; m_skeletonBoneIndices.clear(); @@ -503,19 +498,9 @@ void EveChildTurret::EnterStateFiring() m_firingEffect->StopFiring(); } - // We're starting a firing sequence, we need to set up our firing effect time-delays if( m_firingEffect ) { - // TODO: random firing delay yay or nay - //if( m_maxCyclingFirePos > 1 ) - //{ - // m_firingEffect->PrepareFiring( m_randomFiringDelay, m_currentCyclingFiresPos, m_cyclingFireGroupCount ); - //} - //else - //{ - float randomFiringDelay = 0.f; - m_firingEffect->PrepareFiring( randomFiringDelay ); - //} + m_firingEffect->PrepareFiring( 0.f ); if( m_target != nullptr ) { @@ -555,11 +540,6 @@ bool EveChildTurret::SetupFiringState() } */ - // timing: apply a randomized fire delay - // TODO: remove? - // CalcRandomDelay(); - float randomFiringDelay = 0.f; // TODO: temp value - // timing: is the length of the firing effect known? float effectTotalTime = m_firingEffect ? m_firingEffect->GetFiringDuration() : 0.f; float effectPeakTime = m_firingEffect ? m_firingEffect->GetFiringPeakTime() : 0.f; @@ -571,19 +551,17 @@ bool EveChildTurret::SetupFiringState() { case STATE_IDLE: case STATE_RELOADING: - // and delay the effect until we are facing target - randomFiringDelay += m_maxTrackingTime; // fadein tracking, play fire anim (only one the firing turret!) and then the active anim m_delayToFadeInTracking = 0.0001f; - PlayAnimation( GetFireAnimationName(), "Active", randomFiringDelay ); + PlayAnimation( GetFireAnimationName(), "Active", m_maxTrackingTime ); // assign locator and turret - m_target->StartFireAtLocator( closestLocator, randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + m_target->StartFireAtLocator( closestLocator, m_maxTrackingTime + effectPeakTime, effectTotalTime - effectPeakTime, &source ); break; case STATE_FIRING: case STATE_TARGETING: - PlayAnimation( GetFireAnimationName(), "Active", randomFiringDelay ); - m_target->StartFireAtLocator( closestLocator, randomFiringDelay + effectPeakTime, effectTotalTime - effectPeakTime, &source ); + PlayAnimation( GetFireAnimationName(), "Active", m_maxTrackingTime ); + m_target->StartFireAtLocator( closestLocator, m_maxTrackingTime + effectPeakTime, effectTotalTime - effectPeakTime, &source ); break; default: @@ -662,7 +640,6 @@ void EveChildTurret::ForceIdleAnimation() break; } - // set it to all turrets in this set if( idleAnimName.length() > 0 ) { PlayAnimation( "", idleAnimName, 0.f ); From 34784fee9dec7cbd64c88bc02661199d3e07bf14 Mon Sep 17 00:00:00 2001 From: breki Date: Mon, 27 Jul 2026 16:38:29 +0000 Subject: [PATCH 07/23] impact behviour support --- trinity/Eve/SpaceObject/Children/EveChildTurret.cpp | 12 ++++-------- .../Eve/SpaceObject/Children/EveChildTurret_Blue.cpp | 2 +- trinity/Eve/Turret/EveTurretTarget.cpp | 9 +++++++++ trinity/Eve/Turret/EveTurretTarget.h | 1 + 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 1822365c7..a4b37f7a8 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -59,21 +59,17 @@ EveChildTurret::~EveChildTurret() } bool EveChildTurret::Initialize() { - // pass down some user-defined data into sub-modules we don't save out - // TODO: keep or discard - // m_target->SetBehaviour( m_laserMissBehaviour, m_projectileMissBehaviour, m_impactSize, m_impactBehaviour ); + // pass down some user-defined data into sub-modules we don't save out. + m_target->SetImpactBehaviour( m_impactSize, m_impactBehaviour ); return EveChildMesh::Initialize(); } bool EveChildTurret::OnModified( Be::Var* value ) { - /* - if( IsMatch( value, m_laserMissBehaviour ) || IsMatch( value, m_projectileMissBehaviour ) || IsMatch( value, m_impactSize ) || IsMatch( value, m_impactBehaviour ) ) + if( IsMatch( value, m_impactSize ) || IsMatch( value, m_impactBehaviour ) ) { - // TODO: keep or discard - m_target->SetBehaviour( m_laserMissBehaviour, m_projectileMissBehaviour, m_impactSize, m_impactBehaviour ); + m_target->SetImpactBehaviour( m_impactSize, m_impactBehaviour ); } - */ return EveChildMesh::OnModified( value ); } void EveChildTurret::RegisterComponents() diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index 3b3bb0251..9d498f21f 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -35,7 +35,7 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() MAP_PROPERTY( "firingEffect", GetFiringEffect, SetFiringEffect, "The module for the firing effect of this turret" ) MAP_ATTRIBUTE( "firingEffectResPath", m_firingEffectResPath, "A res path to the redfile containing the primary firing effect", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "impactSize", m_impactSize, "Size of impacts. No impact if size is 0 or less", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "impactSize", m_impactSize, "Size of impacts. No impact if size is 0 or less", Be::READWRITE | Be::NOTIFY | Be::PERSIST ) MAP_ATTRIBUTE_WITH_CHOOSER( "impactBehaviour", m_impactBehaviour, "What do we want to hit? ", Be::READWRITE | Be::NOTIFY | Be::PERSIST | Be::ENUM, ImpactBehaviourChooser ) MAP_ATTRIBUTE( "turretMovementObserver", m_turretMovementObserver, "The observer for turret movement sounds. Note: the positioning of this observer is automatic.", Be::READWRITE | Be::PERSIST ) diff --git a/trinity/Eve/Turret/EveTurretTarget.cpp b/trinity/Eve/Turret/EveTurretTarget.cpp index a4126ae26..d3298ced1 100644 --- a/trinity/Eve/Turret/EveTurretTarget.cpp +++ b/trinity/Eve/Turret/EveTurretTarget.cpp @@ -332,6 +332,15 @@ void EveTurretTarget::SetBehaviour( bool laserMiss, bool projectileMiss, float i { m_laserMissBehaviour = laserMiss; m_projectileMissBehaviour = projectileMiss; + SetImpactBehaviour( impactSize, impactBehaviour ); +} + +// -------------------------------------------------------------------------------- +// Description: +// Set the impact configuration, leaving miss behaviour disabled/untouched +// -------------------------------------------------------------------------------- +void EveTurretTarget::SetImpactBehaviour( float impactSize, ImpactBehaviour::Type impactBehaviour ) +{ m_impactSize = impactSize; m_impactBehaviour = impactBehaviour; } diff --git a/trinity/Eve/Turret/EveTurretTarget.h b/trinity/Eve/Turret/EveTurretTarget.h index d4de78f8c..5a1769c0a 100644 --- a/trinity/Eve/Turret/EveTurretTarget.h +++ b/trinity/Eve/Turret/EveTurretTarget.h @@ -48,6 +48,7 @@ BLUE_CLASS( EveTurretTarget ) : // hit/miss void SetBehaviour( bool laserMiss, bool projectileMiss, float impactSize, ImpactBehaviour::Type impactBehaviour ); + void SetImpactBehaviour( float impactSize, ImpactBehaviour::Type impactBehaviour ); bool GetShotMissed() const; void SetShotMissed( bool missed ); double GetLastShotTime() const; From 0cbdbfd1e98a469cd5d5232a7537ff8781865891 Mon Sep 17 00:00:00 2001 From: breki Date: Tue, 28 Jul 2026 11:45:29 +0000 Subject: [PATCH 08/23] resolve more todos --- .../SpaceObject/Children/EveChildTurret.cpp | 107 +++++------------- .../Eve/SpaceObject/Children/EveChildTurret.h | 6 + .../Children/EveChildTurret_Blue.cpp | 8 ++ 3 files changed, 44 insertions(+), 77 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index a4b37f7a8..965011eea 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -7,7 +7,7 @@ #include "TriMath.h" #include "TriObserverLocal.h" -// names of system bones like they are in the granny file +// names of system bones like they are in the cmf file constexpr const char* s_systemBoneSkeletonNames[] = { "invalid", // SYSBONE_INVALID "Sys_Rotation_Arm", // SYSBONE_ROTATION @@ -59,7 +59,7 @@ EveChildTurret::~EveChildTurret() } bool EveChildTurret::Initialize() { - // pass down some user-defined data into sub-modules we don't save out. + // pass down some user-defined data into submodules we don't save out. m_target->SetImpactBehaviour( m_impactSize, m_impactBehaviour ); return EveChildMesh::Initialize(); @@ -129,30 +129,10 @@ void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, co { float deltaT = updateContext.GetDeltaT(); - /* - // TODO: LODs needed? - // LODing - if( UpdateLOD( updateContext ) ) + if( m_firingEffect ) { - // LOD change, so just call ::InitializeGeometryResource(), takes care of everything - InitializeGeometryResource(); - - // LOD change: toggle source dest effect of the attached firingFX - if( m_firingEffect ) - { - switch( m_lodLevel ) - { - case LOD_DISABLED: - case LOD_HIGHEST: - m_firingEffect->SetDisplaySourceObject( true ); - break; - default: - m_firingEffect->SetDisplaySourceObject( false ); - break; - } - } + m_firingEffect->SetDisplaySourceObject( IsVisible( updateContext ) ); } - */ UpdateCachedGeometryData(); @@ -192,8 +172,7 @@ void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, co } // update the target locator position - // TODO: probably wrong - Vector3 position = m_parentData.transform.GetTranslation(); + Vector3 position = m_worldTransform.GetTranslation(); if( m_firingEffect ) { m_firingEffect->GetStartPosition( position ); @@ -203,16 +182,13 @@ void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, co if( m_mesh && m_turretMovementObserver != nullptr ) { - // TODO: new turret movementObserver prob needed - // m_turretMovementObserver->Update( m_singleTurrets[0].worldMatrix ); + m_turretMovementObserver->Update( m_worldTransform ); } EveChildMesh::UpdateSyncronous( updateContext, params ); } void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) { - - // TODO: prob some freakyness in here float deltaT = updateContext.GetDeltaT(); // handle fading of turret tracking if( m_trackingInfluenceDelta != 0.f ) @@ -250,7 +226,6 @@ void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, c } } - // TODO: does this have to happen after the timing stuff over there ^ // Should handle all the mesh data and transforms EveChildMesh::UpdateAsyncronous( updateContext, params ); @@ -277,14 +252,13 @@ void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, c { // if we haven't initialised muzzle positions, do it now // this can happen, and if we don't do this all effects originate from - // the player ship until turret geometry is loaded and muzzle positions + // the turret root until turret geometry is loaded and muzzle positions // properly set if( !m_firingEffectMuzzlePosSet ) { for( unsigned int i = 0; i < m_firingEffect->GetPerMuzzleEffectCount(); ++i ) { - // use something relatively sensible, even absent geometry - m_firingEffect->SetMuzzleTransform( i, &m_parentData.transform ); + m_firingEffect->SetMuzzleTransform( i, &m_worldTransform ); } m_firingEffectMuzzlePosSet = true; @@ -309,23 +283,6 @@ void EveChildTurret::UpdateCachedGeometryData() } void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) { - // finished loading the turret geometry resource, so grab vertex decl and bounding sphere - if( geometryRes.GetMeshCount() ) - { - if( geometryRes.GetMeshData( 0 ) ) - { - // get a bounding box for visibility detection, if this is not already set in the redfile - // TODO: might not be needed - if( m_worldBoundingSphere.radius == 0.f ) - { - geometryRes.RecalculateBoundingSphere(); - Vector4 boundingSphere; - geometryRes.GetBoundingSphere( 0, boundingSphere ); - m_worldBoundingSphere = CcpMath::Sphere( boundingSphere ); - } - } - } - if( geometryRes.GetSkeletonCount() ) { if( TriGeometryResSkeletonData* skeletonData = geometryRes.GetSkeletonData( 0 ) ) @@ -342,7 +299,6 @@ void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) InitializeAnimation(); - // TODO: forceXAnimation based on m_state? ForceIdleAnimation(); } @@ -352,6 +308,7 @@ void EveChildTurret::ReleaseCachedGeometryData() m_skeleton = nullptr; m_skeletonBoneIndices.clear(); m_boneBounds.clear(); + m_firingEffectMuzzlePosSet = false; } void EveChildTurret::EnterStateDeactive() @@ -391,11 +348,10 @@ void EveChildTurret::EnterStateDeactive() void EveChildTurret::EnterStateIdle() { - // TODO: might want to remove this state - // if( !m_isOnline ) - // { - // return; - // } + if( !m_isOnline ) + { + return; + } switch( m_state ) { @@ -435,11 +391,10 @@ void EveChildTurret::EnterStateIdle() void EveChildTurret::EnterStateTargeting() { float animLength = 0.f; - // TODO: might want to remove this state - // if( !m_isOnline ) - // { - // return; - // } + if( !m_isOnline ) + { + return; + } // what state are we in? switch( m_state ) @@ -496,7 +451,14 @@ void EveChildTurret::EnterStateFiring() if( m_firingEffect ) { - m_firingEffect->PrepareFiring( 0.f ); + if( m_maxCyclingFirePos > 1 ) + { + m_firingEffect->PrepareFiring( 0.f, m_currentCyclingFiresPos, m_cyclingFireGroupCount ); + } + else + { + m_firingEffect->PrepareFiring( 0.f ); + } if( m_target != nullptr ) { @@ -523,9 +485,7 @@ bool EveChildTurret::SetupFiringState() closestLocator = m_target->FindClosestLocator( &source, &position ); } - // TODO: remove or keep? // if this turret is set to cycle through the muzzles for firing, do it here - /* if( m_maxCyclingFirePos > 1 ) { m_currentCyclingFiresPos += m_cyclingFireGroupCount; @@ -534,7 +494,6 @@ bool EveChildTurret::SetupFiringState() m_currentCyclingFiresPos = 0; } } - */ // timing: is the length of the firing effect known? float effectTotalTime = m_firingEffect ? m_firingEffect->GetFiringDuration() : 0.f; @@ -627,6 +586,7 @@ void EveChildTurret::ForceIdleAnimation() idleAnimName = "Inactive"; break; case STATE_IDLE: + case STATE_RELOADING: case STATE_TARGETING: case STATE_FIRING: idleAnimName = "Active"; @@ -657,7 +617,7 @@ Matrix EveChildTurret::GetFiringBoneWorldTransform( unsigned int muzzle ) const { if( !m_mesh ) { - return m_parentData.transform; + return m_worldTransform; } Matrix matrix = m_worldTransform; @@ -673,6 +633,7 @@ Matrix EveChildTurret::GetFiringBoneWorldTransform( unsigned int muzzle ) const void EveChildTurret::InitializeFiringEffect() { + m_firingEffectMuzzlePosSet = false; if( !m_firingEffect ) { return; @@ -755,8 +716,6 @@ void EveChildTurret::ModifySystemBoneTransform( SystemBones bone, const Vector3* Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); // 2nd: apply this quat after the original one quat = rotation * quat; - // TODO: cmf_transform ? - // 3rd: make granny_transform from quat rotation = quat; } break; @@ -769,7 +728,6 @@ void EveChildTurret::ModifySystemBoneTransform( SystemBones bone, const Vector3* Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); // 2nd: apply this quat after the original one quat = rotation * quat; - // 3rd: make granny_transform from quat rotation = quat; } break; @@ -840,7 +798,6 @@ void EveChildTurret::CalcTransformForPitchBone( const Vector3* target, float min Quaternion quat = RotationQuaternion( 0.f, -alpha, 0.f ); // 2nd: apply this quat after the original one quat = rotation * quat; - // 2nd: make granny_transform from quat rotation = quat; } @@ -884,19 +841,15 @@ float EveChildTurret::GetBonePitchOffset( unsigned int boneIndex ) const Matrix EveChildTurret::GetTurretBoneTransform( uint32_t boneID ) const { Matrix matrix = m_worldTransform; - - - // TODO: should support lowLodTransform? prob yes - // return lowLodTransform * matrix; if( m_animationUpdater ) { const auto& worldTransforms = m_animationUpdater->GetWorldTransforms(); + // covers Invalid since INVALID_BONE_INDEX is max_float if( boneID < worldTransforms.size() ) { return worldTransforms[boneID] * matrix; } } - // TODO: port rest of function? return matrix; } @@ -953,7 +906,7 @@ float EveChildTurret::PlayAnimation( const std::string& animName, const std::str // stop all animation StopAnimation( delay ); - // granny, play first anim once, if provided & found + // play first anim once, if provided & found if( animIx != cmfData->animations.size() ) { auto& animation = cmfData->animations[animIx]; diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index 7b71a120b..97295bca0 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -124,6 +124,8 @@ BLUE_CLASS( EveChildTurret ) : // target (object we are tracking) EveTurretTargetPtr m_target; + bool m_isOnline = true; + // impacts float m_impactSize = 0.f; ImpactBehaviour::Type m_impactBehaviour = ImpactBehaviour::DAMAGE_LOCATOR; @@ -141,6 +143,10 @@ BLUE_CLASS( EveChildTurret ) : std::unique_ptr m_sequencer; cmf::SkeletonPose m_pose; + uint32_t m_maxCyclingFirePos = 1; + uint32_t m_cyclingFireGroupCount = 1; + uint32_t m_currentCyclingFiresPos = 0; + // system bones unsigned int m_systemBoneID[SYSBONE_MAX]; // specific system bone values diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index 9d498f21f..0d36c6501 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -12,6 +12,9 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() { EXPOSURE_BEGIN( EveChildTurret, "" ) MAP_INTERFACE( EveChildTurret ) + + + MAP_ATTRIBUTE( "isOnline", m_isOnline, "Indicate if turret is active", Be::READWRITE ) MAP_ATTRIBUTE( "trackingInfluence", m_trackingInfluence, "How much tracking is allowed?", Be::READ ) MAP_ATTRIBUTE( "maxTrackingTime", m_maxTrackingTime, "How long does tracking take?", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "state", m_state, "State of the turret", Be::READ | Be::PERSIST ) @@ -31,6 +34,11 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() MAP_ATTRIBUTE( "sysBonePitch03Factor", m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "sysBonePitch03Offset", m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "maxCyclingFirePos", m_maxCyclingFirePos, "If greater than one we cycle through the given number of muzzles.", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "cyclingFireGroupCount", m_cyclingFireGroupCount, "The number of muzzles in one cycle group, usually only one.", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "currentCyclingFiresPos", m_currentCyclingFiresPos, "Current muzzle id due to cycling muzzles", Be::READ ) + + MAP_ATTRIBUTE( "firingEffect", m_firingEffect, "", Be::HIDDEN ) // Needed to make Graphite able to detect bindings inside of the firing effect. MAP_PROPERTY( "firingEffect", GetFiringEffect, SetFiringEffect, "The module for the firing effect of this turret" ) MAP_ATTRIBUTE( "firingEffectResPath", m_firingEffectResPath, "A res path to the redfile containing the primary firing effect", Be::READWRITE | Be::PERSIST ) From e05dd34ce4be6be4fc03a53b1ac6b392083b4c89 Mon Sep 17 00:00:00 2001 From: breki Date: Tue, 28 Jul 2026 14:52:54 +0000 Subject: [PATCH 09/23] Add posemodifer interface and remove more todos --- trinity/CMakeLists.txt | 1 + .../SpaceObject/Children/EveChildTurret.cpp | 67 +++++++++++-------- .../Eve/SpaceObject/Children/EveChildTurret.h | 20 ++---- trinity/Include/ITr2PoseModifier.h | 19 ++++++ trinity/Tr2GrannyAnimation.cpp | 20 +++++- trinity/Tr2GrannyAnimation.h | 6 ++ 6 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 trinity/Include/ITr2PoseModifier.h diff --git a/trinity/CMakeLists.txt b/trinity/CMakeLists.txt index fe753d463..3aa2a7b29 100644 --- a/trinity/CMakeLists.txt +++ b/trinity/CMakeLists.txt @@ -842,6 +842,7 @@ set(_SOURCES Include/ITr2InstanceData.h Include/ITr2Interior.h Include/ITr2MultiPassScene.h + Include/ITr2PoseModifier.h Include/ITr2Scene.h Include/ITr2Updateable.h Include/ITr2ValueBinding.h diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 965011eea..4af33e885 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "EveChildTurret.h" #include "Eve/Turret/EveTurretFiringFX.h" +#include "Tr2GrannyAnimation.h" #include "Tr2MeshBase.h" #include "TriMath.h" #include "TriObserverLocal.h" @@ -48,6 +49,11 @@ EveChildTurret::EveChildTurret( IRoot* lockobj ) : EveChildTurret::~EveChildTurret() { + if( m_hookedUpdater && m_hookedUpdater->GetPoseModifier() == this ) + { + m_hookedUpdater->SetPoseModifier( nullptr ); + } + if( m_firingEffect ) { m_firingEffect->CleanUp(); @@ -136,11 +142,6 @@ void EveChildTurret::UpdateSyncronous( const EveUpdateContext& updateContext, co UpdateCachedGeometryData(); - if( m_sequencer ) - { - m_sequencer->RemoveFinishedAnimations( Tr2Renderer::GetAnimationTime() ); - } - // setup and update attached firing effect if( m_firingEffect ) { @@ -305,9 +306,6 @@ void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) void EveChildTurret::ReleaseCachedGeometryData() { m_cachedGeometryRes = nullptr; - m_skeleton = nullptr; - m_skeletonBoneIndices.clear(); - m_boneBounds.clear(); m_firingEffectMuzzlePosSet = false; } @@ -668,33 +666,44 @@ void EveChildTurret::InitializeFiringEffect() void EveChildTurret::InitializeAnimation() { + if( !m_animationUpdater ) + { + m_animationUpdater.CreateInstance(); + } EveChildMesh::InitializeAnimation(); - if( const auto geometryResource = GetGeometryRes() ) + + if( m_hookedUpdater != m_animationUpdater ) { - // get a model, a meshbinding and animation stuff from the resource - const cmf::Data* cmfData = geometryResource->GetCMFData(); - if( cmfData && cmfData->skeletons.size() ) + if( m_hookedUpdater && m_hookedUpdater->GetPoseModifier() == this ) { - const auto mesh = std::find_if( cmfData->meshes.begin(), cmfData->meshes.end(), []( const cmf::Mesh& m ) { - return m.skeleton == 0; - } ); - - if( mesh != cmfData->meshes.end() && mesh->boneBindings.size() ) - { - if( m_skeletonBoneIndices.empty() ) - { - m_skeleton = &cmfData->skeletons[0]; + m_hookedUpdater->SetPoseModifier( nullptr ); + } + m_animationUpdater->SetPoseModifier( this ); + m_hookedUpdater = m_animationUpdater; + } +} +void EveChildTurret::ModifyPose( const cmf::Skeleton& skeleton, cmf::SkeletonPose& pose ) +{ + if( m_trackingInfluence == 0.f ) + { + return; + } - if( !m_sequencer ) - { - m_sequencer = std::make_unique( *m_skeleton ); - cmf::RestPose( m_pose, *m_skeleton ); - } + Vector3 targetPosOS = TransformCoord( *m_target->GetTrackingPosition(), Inverse( m_worldTransform ) ); - m_skeletonBoneIndices = Tr2GrannyAnimationUtils::CreateMapping( *m_skeleton, mesh->boneBindings, static_cast( mesh->boneBindings.size() ) ); - } - } + for( unsigned int bone = 0; bone < SYSBONE_MAX; ++bone ) + { + // covers Invalid since INVALID_BONE_INDEX is max + if( m_systemBoneID[bone] < pose.boneTransforms.size() ) + { + cmf::Transform& boneTransform = pose.boneTransforms[m_systemBoneID[bone]]; + ModifySystemBoneTransform( + static_cast( bone ), + &targetPosOS, + nullptr, + boneTransform.position, + boneTransform.rotation ); } } } diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index 97295bca0..033b9c925 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -6,12 +6,14 @@ #include "EveChildMesh.h" #include "Eve/Turret/EveTurretTarget.h" +#include "Include/ITr2PoseModifier.h" BLUE_DECLARE( EveTurretFiringFX ); BLUE_DECLARE( EveTurretTarget ); BLUE_CLASS( EveChildTurret ) : - public EveChildMesh + public EveChildMesh, + public ITr2PoseModifier { public: EXPOSE_TO_BLUE(); @@ -60,9 +62,10 @@ BLUE_CLASS( EveChildTurret ) : STATE_RELOADING, }; + void ModifyPose( const cmf::Skeleton& skeleton, cmf::SkeletonPose& pose ) override; + protected: // system-controlled bones - // TODO: needed? enum SystemBones { SYSBONE_INVALID = 0, @@ -88,8 +91,6 @@ BLUE_CLASS( EveChildTurret ) : void InitializeAnimation() override; - // TODO: Need update LOD ? - // set transform for tracking void ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const; @@ -113,9 +114,6 @@ BLUE_CLASS( EveChildTurret ) : EveTurretFiringFX* GetFiringEffect(); void SetFiringEffect( EveTurretFiringFX * firingEffect ); - // TODO: rename GrannyBoneBindingBounds? - std::vector m_boneBounds; - // Assign the target object void SetTargetObject( IRoot * target ); ITriTargetablePtr GetTargetObject(); @@ -137,11 +135,8 @@ BLUE_CLASS( EveChildTurret ) : float m_delayToFadeInTracking = 0.f; float m_maxTrackingTime = 1.f; - // animation - const cmf::Skeleton* m_skeleton = nullptr; - std::vector m_skeletonBoneIndices; - std::unique_ptr m_sequencer; - cmf::SkeletonPose m_pose; + // animation: updater we last hooked our pose modifier into (to unhook on swap) + Tr2GrannyAnimationPtr m_hookedUpdater; uint32_t m_maxCyclingFirePos = 1; uint32_t m_cyclingFireGroupCount = 1; @@ -170,7 +165,6 @@ BLUE_CLASS( EveChildTurret ) : // firing effect redfile path std::string m_firingEffectResPath; - // TODO: move firing effect into its own class? // firing effect EveTurretFiringFXPtr m_firingEffect; bool m_firingEffectMuzzlePosSet = false; diff --git a/trinity/Include/ITr2PoseModifier.h b/trinity/Include/ITr2PoseModifier.h new file mode 100644 index 000000000..1d23e3284 --- /dev/null +++ b/trinity/Include/ITr2PoseModifier.h @@ -0,0 +1,19 @@ +// Copyright © 2026 Fenris Creations ehf. + +#pragma once + +#ifndef ITR2POSEMODIFIER_H +#define ITR2POSEMODIFIER_H + +#include + +class ITr2PoseModifier +{ +public: + virtual void ModifyPose( const cmf::Skeleton& skeleton, cmf::SkeletonPose& pose ) = 0; + +protected: + ~ITr2PoseModifier() = default; +}; + +#endif //ITR2POSEMODIFIER_H diff --git a/trinity/Tr2GrannyAnimation.cpp b/trinity/Tr2GrannyAnimation.cpp index 0dbe67aa5..921d2fa20 100644 --- a/trinity/Tr2GrannyAnimation.cpp +++ b/trinity/Tr2GrannyAnimation.cpp @@ -6,6 +6,7 @@ #include "Resources/TriGeometryRes.h" #include "Tr2Renderer.h" #include "include/ITr2DebugRenderer.h" +#include "Include/ITr2PoseModifier.h" #include "Utilities/BoundingBox.h" #include "Utilities/BoundingSphere.h" #include "Tr2VertexDefinitionUtilities.h" @@ -88,6 +89,7 @@ Tr2GrannyAnimation::Tr2GrannyAnimation( IRoot* lockobj ) : m_additiveMode( false ), m_aimingBone( false ), m_aimBone( "" ), + m_poseModifier( nullptr ), m_paused( false ), m_pauseTime( 0.f ), m_totalPauseOffset( 0.f ) @@ -1691,6 +1693,12 @@ void Tr2GrannyAnimation::PrePhysicsAnimation( Be::Time time, const Matrix& model UpdateAimingBone( skeleton ); + if( m_poseModifier ) + { + m_poseModifier->ModifyPose( skeleton, m_pose ); + } + + if( m_boneOffset.NeedRebind( (uint32_t)skeleton.bones.size() ) && skeleton.bones.size() ) { std::vector bones( skeleton.bones.size() ); @@ -2133,6 +2141,16 @@ void Tr2GrannyAnimation::DisableAimBone() m_aimingBone = false; } +ITr2PoseModifier* Tr2GrannyAnimation::GetPoseModifier() const +{ + return m_poseModifier; +} + +void Tr2GrannyAnimation::SetPoseModifier( ITr2PoseModifier* poseModifier ) +{ + m_poseModifier = poseModifier; +} + void Tr2GrannyAnimation::SetAdditiveBlendMode( bool additive ) { m_additiveMode = additive; @@ -2434,7 +2452,7 @@ std::pair Tr2AnimationMeshBinding::GetBoneTransforms() { GrannyColumnMatrixMultiply4x3Transpose( (granny_real32*)( (granny_matrix_3x4*)m_boneTransforms.get() )[i], - (granny_real32*)m_meshSkeleton->Bones[meshToBone[i]].InverseWorld4x4, + (granny_real32*)m_meshSkeleton -> Bones[meshToBone[i]].InverseWorld4x4, (granny_real32*)GrannyGetWorldPose4x4( m_animation->m_worldPose, animBones[i] ) ); } } diff --git a/trinity/Tr2GrannyAnimation.h b/trinity/Tr2GrannyAnimation.h index 90ade9265..95cd64b52 100644 --- a/trinity/Tr2GrannyAnimation.h +++ b/trinity/Tr2GrannyAnimation.h @@ -13,6 +13,7 @@ BLUE_DECLARE( TriGeometryRes ); BLUE_DECLARE( Tr2GrannyAnimation ); class Tr2AnimationMeshBinding; +class ITr2PoseModifier; namespace Tr2GrannyAnimationUtils { @@ -94,6 +95,9 @@ BLUE_CLASS( Tr2GrannyAnimation ) : void AimBone( const char* boneName, float target_x, float target_y, float target_z, float axis_x, float axis_y, float axis_z ); void DisableAimBone(); + ITr2PoseModifier* GetPoseModifier() const; + void SetPoseModifier( ITr2PoseModifier * poseModifier ); + void SetAdditiveBlendMode( bool additive ); bool GetAdditiveBlendMode(); @@ -219,6 +223,8 @@ BLUE_CLASS( Tr2GrannyAnimation ) : Vector3 m_aimBoneOrientation; Vector3 m_aimAxis; + ITr2PoseModifier* m_poseModifier; + bool m_useMeshBinding; bool m_animationEnabled; From b22b565f7f7b67c43f0cf576902290a5a431aa8d Mon Sep 17 00:00:00 2001 From: breki Date: Tue, 28 Jul 2026 15:32:55 +0000 Subject: [PATCH 10/23] more animation setup, play/stop working now --- .../SpaceObject/Children/EveChildTurret.cpp | 101 +++--------------- trinity/Tr2GrannyAnimation.cpp | 5 + trinity/Tr2GrannyAnimation.h | 1 + trinity/Tr2GrannyAnimationLayer.cpp | 36 +++++++ trinity/Tr2GrannyAnimationLayer.h | 1 + trinity/Tr2GrannyAnimation_Blue.cpp | 6 ++ 6 files changed, 61 insertions(+), 89 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 4af33e885..1dbc16981 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -867,116 +867,41 @@ TriGeometryRes* EveChildTurret::GetGeometryRes() const return m_mesh ? m_mesh->GetGeometryResource() : nullptr; } -// TODO: heavily refactor once animation ownership is decided (m_animationUpdater vs m_sequencer). -// Known defects for the rewrite: -// - a missing anim name aborts the whole request instead of playing what was found -// - the idle anim starts at `delay` instead of after the one-shot finishes -// (original sequenced via player SetStartTime/SetStopTime, no equivalent wired here) -// - StopAnimation is a stub, so the "stop all animation" call below does nothing -// - duplicated find_if lookups float EveChildTurret::PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay ) { - auto geometryRes = GetGeometryRes(); - if( !m_animationUpdater || !geometryRes ) + if( !m_animationUpdater ) { return 0.f; } - float animLength = 0.f; - - if( auto cmfData = geometryRes->GetCMFData() ) - { - // there can be more animations in one res, so find right one - size_t animIx = cmfData->animations.size(); - if( !animName.empty() ) - { - auto animation = std::find_if( cmfData->animations.begin(), cmfData->animations.end(), [&animName]( const cmf::Animation& anim ) { - return cmf::ToStdStringView( anim.name ) == animName; - } ); - if( animation == cmfData->animations.end() ) - { - return 0.f; - } - animIx = std::distance( cmfData->animations.begin(), animation ); - } - - size_t idleIx = cmfData->animations.size(); - if( !animNameIdle.empty() ) - { - auto animation = std::find_if( cmfData->animations.begin(), cmfData->animations.end(), [&animNameIdle]( const cmf::Animation& anim ) { - return cmf::ToStdStringView( anim.name ) == animNameIdle; - } ); - if( animation == cmfData->animations.end() ) - { - return 0.f; - } - idleIx = std::distance( cmfData->animations.begin(), animation ); - } - // stop all animation - StopAnimation( delay ); + m_animationUpdater->StopAnimations( delay ); - // play first anim once, if provided & found - if( animIx != cmfData->animations.size() ) - { - auto& animation = cmfData->animations[animIx]; - animLength = animation.duration; - - // ( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ) - std::string animationName = cmf::ToStdString( animation.name ); - bool replace = false; // TODO: correct? - int loopCount = 1; - float speed = 1.f; - m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); - // TODO: set start/stop time seems different from ^ - // player->SetStartTime( delay + Tr2Renderer::GetAnimationTime() ); - // player->SetStopTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); - } - - // then play idle anim on loop (after delay), if provided & found - if( idleIx != cmfData->animations.size() ) + float animLength = 0.f; + if( !animName.empty() ) + { + if( m_animationUpdater->PlayAnimation( animName.c_str(), false, 1, 0.f, 1.f, false ) ) { - auto& animation = cmfData->animations[idleIx]; - std::string animationName = cmf::ToStdString( animation.name ); - bool replace = false; // TODO: correct? - int loopCount = 0; - float speed = 1.f; - - m_animationUpdater->PlayAnimation( animationName.c_str(), replace, loopCount, delay, speed ); - // TODO: set start time seems different from ^ - // player->SetStartTime( animLength + delay + Tr2Renderer::GetAnimationTime() ); + animLength = m_animationUpdater->FindAnimationDurationByName( animName.c_str() ); } } + if( !animNameIdle.empty() ) + { + m_animationUpdater->PlayAnimation( animNameIdle.c_str(), false, 0, 0.f, 1.f, false ); + } return animLength; } void EveChildTurret::StopAnimation( float delay ) { - // TODO: prob not needed and can just use animation class function instead of this probably useless middleman - // if we don't have a geometry, animation is useless and probably unwanted - if( !GetGeometryRes() ) - { - return; - } - - // stop if( m_animationUpdater ) { - /* - // TODO: find correct functions - m_animationUpdater->EnumerateAnimations( [&]( const std::shared_ptr& player ) { - player->SetStopTime( delay + Tr2Renderer::GetAnimationTime() ); - } ); - - m_animationUpdater->RemoveFinishedAnimations( Tr2Renderer::GetAnimationTime() ); - */ + m_animationUpdater->StopAnimations( delay ); } } std::string EveChildTurret::GetFireAnimationName() const { - /* - // TODO: idk if this is useful skipping for now // if m_currentCyclingFiresPos is 0, it's just "Fire" std::string res = "Fire"; if( m_currentCyclingFiresPos > 0 ) @@ -986,8 +911,6 @@ std::string EveChildTurret::GetFireAnimationName() const } return res; - */ - return ""; } EveTurretFiringFX* EveChildTurret::GetFiringEffect() diff --git a/trinity/Tr2GrannyAnimation.cpp b/trinity/Tr2GrannyAnimation.cpp index 921d2fa20..275429617 100644 --- a/trinity/Tr2GrannyAnimation.cpp +++ b/trinity/Tr2GrannyAnimation.cpp @@ -1496,6 +1496,11 @@ void Tr2GrannyAnimation::EndAnimation() } +void Tr2GrannyAnimation::StopAnimations( float delay ) +{ + m_baseLayer.StopAnimations( delay ); +} + void Tr2GrannyAnimation::ClearAnimations() { m_baseLayer.ClearAnimations(); diff --git a/trinity/Tr2GrannyAnimation.h b/trinity/Tr2GrannyAnimation.h index 95cd64b52..7b100211f 100644 --- a/trinity/Tr2GrannyAnimation.h +++ b/trinity/Tr2GrannyAnimation.h @@ -76,6 +76,7 @@ BLUE_CLASS( Tr2GrannyAnimation ) : bool PlayAnimation( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone = true ); bool PlayLayerAnimationByName( const char* layer, const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ); void EndAnimation(); + void StopAnimations( float delay ); void ClearAnimations(); float GetAnimationChainCompleteTime(); diff --git a/trinity/Tr2GrannyAnimationLayer.cpp b/trinity/Tr2GrannyAnimationLayer.cpp index 3458c5d6a..ca4713280 100644 --- a/trinity/Tr2GrannyAnimationLayer.cpp +++ b/trinity/Tr2GrannyAnimationLayer.cpp @@ -457,6 +457,41 @@ void Tr2GrannyAnimationLayer::ClearMorphTracks( granny_control* control ) } #endif +void Tr2GrannyAnimationLayer::StopAnimations( float delay ) +{ + m_animationQueue.clear(); + + if( m_sequencer ) + { + const float animationTime = GetLayerAnimationTime(); + m_sequencer->EnumerateAnimations( [&]( const std::shared_ptr& player ) { + player->SetStopTime( animationTime + delay ); + if( delay <= 0.f ) + { + ClearMorphTracks( player.get() ); + } + } ); + m_sequencer->RemoveFinishedAnimations( animationTime ); + } + +#if WITH_GRANNY + if( m_modelInstance ) + { + for( granny_model_control_binding* binding = GrannyModelControlsBegin( m_modelInstance ); binding != GrannyModelControlsEnd( m_modelInstance ); ) + { + granny_control* control = GrannyGetControlFromBinding( binding ); + binding = GrannyModelControlsNext( binding ); + GrannyCompleteControlAt( control, GetLayerAnimationTime() + delay ); + if( GrannyFreeControlIfComplete( control ) ) + { + ClearTextTracks( control ); + ClearMorphTracks( control ); + } + } + } +#endif +} + void Tr2GrannyAnimationLayer::ClearAnimations() { m_animationQueue.clear(); @@ -773,6 +808,7 @@ void Tr2GrannyAnimationLayer::FreeCompletedControls() ClearMorphTracks( player.get() ); } } ); + m_sequencer->RemoveFinishedAnimations( GetLayerAnimationTime() ); } #if WITH_GRANNY diff --git a/trinity/Tr2GrannyAnimationLayer.h b/trinity/Tr2GrannyAnimationLayer.h index a4e902862..b6155f35e 100644 --- a/trinity/Tr2GrannyAnimationLayer.h +++ b/trinity/Tr2GrannyAnimationLayer.h @@ -70,6 +70,7 @@ class Tr2GrannyAnimationLayer bool PlayAnimation( const Tr2GrannyAnimation* grannyAnimation, const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ); void QueueAnimation( const char* animName, bool replace, int loopCount, float delay, float speed, bool clearWhenDone ); void EndAnimation(); + void StopAnimations( float delay ); void ClearAnimations(); float GetAnimationChainCompleteTime(); float GetAnimationRemainingTime(); diff --git a/trinity/Tr2GrannyAnimation_Blue.cpp b/trinity/Tr2GrannyAnimation_Blue.cpp index 35192d6a8..2ae7ab057 100644 --- a/trinity/Tr2GrannyAnimation_Blue.cpp +++ b/trinity/Tr2GrannyAnimation_Blue.cpp @@ -85,6 +85,12 @@ const Be::ClassInfo* Tr2GrannyAnimation::ExposeToBlue() ClearAnimations, "ClearAnimations()\n\n" "Abruptly ends all animations." ) + MAP_METHOD_AND_WRAP( + "StopAnimations", + StopAnimations, + "StopAnimations( delay )\n\n" + "Stops all animations, current and queued.\n" + ":param delay: time (in seconds) from now until playing animations stop" ) MAP_METHOD_AND_WRAP( "PlayLayerAnimation", From e338a312ec2b01dcad1a15e35881528635ac92af Mon Sep 17 00:00:00 2001 From: breki Date: Fri, 31 Jul 2026 11:08:15 +0000 Subject: [PATCH 11/23] runtime child init and firingEffectResPath consumption --- trinity/Eve/SpaceObject/Children/EveChildTurret.cpp | 10 ++++++++++ .../Eve/SpaceObject/Children/EveChildTurret_Blue.cpp | 2 +- trinity/Eve/SpaceObject/EveSpaceObject2.cpp | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 1dbc16981..0cf31035b 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -68,6 +68,12 @@ bool EveChildTurret::Initialize() // pass down some user-defined data into submodules we don't save out. m_target->SetImpactBehaviour( m_impactSize, m_impactBehaviour ); + // an inline-authored firingEffect wins over the res path at load time + if( !m_firingEffect && !m_firingEffectResPath.empty() ) + { + SetFiringEffect( BeResMan->LoadObject( m_firingEffectResPath.c_str() ).p ); + } + return EveChildMesh::Initialize(); } bool EveChildTurret::OnModified( Be::Var* value ) @@ -76,6 +82,10 @@ bool EveChildTurret::OnModified( Be::Var* value ) { m_target->SetImpactBehaviour( m_impactSize, m_impactBehaviour ); } + if( IsMatch( value, m_firingEffectResPath ) && !m_firingEffectResPath.empty() ) + { + SetFiringEffect( BeResMan->LoadObject( m_firingEffectResPath.c_str() ).p ); + } return EveChildMesh::OnModified( value ); } void EveChildTurret::RegisterComponents() diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index 0d36c6501..ed17ee659 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -41,7 +41,7 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() MAP_ATTRIBUTE( "firingEffect", m_firingEffect, "", Be::HIDDEN ) // Needed to make Graphite able to detect bindings inside of the firing effect. MAP_PROPERTY( "firingEffect", GetFiringEffect, SetFiringEffect, "The module for the firing effect of this turret" ) - MAP_ATTRIBUTE( "firingEffectResPath", m_firingEffectResPath, "A res path to the redfile containing the primary firing effect", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "firingEffectResPath", m_firingEffectResPath, "A res path to the redfile containing the primary firing effect", Be::READWRITE | Be::PERSIST | Be::NOTIFY ) MAP_ATTRIBUTE( "impactSize", m_impactSize, "Size of impacts. No impact if size is 0 or less", Be::READWRITE | Be::NOTIFY | Be::PERSIST ) MAP_ATTRIBUTE_WITH_CHOOSER( "impactBehaviour", m_impactBehaviour, "What do we want to hit? ", Be::READWRITE | Be::NOTIFY | Be::PERSIST | Be::ENUM, ImpactBehaviourChooser ) diff --git a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp index c580579b1..0de7cd154 100644 --- a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp +++ b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp @@ -307,6 +307,11 @@ void EveSpaceObject2::OnListModified( long event, ssize_t key, ssize_t key2, IRo switch( event & BELIST_EVENTMASK ) { case BELIST_INSERTED: + // children inserted at runtime never go through the loader's initialize pass + if( IInitializePtr init = BlueCastPtr( value ) ) + { + init->Initialize(); + } if( IEveSpaceObjectChildPtr child = BlueCastPtr( value ) ) { for( auto it = begin( m_controllerVariables ); it != end( m_controllerVariables ); ++it ) From 3b3bd27158f6bdc9f845acc1fa4a40705de40ae4 Mon Sep 17 00:00:00 2001 From: breki Date: Tue, 4 Aug 2026 14:05:38 +0000 Subject: [PATCH 12/23] remove animation clearing fix --- trinity/Tr2GrannyAnimationLayer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/trinity/Tr2GrannyAnimationLayer.cpp b/trinity/Tr2GrannyAnimationLayer.cpp index ca4713280..5833eb006 100644 --- a/trinity/Tr2GrannyAnimationLayer.cpp +++ b/trinity/Tr2GrannyAnimationLayer.cpp @@ -808,7 +808,6 @@ void Tr2GrannyAnimationLayer::FreeCompletedControls() ClearMorphTracks( player.get() ); } } ); - m_sequencer->RemoveFinishedAnimations( GetLayerAnimationTime() ); } #if WITH_GRANNY From 889e172b95b3f3d5bbefd944a2a8c47ab90a513d Mon Sep 17 00:00:00 2001 From: breki Date: Tue, 4 Aug 2026 14:50:38 +0000 Subject: [PATCH 13/23] revert initalization and stopanimation --- trinity/Eve/SpaceObject/Children/EveChildTurret.cpp | 8 -------- trinity/Eve/SpaceObject/Children/EveChildTurret.h | 1 - trinity/Eve/SpaceObject/EveSpaceObject2.cpp | 5 ----- 3 files changed, 14 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 0cf31035b..22dfa6c94 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -902,14 +902,6 @@ float EveChildTurret::PlayAnimation( const std::string& animName, const std::str return animLength; } -void EveChildTurret::StopAnimation( float delay ) -{ - if( m_animationUpdater ) - { - m_animationUpdater->StopAnimations( delay ); - } -} - std::string EveChildTurret::GetFireAnimationName() const { // if m_currentCyclingFiresPos is 0, it's just "Fire" diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index 033b9c925..9a920b5f4 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -108,7 +108,6 @@ BLUE_CLASS( EveChildTurret ) : // animation float PlayAnimation( const std::string& animName, const std::string& animNameIdle, float delay = 0.f ); - void StopAnimation( float delay = 0.f ); std::string GetFireAnimationName() const; EveTurretFiringFX* GetFiringEffect(); diff --git a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp index 0de7cd154..c580579b1 100644 --- a/trinity/Eve/SpaceObject/EveSpaceObject2.cpp +++ b/trinity/Eve/SpaceObject/EveSpaceObject2.cpp @@ -307,11 +307,6 @@ void EveSpaceObject2::OnListModified( long event, ssize_t key, ssize_t key2, IRo switch( event & BELIST_EVENTMASK ) { case BELIST_INSERTED: - // children inserted at runtime never go through the loader's initialize pass - if( IInitializePtr init = BlueCastPtr( value ) ) - { - init->Initialize(); - } if( IEveSpaceObjectChildPtr child = BlueCastPtr( value ) ) { for( auto it = begin( m_controllerVariables ); it != end( m_controllerVariables ); ++it ) From 170bdddaae89e43a5e7d3340b59c938bfd89c139 Mon Sep 17 00:00:00 2001 From: breki Date: Wed, 5 Aug 2026 09:16:51 +0000 Subject: [PATCH 14/23] workaround because clang formatter is being weird --- trinity/Tr2GrannyAnimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trinity/Tr2GrannyAnimation.cpp b/trinity/Tr2GrannyAnimation.cpp index 275429617..04adc45bb 100644 --- a/trinity/Tr2GrannyAnimation.cpp +++ b/trinity/Tr2GrannyAnimation.cpp @@ -2457,7 +2457,7 @@ std::pair Tr2AnimationMeshBinding::GetBoneTransforms() { GrannyColumnMatrixMultiply4x3Transpose( (granny_real32*)( (granny_matrix_3x4*)m_boneTransforms.get() )[i], - (granny_real32*)m_meshSkeleton -> Bones[meshToBone[i]].InverseWorld4x4, + (granny_real32*)( m_meshSkeleton->Bones[meshToBone[i]].InverseWorld4x4 ), (granny_real32*)GrannyGetWorldPose4x4( m_animation->m_worldPose, animBones[i] ) ); } } From 352c2f7fcd5400954fc8c92bdeee4684d1728d7d Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Wed, 12 Aug 2026 12:20:09 +0100 Subject: [PATCH 15/23] Fixed animation rotation snapping to default position on animation stop --- trinity/Tr2GrannyAnimation.cpp | 8 ++++++++ trinity/Tr2GrannyAnimation.h | 1 + 2 files changed, 9 insertions(+) diff --git a/trinity/Tr2GrannyAnimation.cpp b/trinity/Tr2GrannyAnimation.cpp index 04adc45bb..196e79ca1 100644 --- a/trinity/Tr2GrannyAnimation.cpp +++ b/trinity/Tr2GrannyAnimation.cpp @@ -1690,6 +1690,13 @@ void Tr2GrannyAnimation::PrePhysicsAnimation( Be::Time time, const Matrix& model m_morphAnimations.clear(); + // sampling only writes bones referenced by active animations, so restore the + // sampled pose first or the pose modifier compounds onto its own output + if( m_poseModifier && m_sampledPose.skeleton == m_pose.skeleton && m_sampledPose.boneTransforms.size() == m_pose.boneTransforms.size() ) + { + m_pose = m_sampledPose; + } + m_baseLayer.SampleAnimation( animationTime, &m_pose, m_eventListener, m_morphAnimations ); for( auto& [_, layer] : m_animationLayers ) { @@ -1700,6 +1707,7 @@ void Tr2GrannyAnimation::PrePhysicsAnimation( Be::Time time, const Matrix& model if( m_poseModifier ) { + m_sampledPose = m_pose; m_poseModifier->ModifyPose( skeleton, m_pose ); } diff --git a/trinity/Tr2GrannyAnimation.h b/trinity/Tr2GrannyAnimation.h index 7b100211f..1cd15b2aa 100644 --- a/trinity/Tr2GrannyAnimation.h +++ b/trinity/Tr2GrannyAnimation.h @@ -197,6 +197,7 @@ BLUE_CLASS( Tr2GrannyAnimation ) : #endif cmf::SkeletonPose m_pose; cmf::SkeletonPose m_tmpPose; + cmf::SkeletonPose m_sampledPose; std::vector m_skeletonBoneIndices; std::vector m_worldTransforms; From 4f4bd84055e3fe7c42b5293a74b2ae0403176057 Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Fri, 14 Aug 2026 15:55:12 +0100 Subject: [PATCH 16/23] Fixed firing effect not spawning on child turret --- .../SpaceObject/Children/EveChildTurret.cpp | 41 +++++++++++++++++++ .../Eve/SpaceObject/Children/EveChildTurret.h | 4 ++ 2 files changed, 45 insertions(+) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index 22dfa6c94..e684a9c0e 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -278,6 +278,47 @@ void EveChildTurret::UpdateAsyncronous( const EveUpdateContext& updateContext, c } } } + +void EveChildTurret::UpdateVisibility( const EveUpdateContext& updateContext, const Matrix& parentTransform, Tr2Lod parentLod ) +{ + EveChildMesh::UpdateVisibility( updateContext, parentTransform, parentLod ); + + if( m_display && m_firingEffect ) + { + m_firingEffect->UpdateVisibility( updateContext ); + } +} + +void EveChildTurret::GetRenderables( std::vector& renderables ) +{ + EveChildMesh::GetRenderables( renderables ); + + if( m_display && m_firingEffect ) + { + m_firingEffect->GetRenderables( renderables ); + } +} + +void EveChildTurret::RegisterWithQuadRenderer( Tr2QuadRenderer& quadRenderer ) +{ + EveChildMesh::RegisterWithQuadRenderer( quadRenderer ); + + if( m_firingEffect ) + { + m_firingEffect->RegisterWithQuadRenderer( quadRenderer ); + } +} + +void EveChildTurret::AddQuadsToQuadRenderer( const TriFrustum& frustum, Tr2QuadRenderer& quadRenderer ) const +{ + EveChildMesh::AddQuadsToQuadRenderer( frustum, quadRenderer ); + + if( m_display && m_firingEffect ) + { + m_firingEffect->AddQuadsToQuadRenderer( frustum, quadRenderer ); + } +} + void EveChildTurret::UpdateCachedGeometryData() { auto* geometryRes = GetGeometryRes(); diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index 9a920b5f4..0a50d41c2 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -32,6 +32,10 @@ BLUE_CLASS( EveChildTurret ) : // EveSpaceObjectChild void UpdateSyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; void UpdateAsyncronous( const EveUpdateContext& updateContext, const EveChildUpdateParams& params ) override; + void UpdateVisibility( const EveUpdateContext& updateContext, const Matrix& parentTransform, Tr2Lod parentLod ) override; + void GetRenderables( std::vector & renderables ) override; + void RegisterWithQuadRenderer( Tr2QuadRenderer & quadRenderer ) override; + void AddQuadsToQuadRenderer( const TriFrustum& frustum, Tr2QuadRenderer& quadRenderer ) const override; void UpdateCachedGeometryData(); void BuildCachedGeometryData( TriGeometryRes & geometryRes ); From daf70957746f1573d9a4876ca555c85a655d0529 Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Mon, 17 Aug 2026 12:50:57 +0100 Subject: [PATCH 17/23] Extracted shared sysbone aiming math into EveTurretAiming --- trinity/CMakeLists.txt | 2 + .../SpaceObject/Children/EveChildTurret.cpp | 163 +------------- .../Eve/SpaceObject/Children/EveChildTurret.h | 47 +--- .../Children/EveChildTurret_Blue.cpp | 22 +- trinity/Eve/Turret/EveTurretAiming.cpp | 182 +++++++++++++++ trinity/Eve/Turret/EveTurretAiming.h | 57 +++++ trinity/Eve/Turret/EveTurretSet.cpp | 210 +----------------- trinity/Eve/Turret/EveTurretSet.h | 47 +--- trinity/Eve/Turret/EveTurretSet_Blue.cpp | 22 +- 9 files changed, 277 insertions(+), 475 deletions(-) create mode 100644 trinity/Eve/Turret/EveTurretAiming.cpp create mode 100644 trinity/Eve/Turret/EveTurretAiming.h diff --git a/trinity/CMakeLists.txt b/trinity/CMakeLists.txt index 3aa2a7b29..e9de64c79 100644 --- a/trinity/CMakeLists.txt +++ b/trinity/CMakeLists.txt @@ -688,6 +688,8 @@ set(_SOURCES Eve/SpaceObjectFactory/EveSOFDNA_Blue.cpp Eve/SpaceObjectFactory/EveSOFUtils.cpp Eve/SpaceObjectFactory/EveSOFUtils.h + Eve/Turret/EveTurretAiming.cpp + Eve/Turret/EveTurretAiming.h Eve/Turret/EveTurretFiringFX.cpp Eve/Turret/EveTurretFiringFX.h Eve/Turret/EveTurretFiringFX_Blue.cpp diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index e684a9c0e..fa534807f 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -8,25 +8,6 @@ #include "TriMath.h" #include "TriObserverLocal.h" -// names of system bones like they are in the cmf file -constexpr const char* s_systemBoneSkeletonNames[] = { - "invalid", // SYSBONE_INVALID - "Sys_Rotation_Arm", // SYSBONE_ROTATION - "Sys_Rotation_Arm01", // SYSBONE_ROTATION1 - "Sys_Rotation_Arm02", // SYSBONE_ROTATION2 - "Sys_CounterRotation", // SYSBONE_COUNTER_ROTATION - "Sys_Pitch_Barrel", // SYSBONE_PITCH - "Sys_Pitch_Barrel1", // SYSBONE_PITCH1 - "Sys_Pitch_Barrel2", // SYSBONE_PITCH2 - "Sys_Height", // SYSBONE_SCALED_HEIGHT - "Sys_Pitch_Arm01", // SYSBONE_SCALED_PITCH01 - "Sys_Pitch_Arm02", // SYSBONE_SCALED_PITCH02 - "Sys_Pitch_Arm03", // SYSBONE_SCALED_PITCH03 - "Sys_Pitch_Arm04", // SYSBONE_SCALED_PITCH04 - "Sys_Pitch_Arm05", // SYSBONE_SCALED_PITCH05 - "Sys_Pitch_Arm06", // SYSBONE_SCALED_PITCH06 -}; - // invalids constexpr unsigned int INVALID_BONE_INDEX = 0xffffffff; constexpr unsigned int INVALID_TURRET_INDEX = 0xffffffff; @@ -342,7 +323,7 @@ void EveChildTurret::BuildCachedGeometryData( TriGeometryRes& geometryRes ) for( int i = 0; i < SYSBONE_MAX; ++i ) { // in case we don't find system bone, ::FindJoint() returns 0xffffffff - m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i] ); + m_systemBoneID[i] = skeletonData->FindJoint( EveTurretAiming::GetSystemBoneName( i ) ); } InitializeFiringEffect(); @@ -749,155 +730,17 @@ void EveChildTurret::ModifyPose( const cmf::Skeleton& skeleton, cmf::SkeletonPos if( m_systemBoneID[bone] < pose.boneTransforms.size() ) { cmf::Transform& boneTransform = pose.boneTransforms[m_systemBoneID[bone]]; - ModifySystemBoneTransform( + m_aiming.ModifySystemBoneTransform( static_cast( bone ), &targetPosOS, nullptr, + m_trackingInfluence, boneTransform.position, boneTransform.rotation ); } } } -void EveChildTurret::ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const -{ - switch( bone ) - { - case SYSBONE_INVALID: - break; - case SYSBONE_ROTATION: - case SYSBONE_ROTATION01: - case SYSBONE_ROTATION02: { - // rotation of turret 360 degrees, alpha is between -pi and pi - float alpha = atan2( target->x, target->z ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - rotation = quat; - } - break; - case SYSBONE_COUNTER_ROTATION: { - // inverse(!!) rotation of turret 360 degress, alpha is between -pi and pi - float alpha = -atan2( target->x, target->z ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - rotation = quat; - } - break; - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: { - CalcTransformForPitchBone( target, XMConvertToRadians( m_sysBonePitchMin ), XMConvertToRadians( m_sysBonePitchMax ), bone, localTransform, rotation ); - } - break; - case SYSBONE_SCALED_HEIGHT: { - // pitch of barrel 90 degrees - Vector3 directionNormal = Normalize( *target ); - float height = TriClamp( directionNormal.y, 0.f, 1.f ); - // never forget do apply influence! - height *= m_trackingInfluence; - // it's a pos extension with a scale - Vector3 pos = Vector3( 0.f, height * m_sysBoneHeight, 0.f ) + position; - position = pos; - } - break; - case SYSBONE_SCALED_PITCH01: - case SYSBONE_SCALED_PITCH02: - case SYSBONE_SCALED_PITCH03: - case SYSBONE_SCALED_PITCH04: - case SYSBONE_SCALED_PITCH05: - case SYSBONE_SCALED_PITCH06: { - CalcTransformForPitchBone( target, 0.f, XMConvertToRadians( m_sysBonePitchMax ), bone, nullptr, rotation ); - } - break; - default: - break; - } -} - -void EveChildTurret::CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const -{ - float pitchOffset = GetBonePitchOffset( boneIndex ); - float pitchFactor = GetBonePitchFactor( boneIndex ); - // pitch of barrel 90 degrees - Vector3 bone_position( 0.f, 0.f, 0.f ); - - if( localTransform ) - { - bone_position = localTransform->GetTranslation(); - } - - Vector3 relTarget = *target - bone_position; - Vector3 dirNrm = Normalize( relTarget ); - float radians = asinf( dirNrm.y ); - - if( localTransform ) - { - Vector3 bone_direction = Normalize( bone_position ); - float d = Dot( bone_direction, *target ); - if( d < Length( bone_position ) ) - { - // Assuming up is enough for now to avoid cross products - radians = TriFloatSign( relTarget.y ) * XM_PI - radians; - } - } - - float alpha = TriClamp( radians, minPitch, maxPitch ); - // modify! - alpha = pitchFactor * alpha + XMConvertToRadians( pitchOffset ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( 0.f, -alpha, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - rotation = quat; -} - -float EveChildTurret::GetBonePitchFactor( unsigned int boneIndex ) const -{ - switch( boneIndex ) - { - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: - return m_sysBonePitchFactor; - case SYSBONE_SCALED_PITCH01: - return m_sysBonePitch01Factor; - case SYSBONE_SCALED_PITCH02: - return m_sysBonePitch02Factor; - case SYSBONE_SCALED_PITCH03: - return m_sysBonePitch03Factor; - default: - return 1.0f; - } -} - -float EveChildTurret::GetBonePitchOffset( unsigned int boneIndex ) const -{ - switch( boneIndex ) - { - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: - return m_sysBonePitchOffset; - case SYSBONE_SCALED_PITCH01: - return m_sysBonePitch01Offset; - case SYSBONE_SCALED_PITCH02: - return m_sysBonePitch02Offset; - case SYSBONE_SCALED_PITCH03: - return m_sysBonePitch03Offset; - default: - return 0.0f; - } -} Matrix EveChildTurret::GetTurretBoneTransform( uint32_t boneID ) const { Matrix matrix = m_worldTransform; diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.h b/trinity/Eve/SpaceObject/Children/EveChildTurret.h index 0a50d41c2..0dbfcbc99 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.h +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.h @@ -5,6 +5,7 @@ #define EveChildTurret_H #include "EveChildMesh.h" +#include "Eve/Turret/EveTurretAiming.h" #include "Eve/Turret/EveTurretTarget.h" #include "Include/ITr2PoseModifier.h" @@ -69,43 +70,11 @@ BLUE_CLASS( EveChildTurret ) : void ModifyPose( const cmf::Skeleton& skeleton, cmf::SkeletonPose& pose ) override; protected: - // system-controlled bones - enum SystemBones - { - SYSBONE_INVALID = 0, - SYSBONE_ROTATION, - SYSBONE_ROTATION01, - SYSBONE_ROTATION02, - SYSBONE_COUNTER_ROTATION, - SYSBONE_PITCH, - SYSBONE_PITCH1, - SYSBONE_PITCH2, - SYSBONE_SCALED_HEIGHT, - SYSBONE_SCALED_PITCH01, - SYSBONE_SCALED_PITCH02, - SYSBONE_SCALED_PITCH03, - SYSBONE_SCALED_PITCH04, - SYSBONE_SCALED_PITCH05, - SYSBONE_SCALED_PITCH06, - SYSBONE_MAX, - }; - // setup the attached firing effect void InitializeFiringEffect(); void InitializeAnimation() override; - // set transform for tracking - void ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const; - - // Calculates the pitch for a bone based on the parameters - void CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const; - - // Returns the correct pitch factor for a specific bone index - float GetBonePitchFactor( unsigned int boneIndex ) const; - // Returns the correct pitch offset for a specific bone index - float GetBonePitchOffset( unsigned int boneIndex ) const; - Matrix GetTurretBoneTransform( uint32_t boneID ) const; TriGeometryRes* GetGeometryRes() const; @@ -147,18 +116,8 @@ BLUE_CLASS( EveChildTurret ) : // system bones unsigned int m_systemBoneID[SYSBONE_MAX]; - // specific system bone values - float m_sysBoneHeight = 1.f; - float m_sysBonePitchOffset = 0.f; - float m_sysBonePitchFactor = 1.f; - float m_sysBonePitchMin = 0.f; - float m_sysBonePitchMax = 90.f; - float m_sysBonePitch01Offset = 0.f; - float m_sysBonePitch01Factor = 1.f; - float m_sysBonePitch02Offset = 0.f; - float m_sysBonePitch02Factor = 1.f; - float m_sysBonePitch03Offset = 0.f; - float m_sysBonePitch03Factor = 1.f; + // sysbone aiming math + tuning (shared with EveTurretSet) + EveTurretAiming m_aiming; // state of turret set State m_state = STATE_IDLE; diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index ed17ee659..158bc6492 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -22,17 +22,17 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() MAP_PROPERTY( "targetObject", GetTargetObject, SetTargetObject, "object this turret will track" ) MAP_ATTRIBUTE( "target", m_target, "Info on the target", Be::READ ) - MAP_ATTRIBUTE( "sysBoneHeight", m_sysBoneHeight, "System bone HEIGHT extension factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchFactor", m_sysBonePitchFactor, "main pitch factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchOffset", m_sysBonePitchOffset, "main pitch offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchMin", m_sysBonePitchMin, "main pitch minimum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchMax", m_sysBonePitchMax, "main pitch maximum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch01Factor", m_sysBonePitch01Factor, "pitch 01 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch01Offset", m_sysBonePitch01Offset, "pitch 01 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch02Factor", m_sysBonePitch02Factor, "pitch 02 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch02Offset", m_sysBonePitch02Offset, "pitch 02 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch03Factor", m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch03Offset", m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBoneHeight", m_aiming.m_sysBoneHeight, "System bone HEIGHT extension factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchFactor", m_aiming.m_sysBonePitchFactor, "main pitch factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchOffset", m_aiming.m_sysBonePitchOffset, "main pitch offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMin", m_aiming.m_sysBonePitchMin, "main pitch minimum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMax", m_aiming.m_sysBonePitchMax, "main pitch maximum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Factor", m_aiming.m_sysBonePitch01Factor, "pitch 01 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Offset", m_aiming.m_sysBonePitch01Offset, "pitch 01 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Factor", m_aiming.m_sysBonePitch02Factor, "pitch 02 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Offset", m_aiming.m_sysBonePitch02Offset, "pitch 02 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Factor", m_aiming.m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Offset", m_aiming.m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "maxCyclingFirePos", m_maxCyclingFirePos, "If greater than one we cycle through the given number of muzzles.", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "cyclingFireGroupCount", m_cyclingFireGroupCount, "The number of muzzles in one cycle group, usually only one.", Be::READWRITE | Be::PERSIST ) diff --git a/trinity/Eve/Turret/EveTurretAiming.cpp b/trinity/Eve/Turret/EveTurretAiming.cpp new file mode 100644 index 000000000..82a114b45 --- /dev/null +++ b/trinity/Eve/Turret/EveTurretAiming.cpp @@ -0,0 +1,182 @@ +// Copyright © 2026 Fenris Creations ehf. + +#include "StdAfx.h" +#include "EveTurretAiming.h" +#include "TriMath.h" + +// names of system bones like they are in the model skeleton +static constexpr const char* s_systemBoneSkeletonNames[] = { + "invalid", // SYSBONE_INVALID + "Sys_Rotation_Arm", // SYSBONE_ROTATION + "Sys_Rotation_Arm01", // SYSBONE_ROTATION1 + "Sys_Rotation_Arm02", // SYSBONE_ROTATION2 + "Sys_CounterRotation", // SYSBONE_COUNTER_ROTATION + "Sys_Pitch_Barrel", // SYSBONE_PITCH + "Sys_Pitch_Barrel1", // SYSBONE_PITCH1 + "Sys_Pitch_Barrel2", // SYSBONE_PITCH2 + "Sys_Height", // SYSBONE_SCALED_HEIGHT + "Sys_Pitch_Arm01", // SYSBONE_SCALED_PITCH01 + "Sys_Pitch_Arm02", // SYSBONE_SCALED_PITCH02 + "Sys_Pitch_Arm03", // SYSBONE_SCALED_PITCH03 + "Sys_Pitch_Arm04", // SYSBONE_SCALED_PITCH04 + "Sys_Pitch_Arm05", // SYSBONE_SCALED_PITCH05 + "Sys_Pitch_Arm06", // SYSBONE_SCALED_PITCH06 +}; + +const char* EveTurretAiming::GetSystemBoneName( unsigned int bone ) +{ + return bone < SYSBONE_MAX ? s_systemBoneSkeletonNames[bone] : s_systemBoneSkeletonNames[SYSBONE_INVALID]; +} + +// -------------------------------------------------------------------------------- +// Description: +// Depending on the type of the system bone, we calculate a new transform for +// it and apply it. All of this is highly "hard-coded", but there are some +// variables in there, so we can customize the tracking to individual turrets. +// The modification should pay attention the amount of modification needed, +// passed in trackingInfluence +// Arguments: +// bone - type of system bone +// target - position of target in "turret"-space +// position - the bone position that needs to get modified +// rotation - the bone rotation that needs to get modified +// -------------------------------------------------------------------------------- +void EveTurretAiming::ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, float trackingInfluence, Vector3& position, Quaternion& rotation ) const +{ + switch( bone ) + { + case SYSBONE_INVALID: + break; + case SYSBONE_ROTATION: + case SYSBONE_ROTATION01: + case SYSBONE_ROTATION02: { + // rotation of turret 360 degrees, alpha is between -pi and pi + float alpha = atan2( target->x, target->z ); + // never forget do apply influence! + alpha *= trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + rotation = quat; + } + break; + case SYSBONE_COUNTER_ROTATION: { + // inverse(!!) rotation of turret 360 degress, alpha is between -pi and pi + float alpha = -atan2( target->x, target->z ); + // never forget do apply influence! + alpha *= trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + rotation = quat; + } + break; + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: { + CalcTransformForPitchBone( target, XMConvertToRadians( m_sysBonePitchMin ), XMConvertToRadians( m_sysBonePitchMax ), bone, localTransform, trackingInfluence, rotation ); + } + break; + case SYSBONE_SCALED_HEIGHT: { + // pitch of barrel 90 degrees + Vector3 directionNormal = Normalize( *target ); + float height = TriClamp( directionNormal.y, 0.f, 1.f ); + // never forget do apply influence! + height *= trackingInfluence; + // it's a pos extension with a scale + Vector3 pos = Vector3( 0.f, height * m_sysBoneHeight, 0.f ) + position; + position = pos; + } + break; + case SYSBONE_SCALED_PITCH01: + case SYSBONE_SCALED_PITCH02: + case SYSBONE_SCALED_PITCH03: + case SYSBONE_SCALED_PITCH04: + case SYSBONE_SCALED_PITCH05: + case SYSBONE_SCALED_PITCH06: { + CalcTransformForPitchBone( target, 0.f, XMConvertToRadians( m_sysBonePitchMax ), bone, nullptr, trackingInfluence, rotation ); + } + break; + default: + break; + } +} + +void EveTurretAiming::CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, float trackingInfluence, Quaternion& rotation ) const +{ + float pitchOffset = GetBonePitchOffset( boneIndex ); + float pitchFactor = GetBonePitchFactor( boneIndex ); + // pitch of barrel 90 degrees + Vector3 bone_position( 0.f, 0.f, 0.f ); + + if( localTransform ) + { + bone_position = localTransform->GetTranslation(); + } + + Vector3 relTarget = *target - bone_position; + Vector3 dirNrm = Normalize( relTarget ); + float radians = asinf( dirNrm.y ); + + if( localTransform ) + { + Vector3 bone_direction = Normalize( bone_position ); + float d = Dot( bone_direction, *target ); + if( d < Length( bone_position ) ) + { + // Assuming up is enough for now to avoid cross products + radians = TriFloatSign( relTarget.y ) * XM_PI - radians; + } + } + + float alpha = TriClamp( radians, minPitch, maxPitch ); + // modify! + alpha = pitchFactor * alpha + XMConvertToRadians( pitchOffset ); + // never forget do apply influence! + alpha *= trackingInfluence; + // 1st: make quaternion + Quaternion quat = RotationQuaternion( 0.f, -alpha, 0.f ); + // 2nd: apply this quat after the original one + quat = rotation * quat; + rotation = quat; +} + +float EveTurretAiming::GetBonePitchFactor( unsigned int boneIndex ) const +{ + switch( boneIndex ) + { + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: + return m_sysBonePitchFactor; + case SYSBONE_SCALED_PITCH01: + return m_sysBonePitch01Factor; + case SYSBONE_SCALED_PITCH02: + return m_sysBonePitch02Factor; + case SYSBONE_SCALED_PITCH03: + return m_sysBonePitch03Factor; + default: + return 1.0f; + } +} + +float EveTurretAiming::GetBonePitchOffset( unsigned int boneIndex ) const +{ + switch( boneIndex ) + { + case SYSBONE_PITCH: + case SYSBONE_PITCH1: + case SYSBONE_PITCH2: + return m_sysBonePitchOffset; + case SYSBONE_SCALED_PITCH01: + return m_sysBonePitch01Offset; + case SYSBONE_SCALED_PITCH02: + return m_sysBonePitch02Offset; + case SYSBONE_SCALED_PITCH03: + return m_sysBonePitch03Offset; + default: + return 0.0f; + } +} diff --git a/trinity/Eve/Turret/EveTurretAiming.h b/trinity/Eve/Turret/EveTurretAiming.h new file mode 100644 index 000000000..f32717dd3 --- /dev/null +++ b/trinity/Eve/Turret/EveTurretAiming.h @@ -0,0 +1,57 @@ +// Copyright © 2026 Fenris Creations ehf. + +#pragma once +#ifndef EveTurretAiming_H +#define EveTurretAiming_H + +// system-controlled bones +enum SystemBones +{ + SYSBONE_INVALID = 0, + SYSBONE_ROTATION, + SYSBONE_ROTATION01, + SYSBONE_ROTATION02, + SYSBONE_COUNTER_ROTATION, + SYSBONE_PITCH, + SYSBONE_PITCH1, + SYSBONE_PITCH2, + SYSBONE_SCALED_HEIGHT, + SYSBONE_SCALED_PITCH01, + SYSBONE_SCALED_PITCH02, + SYSBONE_SCALED_PITCH03, + SYSBONE_SCALED_PITCH04, + SYSBONE_SCALED_PITCH05, + SYSBONE_SCALED_PITCH06, + SYSBONE_MAX, +}; + +// Sysbone aiming math and tuning values shared by EveTurretSet and EveChildTurret. +// Hosts embed this by value and expose the members through their own Blue schema. +class EveTurretAiming +{ +public: + // name of a system bone as authored in the model skeleton + static const char* GetSystemBoneName( unsigned int bone ); + + void ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, float trackingInfluence, Vector3& position, Quaternion& rotation ) const; + + void CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, float trackingInfluence, Quaternion& rotation ) const; + + float GetBonePitchFactor( unsigned int boneIndex ) const; + float GetBonePitchOffset( unsigned int boneIndex ) const; + + // specific system bone values + float m_sysBoneHeight = 1.f; + float m_sysBonePitchOffset = 0.f; + float m_sysBonePitchFactor = 1.f; + float m_sysBonePitchMin = 0.f; + float m_sysBonePitchMax = 90.f; + float m_sysBonePitch01Offset = 0.f; + float m_sysBonePitch01Factor = 1.f; + float m_sysBonePitch02Offset = 0.f; + float m_sysBonePitch02Factor = 1.f; + float m_sysBonePitch03Offset = 0.f; + float m_sysBonePitch03Factor = 1.f; +}; + +#endif diff --git a/trinity/Eve/Turret/EveTurretSet.cpp b/trinity/Eve/Turret/EveTurretSet.cpp index 151c7f0ff..ce57c67cd 100644 --- a/trinity/Eve/Turret/EveTurretSet.cpp +++ b/trinity/Eve/Turret/EveTurretSet.cpp @@ -26,25 +26,6 @@ using namespace Tr2RenderContextEnum; extern bool g_brokenMacOSNvidiaDrivers; -// names of system bones like they are in the granny file -static std::string s_systemBoneSkeletonNames[] = { - "invalid", // SYSBONE_INVALID - "Sys_Rotation_Arm", // SYSBONE_ROTATION - "Sys_Rotation_Arm01", // SYSBONE_ROTATION1 - "Sys_Rotation_Arm02", // SYSBONE_ROTATION2 - "Sys_CounterRotation", // SYSBONE_COUNTER_ROTATION - "Sys_Pitch_Barrel", // SYSBONE_PITCH - "Sys_Pitch_Barrel1", // SYSBONE_PITCH1 - "Sys_Pitch_Barrel2", // SYSBONE_PITCH2 - "Sys_Height", // SYSBONE_SCALED_HEIGHT - "Sys_Pitch_Arm01", // SYSBONE_SCALED_PITCH01 - "Sys_Pitch_Arm02", // SYSBONE_SCALED_PITCH02 - "Sys_Pitch_Arm03", // SYSBONE_SCALED_PITCH03 - "Sys_Pitch_Arm04", // SYSBONE_SCALED_PITCH04 - "Sys_Pitch_Arm05", // SYSBONE_SCALED_PITCH05 - "Sys_Pitch_Arm06", // SYSBONE_SCALED_PITCH06 -}; - // invalids const unsigned int INVALID_BONE_INDEX = 0xffffffff; const unsigned int INVALID_TURRET_INDEX = 0xffffffff; @@ -100,17 +81,6 @@ EveTurretSet::EveTurretSet( IRoot* lockobj ) : m_maxCyclingFirePos( 1 ), m_cyclingFireGroupCount( 1 ), m_currentCyclingFiresPos( 0 ), - m_sysBoneHeight( 1.f ), - m_sysBonePitchOffset( 0.f ), - m_sysBonePitchFactor( 1.f ), - m_sysBonePitchMin( 0.f ), - m_sysBonePitchMax( 90.f ), - m_sysBonePitch01Offset( 0.f ), - m_sysBonePitch01Factor( 1.f ), - m_sysBonePitch02Offset( 0.f ), - m_sysBonePitch02Factor( 1.f ), - m_sysBonePitch03Offset( 0.f ), - m_sysBonePitch03Factor( 1.f ), m_state( STATE_IDLE ), m_activeTurret( INVALID_TURRET_INDEX ), m_recheckTimeLeft( -1.f ), @@ -1073,7 +1043,7 @@ void EveTurretSet::RebuildCachedData( BlueAsyncRes* p ) for( int i = 0; i < SYSBONE_MAX; ++i ) { // in case we don't find system bone, ::FindJoint() returns 0xffffffff - m_systemBoneID[i] = skeletonData->FindJoint( s_systemBoneSkeletonNames[i].c_str() ); + m_systemBoneID[i] = skeletonData->FindJoint( EveTurretAiming::GetSystemBoneName( i ) ); } // try to link an existing firing effect to skeleton's bones @@ -1346,7 +1316,7 @@ void EveTurretSet::UpdateSingleTurrets() } // modify this bone's transform data cmf::Transform& boneTransform = turret.pose.boneTransforms[m_systemBoneID[bone]]; - ModifySystemBoneTransform( (SystemBones)bone, &targetPosOS, localTransformPtr, boneTransform.position, boneTransform.rotation ); + m_aiming.ModifySystemBoneTransform( (SystemBones)bone, &targetPosOS, localTransformPtr, m_trackingInfluence, boneTransform.position, boneTransform.rotation ); } } } @@ -1398,7 +1368,7 @@ void EveTurretSet::UpdateSingleTurrets() { Vector3 position = Vector3( boneTransform->Position[0], boneTransform->Position[1], boneTransform->Position[2] ); Quaternion rotation = *reinterpret_cast( boneTransform->Orientation ); - ModifySystemBoneTransform( (SystemBones)bone, &targetPosOS, localTransformPtr, position, rotation ); + m_aiming.ModifySystemBoneTransform( (SystemBones)bone, &targetPosOS, localTransformPtr, m_trackingInfluence, position, rotation ); GrannySetTransform( boneTransform, &position.x, (float*)&rotation, (float*)boneTransform->ScaleShear ); } } @@ -1626,7 +1596,7 @@ Matrix EveTurretSet::GetTurretBoneTransform( uint32_t closestTurret, uint32_t bo else { // if we don't have a valid pose, position is fine but orientation? depends on launcher settings... - if( m_sysBonePitchMin < 45.f ) + if( m_aiming.m_sysBonePitchMin < 45.f ) { // aiming directly at target, because target cone is large Vector3 nrmToTarget = *m_target->GetTrackingPosition() - m.GetTranslation(); @@ -1682,7 +1652,7 @@ Matrix EveTurretSet::GetTurretBoneTransform( uint32_t closestTurret, uint32_t bo else { // if we don't have a valid granny pose, position is fine but orientation? depends on launcher settings... - if( m_sysBonePitchMin < 45.f ) + if( m_aiming.m_sysBonePitchMin < 45.f ) { // aiming directly at target, because target cone is large Vector3 nrmToTarget = *m_target->GetTrackingPosition() - m.GetTranslation(); @@ -1713,84 +1683,6 @@ Matrix EveTurretSet::GetTurretBoneTransform( uint32_t closestTurret, uint32_t bo #endif } -// -------------------------------------------------------------------------------- -// Description: -// Depending on the type of the system bone, we calculate a new transform for -// it and apply it. All of this is highly "hard-coded", but there are some -// variables in there, so we can customize the tracking to individual turrets. -// The modification should pay attention the amount of modification needed, -// stored in m_trackingInfluence -// Arguments: -// bone - type of system bone -// target - position of target in "turret"-space -// position - the bone position that needs to get modified -// rotation - the bone rotation that needs to get modified -// -------------------------------------------------------------------------------- -void EveTurretSet::ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const -{ - switch( bone ) - { - case SYSBONE_INVALID: - break; - case SYSBONE_ROTATION: - case SYSBONE_ROTATION01: - case SYSBONE_ROTATION02: { - // rotation of turret 360 degrees, alpha is between -pi and pi - float alpha = atan2( target->x, target->z ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - // 3rd: make granny_transform from quat - rotation = quat; - } - break; - case SYSBONE_COUNTER_ROTATION: { - // inverse(!!) rotation of turret 360 degress, alpha is between -pi and pi - float alpha = -1.f * atan2( target->x, target->z ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( alpha, 0.f, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - // 3rd: make granny_transform from quat - rotation = quat; - } - break; - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: { - CalcTransformForPitchBone( target, XMConvertToRadians( m_sysBonePitchMin ), XMConvertToRadians( m_sysBonePitchMax ), bone, localTransform, rotation ); - } - break; - case SYSBONE_SCALED_HEIGHT: { - // pitch of barrel 90 degrees - Vector3 dirNrm = Normalize( *target ); - float height = TriClamp( dirNrm.y, 0.f, 1.f ); - // never forget do apply influence! - height *= m_trackingInfluence; - // it's a pos extension with a scale - Vector3 pos = Vector3( 0.f, height * m_sysBoneHeight, 0.f ) + position; - position = pos; - } - break; - case SYSBONE_SCALED_PITCH01: - case SYSBONE_SCALED_PITCH02: - case SYSBONE_SCALED_PITCH03: - case SYSBONE_SCALED_PITCH04: - case SYSBONE_SCALED_PITCH05: - case SYSBONE_SCALED_PITCH06: { - CalcTransformForPitchBone( target, 0.f, XMConvertToRadians( m_sysBonePitchMax ), bone, nullptr, rotation ); - } - break; - default: - break; - } -} - // -------------------------------------------------------------------------------- // Description: // This sets up a turret on a ship to a give position. The total number of @@ -3766,98 +3658,6 @@ ITriTargetablePtr EveTurretSet::GetTargetObject() return m_target->GetTargetable(); } -// -------------------------------------------------------------------------------- -// Description: -// Calculates the transform for a pitch bone -// -------------------------------------------------------------------------------- -void EveTurretSet::CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const -{ - float pitchOffset = GetBonePitchOffset( boneIndex ); - float pitchFactor = GetBonePitchFactor( boneIndex ); - // pitch of barrel 90 degrees - Vector3 bone_position( 0.f, 0.f, 0.f ); - - if( localTransform ) - { - bone_position = localTransform->GetTranslation(); - } - - Vector3 relTarget = *target - bone_position; - Vector3 dirNrm = Normalize( relTarget ); - float radians = asinf( dirNrm.y ); - - if( localTransform ) - { - Vector3 bone_direction = Normalize( bone_position ); - float d = Dot( bone_direction, *target ); - if( d < Length( bone_position ) ) - { - // Assuming up is enough for now to avoid cross products - radians = TriFloatSign( relTarget.y ) * XM_PI - radians; - } - } - - float alpha = TriClamp( radians, minPitch, maxPitch ); - // modify! - alpha = pitchFactor * alpha + XMConvertToRadians( pitchOffset ); - // never forget do apply influence! - alpha *= m_trackingInfluence; - // 1st: make quaternion - Quaternion quat = RotationQuaternion( 0.f, -alpha, 0.f ); - // 2nd: apply this quat after the original one - quat = rotation * quat; - // 2nd: make granny_transform from quat - rotation = quat; -} - -// -------------------------------------------------------------------------------- -// Description: -// Returns the correct bone pitch factor based on the bone index -// If the bone index does not have a specific bone pitch factor, a default 1.0 is returned -// -------------------------------------------------------------------------------- -float EveTurretSet::GetBonePitchFactor( unsigned int boneIndex ) const -{ - switch( boneIndex ) - { - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: - return m_sysBonePitchFactor; - case SYSBONE_SCALED_PITCH01: - return m_sysBonePitch01Factor; - case SYSBONE_SCALED_PITCH02: - return m_sysBonePitch02Factor; - case SYSBONE_SCALED_PITCH03: - return m_sysBonePitch03Factor; - default: - return 1.0f; - } -} - -// -------------------------------------------------------------------------------- -// Description: -// Returns the correct bone pitch offset based on the bone index -// If the bone index does not have a specific bone pitch offset, a default 0.0 is returned -// -------------------------------------------------------------------------------- -float EveTurretSet::GetBonePitchOffset( unsigned int boneIndex ) const -{ - switch( boneIndex ) - { - case SYSBONE_PITCH: - case SYSBONE_PITCH1: - case SYSBONE_PITCH2: - return m_sysBonePitchOffset; - case SYSBONE_SCALED_PITCH01: - return m_sysBonePitch01Offset; - case SYSBONE_SCALED_PITCH02: - return m_sysBonePitch02Offset; - case SYSBONE_SCALED_PITCH03: - return m_sysBonePitch03Offset; - default: - return 0.0f; - } -} - // -------------------------------------------------------------------------------- void EveTurretSet::RegisterWithQuadRenderer( Tr2QuadRenderer& quadRenderer ) { diff --git a/trinity/Eve/Turret/EveTurretSet.h b/trinity/Eve/Turret/EveTurretSet.h index baa640760..379fe4364 100644 --- a/trinity/Eve/Turret/EveTurretSet.h +++ b/trinity/Eve/Turret/EveTurretSet.h @@ -8,6 +8,7 @@ #include "include/ITriTargetable.h" #include "Tr2ShLightingManager.h" #include "Tr2GrannyAnimation.h" +#include "EveTurretAiming.h" #include "EveTurretTarget.h" #include "Tr2DebugRenderer.h" @@ -254,27 +255,6 @@ BLUE_CLASS( EveTurretSet ) : }; private: - // system-controlled bones - enum SystemBones - { - SYSBONE_INVALID = 0, - SYSBONE_ROTATION, - SYSBONE_ROTATION01, - SYSBONE_ROTATION02, - SYSBONE_COUNTER_ROTATION, - SYSBONE_PITCH, - SYSBONE_PITCH1, - SYSBONE_PITCH2, - SYSBONE_SCALED_HEIGHT, - SYSBONE_SCALED_PITCH01, - SYSBONE_SCALED_PITCH02, - SYSBONE_SCALED_PITCH03, - SYSBONE_SCALED_PITCH04, - SYSBONE_SCALED_PITCH05, - SYSBONE_SCALED_PITCH06, - SYSBONE_MAX, - }; - // geom res load void InitializeGeometryResource(); // instance vertex buffer @@ -296,17 +276,6 @@ BLUE_CLASS( EveTurretSet ) : void UpdateSingleTurrets(); - // set transform for tracking - void ModifySystemBoneTransform( SystemBones bone, const Vector3* target, const Matrix* localTransform, Vector3& position, Quaternion& rotation ) const; - - // Calculates the pitch for a bone based on the parameters - void CalcTransformForPitchBone( const Vector3* target, float minPitch, float maxPitch, unsigned int boneIndex, const Matrix* localTransform, Quaternion& rotation ) const; - - // Returns the correct pitch factor for a specific bone index - float GetBonePitchFactor( unsigned int boneIndex ) const; - // Returns the correct pitch offset for a specific bone index - float GetBonePitchOffset( unsigned int boneIndex ) const; - // animation float PlayAnimation( unsigned int turretIndex, const std::string& animName, const std::string& animNameIdle, float delay = 0.f ); void StopAnimation( unsigned int turretIndex, float delay = 0.f ); @@ -452,18 +421,8 @@ BLUE_CLASS( EveTurretSet ) : // system bones unsigned int m_systemBoneID[SYSBONE_MAX]; - // specific system bone values - float m_sysBoneHeight; - float m_sysBonePitchOffset; - float m_sysBonePitchFactor; - float m_sysBonePitchMin; - float m_sysBonePitchMax; - float m_sysBonePitch01Offset; - float m_sysBonePitch01Factor; - float m_sysBonePitch02Offset; - float m_sysBonePitch02Factor; - float m_sysBonePitch03Offset; - float m_sysBonePitch03Factor; + // sysbone aiming math + tuning (shared with EveChildTurret) + EveTurretAiming m_aiming; Matrix GetTurretBoneTransform( uint32_t closestTurret, uint32_t boneID ) const; diff --git a/trinity/Eve/Turret/EveTurretSet_Blue.cpp b/trinity/Eve/Turret/EveTurretSet_Blue.cpp index fbe2562be..430e3d223 100644 --- a/trinity/Eve/Turret/EveTurretSet_Blue.cpp +++ b/trinity/Eve/Turret/EveTurretSet_Blue.cpp @@ -88,17 +88,17 @@ const Be::ClassInfo* EveTurretSet::ExposeToBlue() MAP_ATTRIBUTE( "cyclingFireGroupCount", m_cyclingFireGroupCount, "The number of muzzles in one cycle group, usually only one.", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "currentCyclingFiresPos", m_currentCyclingFiresPos, "Current muzzle id due to cycling muzzles", Be::READ ) - MAP_ATTRIBUTE( "sysBoneHeight", m_sysBoneHeight, "System bone HEIGHT extension factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchFactor", m_sysBonePitchFactor, "main pitch factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchOffset", m_sysBonePitchOffset, "main pitch offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchMin", m_sysBonePitchMin, "main pitch minimum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitchMax", m_sysBonePitchMax, "main pitch maximum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch01Factor", m_sysBonePitch01Factor, "pitch 01 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch01Offset", m_sysBonePitch01Offset, "pitch 01 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch02Factor", m_sysBonePitch02Factor, "pitch 02 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch02Offset", m_sysBonePitch02Offset, "pitch 02 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch03Factor", m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) - MAP_ATTRIBUTE( "sysBonePitch03Offset", m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBoneHeight", m_aiming.m_sysBoneHeight, "System bone HEIGHT extension factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchFactor", m_aiming.m_sysBonePitchFactor, "main pitch factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchOffset", m_aiming.m_sysBonePitchOffset, "main pitch offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMin", m_aiming.m_sysBonePitchMin, "main pitch minimum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitchMax", m_aiming.m_sysBonePitchMax, "main pitch maximum clamp value, prevents the turret from targeting down too much (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Factor", m_aiming.m_sysBonePitch01Factor, "pitch 01 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch01Offset", m_aiming.m_sysBonePitch01Offset, "pitch 01 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Factor", m_aiming.m_sysBonePitch02Factor, "pitch 02 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch02Offset", m_aiming.m_sysBonePitch02Offset, "pitch 02 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Factor", m_aiming.m_sysBonePitch03Factor, "pitch 03 factor", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sysBonePitch03Offset", m_aiming.m_sysBonePitch03Offset, "pitch 03 offset (in degrees!)", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "firingEffect", m_firingEffect, "", Be::HIDDEN ) // Needed to make Graphite able to detect bindings inside of the firing effect. MAP_PROPERTY( "firingEffect", GetFiringEffect, SetFiringEffect, "The module for the firing effect of this turret" ) From f2f68d1abefd7c46d44d1b7ce3057147349ede46 Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Wed, 19 Aug 2026 11:36:29 +0100 Subject: [PATCH 18/23] Fixed aim snapping when firing starts or stops at a locator --- .../SpaceObject/Children/EveChildTurret.cpp | 1 + trinity/Eve/Turret/EveTurretTarget.cpp | 27 +++++++++++++++++-- trinity/Eve/Turret/EveTurretTarget.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp index fa534807f..f99ba66db 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret.cpp @@ -24,6 +24,7 @@ EveChildTurret::EveChildTurret( IRoot* lockobj ) : } m_target.CreateInstance(); + m_target->SetFadeOnLocatorChange( true ); PrepareResources(); } diff --git a/trinity/Eve/Turret/EveTurretTarget.cpp b/trinity/Eve/Turret/EveTurretTarget.cpp index d3298ced1..23ad70d8f 100644 --- a/trinity/Eve/Turret/EveTurretTarget.cpp +++ b/trinity/Eve/Turret/EveTurretTarget.cpp @@ -21,6 +21,7 @@ EveTurretTarget::EveTurretTarget( IRoot* lockobj ) : m_trackingPosition( 0.f, 0.f, 0.f ), m_positionOld( 0.f, 0.f, 0.f ), m_positionOldInfluence( -1.f ), + m_fadeOnLocatorChange( false ), m_positionMiss( 0.f, 0.f, 0.f ), m_missQueue( "EveTurretTarget::m_missQueue" ), m_lastShotIsMiss( false ), @@ -94,6 +95,15 @@ int EveTurretTarget::GetLocator() const return m_locator; } +// -------------------------------------------------------------------------------- +// Description: +// Smooth the aim over locator changes instead of snapping +// -------------------------------------------------------------------------------- +void EveTurretTarget::SetFadeOnLocatorChange( bool fade ) +{ + m_fadeOnLocatorChange = fade; +} + // -------------------------------------------------------------------------------- // Description: // Start the firing procedure at a given locator @@ -103,6 +113,12 @@ void EveTurretTarget::StartFireAtLocator( int l, float delay, float length, cons // remember this locator m_locator = l; + if( m_fadeOnLocatorChange ) + { + m_positionOld = m_trackingPosition; + m_positionOldInfluence = 1.f; + } + // randomize miss positionm m_randomMissDistanceOffset = TriFloatRandom01(); float u = TriFloatRandom01(), v = TriFloatRandom01(); @@ -147,8 +163,15 @@ void EveTurretTarget::StopFireAtLocator() { // clear out the locator m_locator = -1; - // stopp anyy influence - m_positionOldInfluence = -1.f; + if( m_fadeOnLocatorChange ) + { + m_positionOld = m_trackingPosition; + m_positionOldInfluence = 1.f; + } + else + { + m_positionOldInfluence = -1.f; + } // reset the miss-system m_lastShotIsMiss = false; m_missQueue.clear(); diff --git a/trinity/Eve/Turret/EveTurretTarget.h b/trinity/Eve/Turret/EveTurretTarget.h index 5a1769c0a..94dbad2c5 100644 --- a/trinity/Eve/Turret/EveTurretTarget.h +++ b/trinity/Eve/Turret/EveTurretTarget.h @@ -36,6 +36,7 @@ BLUE_CLASS( EveTurretTarget ) : // access locator int GetLocator() const; + void SetFadeOnLocatorChange( bool fade ); void StartFireAtLocator( int l, float delay, float length, const Vector3* source ); void StopFireAtLocator(); const Vector3* GetTrackingPosition() const; @@ -80,6 +81,7 @@ BLUE_CLASS( EveTurretTarget ) : Vector3 m_targetPosition; Vector3 m_positionOld; float m_positionOldInfluence; + bool m_fadeOnLocatorChange; // hit/miss related data Vector3 m_positionMiss; From a79e4ad35f68c750513775e401b3930b55cfe713 Mon Sep 17 00:00:00 2001 From: Breki Ingibjargarson Date: Thu, 20 Aug 2026 09:19:58 +0000 Subject: [PATCH 19/23] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp index 158bc6492..5631efb4a 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildTurret_Blue.cpp @@ -89,7 +89,7 @@ const Be::ClassInfo* EveChildTurret::ExposeToBlue() MAP_METHOD_AND_WRAP( "GetFiringBoneWorldTransform", GetFiringBoneWorldTransform, - "Returns the world transform matrix of the specfified firing bone in the currently firing turret." + "Returns the world transform matrix of the specified firing bone in the currently firing turret." "\n:param idx: index of the firing bone in the current model." "\n:returns: The world transform matrix." ) From 4e2930b45ebcb37e5f6e291ce5e9c2229ccb0a22 Mon Sep 17 00:00:00 2001 From: Breki Ingibjargarson Date: Thu, 20 Aug 2026 09:36:35 +0000 Subject: [PATCH 20/23] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- trinity/Include/ITr2PoseModifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trinity/Include/ITr2PoseModifier.h b/trinity/Include/ITr2PoseModifier.h index 1d23e3284..500e04a8a 100644 --- a/trinity/Include/ITr2PoseModifier.h +++ b/trinity/Include/ITr2PoseModifier.h @@ -1,4 +1,4 @@ -// Copyright © 2026 Fenris Creations ehf. +// Copyright © 2026 Fenris Creations ehf. #pragma once From 415b91d78d26c768f7b9901270a939c357661c1e Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Thu, 20 Aug 2026 14:29:04 +0100 Subject: [PATCH 21/23] WIP PLAT-9853: direct resource bindings (preliminary, pre-perf-tuning checkpoint) --- .../Children/EveCloudEditableVolume.cpp | 11 +- .../Children/EveCloudEditableVolume.h | 6 +- trinity/ITr2EffectValue.h | 14 +- trinity/Raytracing/Tr2RaytracingGeometry.cpp | 2 +- trinity/Raytracing/Tr2RaytracingManager.cpp | 2 +- .../Parameter/Tr2GeometryBufferParameter.cpp | 26 +- .../Parameter/Tr2GeometryBufferParameter.h | 12 +- .../Parameter/Tr2RuntimeTextureParameter.cpp | 24 +- .../Parameter/Tr2RuntimeTextureParameter.h | 12 +- .../Tr2TextureAnimationParameter.cpp | 19 +- .../Parameter/Tr2TextureAnimationParameter.h | 12 +- .../Shader/Parameter/TriTextureParameter.cpp | 16 +- .../Shader/Parameter/TriTextureParameter.h | 12 +- .../Shader/Parameter/TriVariableParameter.cpp | 21 +- .../Shader/Parameter/TriVariableParameter.h | 12 +- trinity/Shader/Tr2Effect.cpp | 15 +- trinity/Shader/Tr2EffectDescription.cpp | 27 +- trinity/Shader/Tr2EffectDescription.h | 6 +- trinity/Shader/Tr2Material.cpp | 137 +--- trinity/Shader/Tr2Material.h | 21 +- trinity/Sprite2d/Tr2Sprite2dDisplayList.cpp | 4 + trinity/Sprite2d/Tr2Sprite2dDisplayList.h | 2 + trinity/Sprite2d/Tr2Sprite2dScene.cpp | 46 +- trinity/Tr2LightManager.cpp | 2 +- trinity/Tr2VolumetricsRenderer.cpp | 2 +- trinity/TriVariable.cpp | 38 +- trinity/TriVariable.h | 12 +- trinityal/CMakeLists.txt | 25 +- trinityal/dx11/Tr2BufferALDx11.h | 1 - trinityal/dx11/Tr2RenderContextDx11.cpp | 584 +++++++++++++---- trinityal/dx11/Tr2RenderContextDx11.h | 87 ++- trinityal/dx11/Tr2ResourceSetALDx11.cpp | 238 ------- trinityal/dx11/Tr2ResourceSetALDx11.h | 58 -- trinityal/dx11/Tr2SamplerStateALDx11.h | 1 - trinityal/dx11/Tr2ShaderProgramALDx11.h | 2 +- trinityal/dx11/Tr2TextureALDx11.h | 5 - trinityal/dx12/Tr2BufferALDx12.h | 1 - .../dx12/Tr2PrimaryRenderContextDx12.cpp | 2 +- trinityal/dx12/Tr2RenderContextDx12.cpp | 510 +++++++++++++-- trinityal/dx12/Tr2RenderContextDx12.h | 77 ++- trinityal/dx12/Tr2ResourceSetALDx12.cpp | 283 -------- trinityal/dx12/Tr2ResourceSetALDx12.h | 49 -- trinityal/dx12/Tr2SamplerStateALDx12.h | 1 - trinityal/dx12/Tr2ShaderProgramALDx12.h | 3 +- trinityal/dx12/Tr2StreamlineALDx12.h | 1 - trinityal/dx12/Tr2TextureALDx12.cpp | 3 +- trinityal/dx12/Tr2TextureALDx12.h | 2 - trinityal/dx12/upscaling/Tr2XessUpscaling.cpp | 2 +- .../dx12/util/DescriptorStateCacheDx12.cpp | 4 +- .../dx12/util/DescriptorStateCacheDx12.h | 10 +- trinityal/include/Tr2BufferAL.h | 2 - trinityal/include/Tr2RegisterMapAL.h | 28 + trinityal/include/Tr2ResourceSetAL.h | 146 ----- trinityal/include/Tr2RtPipelineStateAL.h | 2 - trinityal/include/Tr2RtShaderTableAL.h | 1 - trinityal/include/Tr2SamplerStateAL.h | 2 - trinityal/include/Tr2ShaderProgramAL.h | 2 - .../include/Tr2StaticResourceBindingsAL.h | 49 ++ trinityal/include/Tr2TextureAL.h | 2 - trinityal/include/TrinityAL.h | 3 +- .../include/upscaling/Tr2Fsr1Upscaling.h | 2 +- trinityal/metal/Tr2RenderContextMetal.h | 24 +- trinityal/metal/Tr2RenderContextMetal.mm | 83 +-- trinityal/metal/Tr2ResourceSetALMetal.h | 56 -- trinityal/metal/Tr2ResourceSetALMetal.mm | 326 ---------- trinityal/metal/Tr2RtPipelineStateALMetal.h | 1 - trinityal/metal/Tr2ShaderALMetal.h | 1 - trinityal/metal/Tr2ShaderProgramALMetal.h | 4 +- trinityal/src/Tr2RegisterMapAL.cpp | 125 ++++ trinityal/src/Tr2ResourceSetAL.cpp | 605 ------------------ trinityal/src/Tr2StaticResourceBindingsAL.cpp | 117 ++++ trinityal/src/upscaling/Tr2Fsr1Upscaling.cpp | 12 +- trinityal/stub/Tr2RenderContextStub.cpp | 42 +- trinityal/stub/Tr2RenderContextStub.h | 12 +- trinityal/stub/Tr2ResourceSetALStub.cpp | 47 -- trinityal/stub/Tr2ResourceSetALStub.h | 29 - trinityal/stub/Tr2ShaderProgramALStub.h | 2 +- trinityal/tests/Compute.cpp | 64 +- trinityal/tests/Raytracing.cpp | 71 +- trinityal/tests/Rendering.cpp | 217 ++----- 80 files changed, 1780 insertions(+), 2759 deletions(-) delete mode 100644 trinityal/dx11/Tr2ResourceSetALDx11.cpp delete mode 100644 trinityal/dx11/Tr2ResourceSetALDx11.h delete mode 100644 trinityal/dx12/Tr2ResourceSetALDx12.cpp delete mode 100644 trinityal/dx12/Tr2ResourceSetALDx12.h create mode 100644 trinityal/include/Tr2RegisterMapAL.h delete mode 100644 trinityal/include/Tr2ResourceSetAL.h create mode 100644 trinityal/include/Tr2StaticResourceBindingsAL.h delete mode 100644 trinityal/metal/Tr2ResourceSetALMetal.h delete mode 100644 trinityal/metal/Tr2ResourceSetALMetal.mm create mode 100644 trinityal/src/Tr2RegisterMapAL.cpp delete mode 100644 trinityal/src/Tr2ResourceSetAL.cpp create mode 100644 trinityal/src/Tr2StaticResourceBindingsAL.cpp delete mode 100644 trinityal/stub/Tr2ResourceSetALStub.cpp delete mode 100644 trinityal/stub/Tr2ResourceSetALStub.h diff --git a/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.cpp b/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.cpp index bbdc52061..2f7c396af 100644 --- a/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.cpp +++ b/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.cpp @@ -412,23 +412,22 @@ void EveCloudVolumeTextureParameter::RebuildEffectHandles( Tr2Shader* effectRes m_isUsedByEffect = true; } -bool EveCloudVolumeTextureParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void EveCloudVolumeTextureParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { TriTextureRes* resource = m_volume ? m_volume->GetTexture() : nullptr; bool isSrgb = ( flags & RESOURCE_FLAG_SRGB ) != 0; auto colorSpace = isSrgb ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; if( Tr2TextureAL* tex = ( resource ? resource->GetTexture() : nullptr ) ) { - - return resourceDesc.SetSrv( stage, registerIndex, *tex, colorSpace ); + renderContext.SetSrv( stage, registerIndex, *tex, colorSpace ); } else { - return resourceDesc.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( Tr2EffectResource::TEXTURE_3D, m_name.c_str() ), colorSpace ); + renderContext.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( Tr2EffectResource::TEXTURE_3D, m_name.c_str() ), colorSpace ); } } diff --git a/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.h b/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.h index 198b75f1e..cfdf6594d 100644 --- a/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.h +++ b/trinity/Eve/SpaceObject/Children/EveCloudEditableVolume.h @@ -155,11 +155,11 @@ BLUE_CLASS( EveCloudVolumeTextureParameter ) : ////////////////////////////////////////////////////////////////////////// // ITriEffectResourceParameter - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; unsigned GetHashValue( unsigned startingHash ) const; private: diff --git a/trinity/ITr2EffectValue.h b/trinity/ITr2EffectValue.h index 929f12c73..b3a31e25b 100644 --- a/trinity/ITr2EffectValue.h +++ b/trinity/ITr2EffectValue.h @@ -33,21 +33,19 @@ BLUE_INTERFACE( ITr2EffectValue ) : { } - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + virtual void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { - return false; } - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + virtual void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { - return false; } virtual void AddUsedTexture( Tr2BindlessResourcesAL & usedTextures ) const diff --git a/trinity/Raytracing/Tr2RaytracingGeometry.cpp b/trinity/Raytracing/Tr2RaytracingGeometry.cpp index 59b448999..8165b443e 100644 --- a/trinity/Raytracing/Tr2RaytracingGeometry.cpp +++ b/trinity/Raytracing/Tr2RaytracingGeometry.cpp @@ -942,8 +942,8 @@ void Tr2RaytracingGeometry::TransformMeshes( Tr2RenderContext& renderContext ) outOffset += lod->m_vertexCount; } } + renderContext.ResetResourceBindings(); #if TRINITY_PLATFORM != TRINITY_DIRECTX12 - renderContext.SetResourceSet( Tr2ResourceSetAL() ); inVbParam->SetGpuBuffer( static_cast( nullptr ) ); outVbParam->SetGpuBuffer( static_cast( nullptr ) ); #endif diff --git a/trinity/Raytracing/Tr2RaytracingManager.cpp b/trinity/Raytracing/Tr2RaytracingManager.cpp index f4efef0fb..b8a6e6048 100644 --- a/trinity/Raytracing/Tr2RaytracingManager.cpp +++ b/trinity/Raytracing/Tr2RaytracingManager.cpp @@ -166,7 +166,7 @@ Tr2GpuResourcePool::Texture Tr2RaytracingManager::RenderShadows( if( m_shadowShaderTable.IsValid() ) { - m_shadowEffect->ApplyMaterialDataForRtState( techniqueIndex, pipelineState, renderContext ); + m_shadowEffect->ApplyMaterialDataForRtState( techniqueIndex, renderContext ); renderContext.SetConstants( m_shadowPerFrameData, Tr2RenderContextEnum::COMPUTE_SHADER, 2 ); diff --git a/trinity/Shader/Parameter/Tr2GeometryBufferParameter.cpp b/trinity/Shader/Parameter/Tr2GeometryBufferParameter.cpp index 1864eadc5..7dbabcef1 100644 --- a/trinity/Shader/Parameter/Tr2GeometryBufferParameter.cpp +++ b/trinity/Shader/Parameter/Tr2GeometryBufferParameter.cpp @@ -101,40 +101,42 @@ void Tr2GeometryBufferParameter::RebuildEffectHandles( Tr2Shader* effectRes ) } // -------------------------------------------------------------------------------------- -bool Tr2GeometryBufferParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2GeometryBufferParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { if( !m_gpuBuffer ) { - return false; + return; } auto buffer = m_gpuBuffer->GetGpuBuffer( m_meshIndex ); if( !buffer ) { - return false; + return; } - return resourceDesc.SetSrv( stage, registerIndex, *buffer ); + renderContext.SetSrv( stage, registerIndex, *buffer ); } // -------------------------------------------------------------------------------------- -bool Tr2GeometryBufferParameter::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2GeometryBufferParameter::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { if( !m_gpuBuffer ) { - return resourceDesc.SetUav( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetUav( stage, registerIndex, Tr2BufferAL() ); + return; } auto buffer = m_gpuBuffer->GetGpuBuffer( m_meshIndex ); if( !buffer ) { - return resourceDesc.SetUav( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetUav( stage, registerIndex, Tr2BufferAL() ); + return; } - return resourceDesc.SetUav( stage, registerIndex, *buffer ); + renderContext.SetUav( stage, registerIndex, *buffer ); } // -------------------------------------------------------------------------------------- diff --git a/trinity/Shader/Parameter/Tr2GeometryBufferParameter.h b/trinity/Shader/Parameter/Tr2GeometryBufferParameter.h index fa8cc2512..b022f08da 100644 --- a/trinity/Shader/Parameter/Tr2GeometryBufferParameter.h +++ b/trinity/Shader/Parameter/Tr2GeometryBufferParameter.h @@ -31,15 +31,15 @@ BLUE_CLASS( Tr2GeometryBufferParameter ) : ////////////////////////////////////////////////////////////////////////// // ITriEffectResourceParameter - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; ///////////////////////////////////////////////////////////////////////////////////// // INotify diff --git a/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.cpp b/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.cpp index a37dd7903..85fe22058 100644 --- a/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.cpp +++ b/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.cpp @@ -20,44 +20,44 @@ bool Tr2RuntimeTextureParameter::OnModified( Be::Var* value ) { for( auto it = begin( m_materials ); it != end( m_materials ); ++it ) { - ( *it )->InvalidateResourceSets(); + ( *it )->ResourceChanged(); } } return true; } // -------------------------------------------------------------------------------------- -bool Tr2RuntimeTextureParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2RuntimeTextureParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { bool isSrgb = ( flags & RESOURCE_FLAG_SRGB ) != 0; auto colorSpace = isSrgb ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; if( Tr2TextureAL* tex = ( m_texture ? m_texture->GetTexture() : nullptr ) ) { - return resourceDesc.SetSrv( stage, registerIndex, *tex, colorSpace ); + renderContext.SetSrv( stage, registerIndex, *tex, colorSpace ); } else { - return resourceDesc.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( m_resourceType, m_name.c_str() ), colorSpace ); + renderContext.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( m_resourceType, m_name.c_str() ), colorSpace ); } } // -------------------------------------------------------------------------------------- -bool Tr2RuntimeTextureParameter::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2RuntimeTextureParameter::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { if( Tr2TextureAL* tex = ( m_texture ? m_texture->GetTexture() : nullptr ) ) { - return resourceDesc.SetUav( stage, registerIndex, *tex, m_uavMipLevel ); + renderContext.SetUav( stage, registerIndex, *tex, m_uavMipLevel ); } else { - return resourceDesc.SetUav( stage, registerIndex, Tr2TextureAL() ); + renderContext.SetUav( stage, registerIndex, Tr2TextureAL() ); } } @@ -116,7 +116,7 @@ void Tr2RuntimeTextureParameter::SetTextureProvider( ITr2TextureProvider* textur m_texture = texture; for( auto it = begin( m_materials ); it != end( m_materials ); ++it ) { - ( *it )->InvalidateResourceSets(); + ( *it )->ResourceChanged(); } } diff --git a/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.h b/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.h index 3d0541597..78150bb51 100644 --- a/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.h +++ b/trinity/Shader/Parameter/Tr2RuntimeTextureParameter.h @@ -16,15 +16,15 @@ BLUE_CLASS( Tr2RuntimeTextureParameter ) : bool OnModified( Be::Var * value ) override; - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; void AddUsedTexture( Tr2BindlessResourcesAL & usedTextures ) const override; virtual const char* GetParameterName() const; virtual void RebuildEffectHandles( Tr2Shader * effectRes ); diff --git a/trinity/Shader/Parameter/Tr2TextureAnimationParameter.cpp b/trinity/Shader/Parameter/Tr2TextureAnimationParameter.cpp index 0a535de06..1c542305a 100644 --- a/trinity/Shader/Parameter/Tr2TextureAnimationParameter.cpp +++ b/trinity/Shader/Parameter/Tr2TextureAnimationParameter.cpp @@ -19,36 +19,35 @@ bool Tr2TextureAnimationParameter::OnModified( Be::Var* value ) { for( auto it = begin( m_materials ); it != end( m_materials ); ++it ) { - ( *it )->InvalidateResourceSets(); + ( *it )->ResourceChanged(); } } return true; } -bool Tr2TextureAnimationParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2TextureAnimationParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { bool isSrgb = ( flags & RESOURCE_FLAG_SRGB ) != 0; auto colorSpace = isSrgb ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; if( m_animation ) { - return resourceDesc.SetSrv( stage, registerIndex, m_animation->GetTexture( m_channel ), colorSpace ); + renderContext.SetSrv( stage, registerIndex, m_animation->GetTexture( m_channel ), colorSpace ); } else { - return resourceDesc.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( m_resourceType, m_name.c_str() ), colorSpace ); + renderContext.SetSrv( stage, registerIndex, Tr2Renderer::GetFallbackTexture( m_resourceType, m_name.c_str() ), colorSpace ); } } -bool Tr2TextureAnimationParameter::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void Tr2TextureAnimationParameter::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { - return false; } const char* Tr2TextureAnimationParameter::GetParameterName() const diff --git a/trinity/Shader/Parameter/Tr2TextureAnimationParameter.h b/trinity/Shader/Parameter/Tr2TextureAnimationParameter.h index e03b5ef32..834482fd4 100644 --- a/trinity/Shader/Parameter/Tr2TextureAnimationParameter.h +++ b/trinity/Shader/Parameter/Tr2TextureAnimationParameter.h @@ -17,15 +17,15 @@ BLUE_CLASS( Tr2TextureAnimationParameter ) : bool OnModified( Be::Var * value ) override; - bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const override; - bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const override; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; const char* GetParameterName() const override; void RebuildEffectHandles( Tr2Shader * effectRes ) override; unsigned GetHashValue( unsigned startingHash ) const override; diff --git a/trinity/Shader/Parameter/TriTextureParameter.cpp b/trinity/Shader/Parameter/TriTextureParameter.cpp index b913d4beb..15a207043 100644 --- a/trinity/Shader/Parameter/TriTextureParameter.cpp +++ b/trinity/Shader/Parameter/TriTextureParameter.cpp @@ -174,24 +174,24 @@ void TriTextureParameter::AddUsedTexture( Tr2BindlessResourcesAL& usedTextures ) } // -------------------------------------------------------------------------------------- -bool TriTextureParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriTextureParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { bool isSrgb = ( flags & RESOURCE_FLAG_SRGB ) != 0; auto colorSpace = isSrgb ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; - return resourceDesc.SetSrv( stage, registerIndex, m_cachedTexture, colorSpace ); + renderContext.SetSrv( stage, registerIndex, m_cachedTexture, colorSpace ); } // -------------------------------------------------------------------------------------- -bool TriTextureParameter::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriTextureParameter::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { - return resourceDesc.SetUav( stage, registerIndex, m_cachedTexture, m_uavMipLevel ); + renderContext.SetUav( stage, registerIndex, m_cachedTexture, m_uavMipLevel ); } // --------------------------------------------------------------- diff --git a/trinity/Shader/Parameter/TriTextureParameter.h b/trinity/Shader/Parameter/TriTextureParameter.h index 2810e4b0b..5d147e932 100644 --- a/trinity/Shader/Parameter/TriTextureParameter.h +++ b/trinity/Shader/Parameter/TriTextureParameter.h @@ -39,15 +39,15 @@ BLUE_CLASS( TriTextureParameter ) : unsigned char* destHandle, size_t size, Tr2RenderContext& renderContext ) const override; - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; void AddUsedTexture( Tr2BindlessResourcesAL & usedTextures ) const override; unsigned GetHashValue( unsigned startingHash ) const; bool SupportsDirtyNotification() const override; diff --git a/trinity/Shader/Parameter/TriVariableParameter.cpp b/trinity/Shader/Parameter/TriVariableParameter.cpp index 31d996368..43c1fd83d 100644 --- a/trinity/Shader/Parameter/TriVariableParameter.cpp +++ b/trinity/Shader/Parameter/TriVariableParameter.cpp @@ -56,30 +56,31 @@ bool TriVariableParameter::Initialize() } // --------------------------------------------------------------- -bool TriVariableParameter::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriVariableParameter::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { if( !m_variable ) { - return false; + return; } - return m_variable->CopyToResourceSet( resourceDesc, stage, registerIndex, flags ); + m_variable->UseSRV( stage, registerIndex, flags, renderContext ); } // --------------------------------------------------------------- -bool TriVariableParameter::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriVariableParameter::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { if( m_variable ) { - return m_variable->ApplyUav( resourceDesc, stage, registerIndex ); + m_variable->UseUav( stage, registerIndex, renderContext ); + return; } - return resourceDesc.SetUav( stage, registerIndex, Tr2TextureAL() ); + renderContext.SetUav( stage, registerIndex, Tr2TextureAL() ); } void TriVariableParameter::CopyValueToEffect( Tr2RenderContextEnum::ShaderType inputType, diff --git a/trinity/Shader/Parameter/TriVariableParameter.h b/trinity/Shader/Parameter/TriVariableParameter.h index fd2bfc449..f442c81e3 100644 --- a/trinity/Shader/Parameter/TriVariableParameter.h +++ b/trinity/Shader/Parameter/TriVariableParameter.h @@ -36,15 +36,15 @@ class TriVariableParameter : public ITriEffectParameter, ///////////////////////////////////////////////////////////////////////////////////// // ITriEffectParameter ///////////////////////////////////////////////////////////////////////////////////// - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; virtual void CopyValueToEffect( Tr2RenderContextEnum::ShaderType inputType, unsigned char* destHandle, size_t size, diff --git a/trinity/Shader/Tr2Effect.cpp b/trinity/Shader/Tr2Effect.cpp index ec59b317a..be1bf87cb 100644 --- a/trinity/Shader/Tr2Effect.cpp +++ b/trinity/Shader/Tr2Effect.cpp @@ -620,13 +620,13 @@ void Tr2Effect::RebuildSamplerOverrides() USE_MAIN_THREAD_RENDER_CONTEXT(); - auto UpdateSamplers = [&]( ShaderType shaderType, const Tr2EffectStageInput& stage, Tr2ResourceSetDescriptionAL& resourceSetDesc ) { + auto UpdateSamplers = [&]( ShaderType shaderType, const Tr2EffectStageInput& stage, Tr2StaticResourceBindingsAL& staticBindings ) { bool modified = false; for( auto& samplerOverride : m_samplerOverrides ) { if( auto sampler = FindSamplerByName( stage.samplers, samplerOverride.name.c_str() ) ) { - modified |= resourceSetDesc.SetSampler( shaderType, sampler->first, samplerOverride.sampler ); + modified |= staticBindings.SetSampler( shaderType, sampler->first, samplerOverride.sampler ); } } return modified; @@ -648,7 +648,7 @@ void Tr2Effect::RebuildSamplerOverrides() continue; } - if( UpdateSamplers( ShaderType( i ), stage, pp.m_resourceSetDesc ) ) + if( UpdateSamplers( ShaderType( i ), stage, pp.m_staticBindings ) ) { pp.m_compatibleWithGdr = false; m_compatibleWithGdr = false; @@ -659,7 +659,7 @@ void Tr2Effect::RebuildSamplerOverrides() { auto& pp = *m_parametersForPasses[technique].libraries[passIx]; - UpdateSamplers( Tr2RenderContextEnum::COMPUTE_SHADER, desc.techniques[technique].libraries[passIx].globalInput, pp.m_globalResourceSetDesc ); + UpdateSamplers( Tr2RenderContextEnum::COMPUTE_SHADER, desc.techniques[technique].libraries[passIx].globalInput, pp.m_globalStaticBindings ); } } } @@ -705,9 +705,7 @@ void Tr2Effect::RebuildCachedDataInternal() { m_parametersForPasses[technique].passes[passIx].reset( CCP_NEW( "Tr2EffectPassParameters" ) Tr2EffectPassParameters() ); Tr2EffectPassParameters& pp = *m_parametersForPasses[technique].passes[passIx]; - pp.m_resourceSetDesc = desc.techniques[technique].passes[passIx].resourceSetDesc; - pp.m_resourceSetHash = 0; - pp.m_resourceSetDirty = true; + pp.m_staticBindings = desc.techniques[technique].passes[passIx].staticBindings; pp.m_compatibleWithGdr = true; uint32_t stageCount = 0; @@ -752,8 +750,7 @@ void Tr2Effect::RebuildCachedDataInternal() m_parametersForPasses[technique].libraries[libIx].reset( CCP_NEW( "Tr2EffectLibraryParameters" ) Tr2EffectLibraryParameters() ); auto& lib = *m_parametersForPasses[technique].libraries[libIx]; - lib.m_globalResourceSetDesc = desc.techniques[technique].libraries[libIx].globalResourceSetDesc; - lib.m_globalResourceSetDirty = true; + lib.m_globalStaticBindings = desc.techniques[technique].libraries[libIx].globalStaticBindings; bool compatibleWithGdr = true; //we don't care diff --git a/trinity/Shader/Tr2EffectDescription.cpp b/trinity/Shader/Tr2EffectDescription.cpp index 33b5bf635..9d2545145 100644 --- a/trinity/Shader/Tr2EffectDescription.cpp +++ b/trinity/Shader/Tr2EffectDescription.cpp @@ -516,9 +516,6 @@ bool Tr2EffectDescription::Read( const void* data, Tr2Pass& pass = techniques[technique].passes[passIx]; pass.shaderTypeMask = 0; - std::vector shaderTypes; - std::vector signatures; - for( unsigned stageIx = 0; stageIx != Tr2RenderContextEnum::SHADER_TYPE_COUNT; ++stageIx ) { pass.stageInputs[stageIx].m_exists = false; @@ -614,9 +611,6 @@ bool Tr2EffectDescription::Read( const void* data, return false; } - shaderTypes.push_back( type ); - signatures.push_back( pass.stageInputs[type].signature ); - for( auto& c : pass.stageInputs[type].constants ) { if( c.type != Tr2EffectConstant::UINT || c.dimension != 1 ) @@ -636,14 +630,13 @@ bool Tr2EffectDescription::Read( const void* data, } } - pass.resourceSetDesc = Tr2ResourceSetDescriptionAL( Tr2RegisterMapAL( shaderTypes.data(), signatures.data(), signatures.size() ) ); for( uint32_t stageIx = 0; stageIx < Tr2RenderContextEnum::SHADER_TYPE_COUNT; ++stageIx ) { if( pass.stageInputs[stageIx].m_exists ) { for( auto sampler = begin( pass.stageInputs[stageIx].samplers ); sampler != end( pass.stageInputs[stageIx].samplers ); ++sampler ) { - pass.resourceSetDesc.SetSampler( Tr2RenderContextEnum::ShaderType( stageIx ), sampler->first, sampler->second.sampler ); + pass.staticBindings.SetSampler( Tr2RenderContextEnum::ShaderType( stageIx ), sampler->first, sampler->second.sampler ); } } } @@ -710,10 +703,9 @@ bool Tr2EffectDescription::Read( const void* data, auto shaderType = Tr2RenderContextEnum::COMPUTE_SHADER; ReadRegisters( library.globalInput.signature, stream, version, shaderType ); ReadInput( library.globalInput, stream, version, shaderType, renderContext ); - library.globalResourceSetDesc = Tr2ResourceSetDescriptionAL( Tr2RegisterMapAL( &shaderType, &library.globalInput.signature, 1 ) ); for( auto sampler = begin( library.globalInput.samplers ); sampler != end( library.globalInput.samplers ); ++sampler ) { - library.globalResourceSetDesc.SetSampler( shaderType, sampler->first, sampler->second.sampler ); + library.globalStaticBindings.SetSampler( shaderType, sampler->first, sampler->second.sampler ); } ReadRegisters( library.localInput.signature, stream, version, shaderType ); @@ -764,21 +756,21 @@ bool Tr2EffectDescription::Read( const void* data, { if( IsHeapView( res.second.name ) ) { - library.globalResourceSetDesc.SetSrvHeapView( type, res.first ); + library.globalStaticBindings.SetSrvHeapView( type, res.first ); } } for( auto& res : library.globalInput.uavs ) { if( IsHeapView( res.second.name ) ) { - library.globalResourceSetDesc.SetUavHeapView( type, res.first ); + library.globalStaticBindings.SetUavHeapView( type, res.first ); } } for( auto& res : library.globalInput.samplers ) { if( IsHeapView( res.second.name ) ) { - library.globalResourceSetDesc.SetSamplerHeapView( type, res.first ); + library.globalStaticBindings.SetSamplerHeapView( type, res.first ); } } } @@ -792,26 +784,23 @@ bool Tr2EffectDescription::Read( const void* data, { for( auto& res : stage.resources ) { - auto isHeapView = IsHeapView( res.second.name ); if( IsHeapView( res.second.name ) ) { - pass.resourceSetDesc.SetSrvHeapView( Tr2RenderContextEnum::ShaderType( type ), res.first ); + pass.staticBindings.SetSrvHeapView( Tr2RenderContextEnum::ShaderType( type ), res.first ); } } for( auto& res : stage.uavs ) { - auto isHeapView = IsHeapView( res.second.name ); if( IsHeapView( res.second.name ) ) { - pass.resourceSetDesc.SetUavHeapView( Tr2RenderContextEnum::ShaderType( type ), res.first ); + pass.staticBindings.SetUavHeapView( Tr2RenderContextEnum::ShaderType( type ), res.first ); } } for( auto& sampler : stage.samplers ) { - auto isHeapView = IsHeapView( sampler.second.name ); if( IsHeapView( sampler.second.name ) ) { - pass.resourceSetDesc.SetSamplerHeapView( Tr2RenderContextEnum::ShaderType( type ), sampler.first ); + pass.staticBindings.SetSamplerHeapView( Tr2RenderContextEnum::ShaderType( type ), sampler.first ); } } } diff --git a/trinity/Shader/Tr2EffectDescription.h b/trinity/Shader/Tr2EffectDescription.h index 70f4d789a..532c415c0 100644 --- a/trinity/Shader/Tr2EffectDescription.h +++ b/trinity/Shader/Tr2EffectDescription.h @@ -7,6 +7,8 @@ #include "../Tr2IndirectDrawBuffer.h" +#include <../trinityal/include/Tr2StaticResourceBindingsAL.h> + extern const BlueSharedString DEFAULT_TECHNIQUE; extern const BlueSharedString ANY_TECHNIQUE; @@ -205,7 +207,7 @@ struct Tr2Pass unsigned int renderStates; unsigned int shaderTypeMask; unsigned int shaderProgram; - Tr2ResourceSetDescriptionAL resourceSetDesc; + Tr2StaticResourceBindingsAL staticBindings; #if TRINITY_PLATFORM == TRINITY_DIRECTX12 || TRINITY_PLATFORM == TRINITY_METAL Tr2IndirectDrawBufferLayout indirectLayout; @@ -226,7 +228,7 @@ struct Tr2EffectLibrary Tr2EffectStageInput globalInput; Tr2EffectStageInput localInput; - Tr2ResourceSetDescriptionAL globalResourceSetDesc; + Tr2StaticResourceBindingsAL globalStaticBindings; }; diff --git a/trinity/Shader/Tr2Material.cpp b/trinity/Shader/Tr2Material.cpp index b79f91723..7af042e37 100644 --- a/trinity/Shader/Tr2Material.cpp +++ b/trinity/Shader/Tr2Material.cpp @@ -9,7 +9,6 @@ #include "Include/ITriEffectParameter.h" CCP_STATS_DECLARE( effectCBLocks, "Trinity/effectCBLocks", true, CST_COUNTER_LOW, "number of CB locks for effect parameters" ); -CCP_STATS_DECLARE( effectResourceSetCreated, "Trinity/effectResourceSetCreated", true, CST_COUNTER_LOW, "number of resource sets created" ); Tr2SharedConstantBuffers g_sharedConstantBuffers; @@ -97,7 +96,7 @@ Tr2MaterialStageInput::~Tr2MaterialStageInput() } Tr2EffectLibraryParameters::Tr2EffectLibraryParameters() : - m_globalResourceSetDirty( true ) + m_usedTexturesDirty( true ) { } @@ -118,9 +117,8 @@ void Tr2EffectLibraryParameters::AddReroutable( ITriReroutable* reroutable ) Tr2EffectPassParameters::Tr2EffectPassParameters() : - m_resourceSetDirty( true ), m_compatibleWithGdr( true ), - m_resourceSetHash( 0 ) + m_usedTexturesDirty( true ) { } @@ -197,7 +195,6 @@ void Tr2MaterialStageInput::GetSharedConstantBuffer( const void* contents, uint3 Tr2Material::Tr2Material( IRoot* lockobj ) : - m_resourceSetHash( 0 ), m_compatibleWithGdr( false ) { } @@ -214,43 +211,20 @@ void Tr2Material::ApplyMaterialDataForPass( uint32_t techniqueIndex, unsigned in } unsigned mask = m_shader->GetShaderTypeMask( techniqueIndex ); auto& pp = *m_parametersForPasses[techniqueIndex].passes[passIndex]; - bool descChanged = pp.m_resourceSetDirty; + + renderContext.ResetResourceBindings(); + pp.m_staticBindings.Apply( renderContext ); + for( unsigned i = 0; i != Tr2RenderContextEnum::SHADER_TYPE_COUNT && mask; ++i ) { if( mask & ( 1 << i ) ) { - descChanged |= ApplyShaderInputs( techniqueIndex, passIndex, Tr2RenderContextEnum::ShaderType( i ), renderContext ); + auto& input = pp.m_stageInput[i]; + ApplyConstants( Tr2RenderContextEnum::ShaderType( i ), input, !pp.m_reroutedParameters.empty(), renderContext ); + SetResources( Tr2RenderContextEnum::ShaderType( i ), input, renderContext ); mask &= ~( 1 << i ); } } - - if( descChanged || !pp.m_resourceSet.IsValid() ) - { - USE_MAIN_THREAD_RENDER_CONTEXT(); - - CCP_STATS_INC( effectResourceSetCreated ); - - auto sp = renderContext.m_esm.GetShaderProgram( m_shader->GetEffect().techniques[techniqueIndex].passes[passIndex].shaderProgram ); - if( !sp ) - { - return; - } - pp.m_resourceSet.Create( pp.m_resourceSetDesc, *sp, renderContext ); - pp.m_resourceSetHash = pp.m_resourceSetDesc.ComputeHash(); - pp.m_resourceSetDirty = false; - - m_resourceSetHash = 0; - - for( auto& technique : m_parametersForPasses ) - { - for( auto& params : technique.passes ) - { - m_resourceSetHash = CcpHashFNV1( ¶ms->m_resourceSetHash, sizeof( params->m_resourceSetHash ), m_resourceSetHash ); - } - } - } - - renderContext.SetResourceSet( pp.m_resourceSet ); } void Tr2Material::ApplyMaterialDataForPassWithOverride( uint32_t techniqueIndex, unsigned int passIndex, uint32_t overrideProgram, Tr2RenderContext& renderContext ) const @@ -267,40 +241,19 @@ void Tr2Material::ApplyMaterialDataForPassWithOverride( uint32_t techniqueIndex, unsigned mask = m_shader->GetShaderTypeMask( techniqueIndex ); auto& pp = *m_parametersForPasses[techniqueIndex].passes[passIndex]; - auto resourceSetDesc = Tr2ResourceSetDescriptionAL( *sp ); + + renderContext.ResetResourceBindings(); + for( unsigned i = 0; i != Tr2RenderContextEnum::SHADER_TYPE_COUNT && mask; ++i ) { if( mask & ( 1 << i ) ) { auto& input = pp.m_stageInput[i]; ApplyConstants( Tr2RenderContextEnum::ShaderType( i ), input, !pp.m_reroutedParameters.empty(), renderContext ); - UpdateResourceSetDesc( Tr2RenderContextEnum::ShaderType( i ), input, resourceSetDesc ); + SetResources( Tr2RenderContextEnum::ShaderType( i ), input, renderContext ); mask &= ~( 1 << i ); } } - - CCP_STATS_INC( effectResourceSetCreated ); - - Tr2ResourceSetAL resourceSet; - resourceSet.Create( resourceSetDesc, *sp, renderContext.GetPrimaryRenderContext() ); - renderContext.SetResourceSet( resourceSet ); - - pp.m_resourceSetDirty = true; -} - -bool Tr2Material::ApplyShaderInputs( uint32_t techniqueIndex, unsigned int passIndex, Tr2RenderContextEnum::ShaderType shaderType, Tr2RenderContext& renderContext ) const -{ - auto& pp = *m_parametersForPasses[techniqueIndex].passes[passIndex]; - return ApplyShaderInputs( pp, shaderType, renderContext ); -} - -bool Tr2Material::ApplyShaderInputs( Tr2EffectPassParameters& pp, Tr2RenderContextEnum::ShaderType shaderType, Tr2RenderContext& renderContext ) const -{ - auto& input = pp.m_stageInput[shaderType]; - - ApplyConstants( shaderType, input, !pp.m_reroutedParameters.empty(), renderContext ); - - return UpdateResourceSetDesc( shaderType, input, pp.m_resourceSetDesc ); } void Tr2Material::ApplyConstants( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput& input, bool hasReroutables, Tr2RenderContext& renderContext ) const @@ -349,23 +302,16 @@ void Tr2Material::UpdateConstants( Tr2RenderContextEnum::ShaderType shaderType, } } -bool Tr2Material::UpdateResourceSetDesc( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput& input, Tr2ResourceSetDescriptionAL& desc ) const +void Tr2Material::SetResources( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput& input, Tr2RenderContext& renderContext ) const { - bool descChanged = false; for( auto it = input.m_textures.cbegin(); it != input.m_textures.cend(); ++it ) { - descChanged |= it->m_sourceValue->CopyToResourceSet( desc, shaderType, it->m_registerIndex, ITr2EffectValue::ResourceFlags( it->m_registerCount ) ); + it->m_sourceValue->UseSRV( shaderType, it->m_registerIndex, ITr2EffectValue::ResourceFlags( it->m_registerCount ), renderContext ); } for( auto it = input.m_uavs.cbegin(); it != input.m_uavs.cend(); ++it ) { - descChanged |= it->m_sourceValue->ApplyUav( desc, shaderType, it->m_registerIndex ); + it->m_sourceValue->UseUav( shaderType, it->m_registerIndex, renderContext ); } - return descChanged; -} - -uint64_t Tr2Material::GetSortValue() const -{ - return m_resourceSetHash; } Tr2Shader* Tr2Material::GetShaderStateInterface() const @@ -373,43 +319,12 @@ Tr2Shader* Tr2Material::GetShaderStateInterface() const return m_shader; } -Tr2EffectPassParameters* Tr2Material::GetPassDescription( uint32_t techniqueIndex, uint32_t passIndex ) -{ - return m_parametersForPasses[techniqueIndex].passes[passIndex].get(); -} - -void Tr2Material::InvalidateResourceSets() -{ - for( auto tit = begin( m_parametersForPasses ); tit != end( m_parametersForPasses ); ++tit ) - { - for( auto pit = begin( tit->passes ); pit != end( tit->passes ); ++pit ) - { - auto params = pit->get(); - params->m_resourceSet = Tr2ResourceSetAL(); - params->m_resourceSetDesc.ClearResources(); - params->m_resourceSetHash = 0; - params->m_resourceSetDirty = true; - - params->m_usedTexturesDirty = true; - } - for( auto pit = begin( tit->libraries ); pit != end( tit->libraries ); ++pit ) - { - auto params = pit->get(); - - params->m_usedTexturesDirty = true; - } - } - m_resourceSetHash = 0; -} - void Tr2Material::ResourceChanged() { for( auto& technique : m_parametersForPasses ) { for( auto& pass : technique.passes ) { - pass->m_resourceSetHash = 0; - pass->m_resourceSetDirty = true; pass->m_usedTexturesDirty = true; } for( auto& pass : technique.libraries ) @@ -417,7 +332,6 @@ void Tr2Material::ResourceChanged() pass->m_usedTexturesDirty = true; } } - m_resourceSetHash = 0; } void Tr2Material::MarkConstantBuffersDirty() @@ -446,7 +360,6 @@ void Tr2Material::MarkConstantBuffersDirty() } } } - m_resourceSetHash = 0; } void Tr2Material::UsedWithScreenSize( float screenSize, float worldRadius, const std::vector& uvDensities ) @@ -565,7 +478,7 @@ void Tr2Material::ApplyConstantBuffers( uint32_t techniqueIndex, unsigned int pa } } -void Tr2Material::ApplyMaterialDataForRtState( uint32_t techniqueIndex, const Tr2RtPipelineStateAL& rtPipelineState, Tr2RenderContext& renderContext ) const +void Tr2Material::ApplyMaterialDataForRtState( uint32_t techniqueIndex, Tr2RenderContext& renderContext ) const { if( !m_shader ) { @@ -573,19 +486,11 @@ void Tr2Material::ApplyMaterialDataForRtState( uint32_t techniqueIndex, const Tr } auto& pp = *m_parametersForPasses[techniqueIndex].libraries[0]; - ApplyConstants( Tr2RenderContextEnum::COMPUTE_SHADER, pp.m_globalInput, !pp.m_reroutedParameters.empty(), renderContext ); - - bool descChanged = pp.m_globalResourceSetDirty; - descChanged |= UpdateResourceSetDesc( Tr2RenderContextEnum::COMPUTE_SHADER, pp.m_globalInput, pp.m_globalResourceSetDesc ); + renderContext.ResetResourceBindings(); + pp.m_globalStaticBindings.Apply( renderContext ); - if( descChanged || !pp.m_globalResourceSet.IsValid() ) - { - USE_MAIN_THREAD_RENDER_CONTEXT(); - pp.m_globalResourceSet.Create( pp.m_globalResourceSetDesc, rtPipelineState, renderContext ); - pp.m_globalResourceSetDirty = false; - } - - renderContext.SetResourceSet( pp.m_globalResourceSet ); + ApplyConstants( Tr2RenderContextEnum::COMPUTE_SHADER, pp.m_globalInput, !pp.m_reroutedParameters.empty(), renderContext ); + SetResources( Tr2RenderContextEnum::COMPUTE_SHADER, pp.m_globalInput, renderContext ); } void Tr2Material::ApplyMaterialDataForRtMaterial( uint32_t techniqueIndex, Tr2RtLocalMaterialDescriptionAL& localMaterial, Tr2RenderContext& renderContext ) const diff --git a/trinity/Shader/Tr2Material.h b/trinity/Shader/Tr2Material.h index 7ca7760ec..6010fe668 100644 --- a/trinity/Shader/Tr2Material.h +++ b/trinity/Shader/Tr2Material.h @@ -138,12 +138,9 @@ class Tr2EffectPassParameters : public PassParametersOwner std::vector m_reroutedParameters; - Tr2ResourceSetDescriptionAL m_resourceSetDesc; - Tr2ResourceSetAL m_resourceSet; + Tr2StaticResourceBindingsAL m_staticBindings; std::vector m_usedResources; Tr2BindlessResourcesAL m_usedTextures; - uint32_t m_resourceSetHash; - bool m_resourceSetDirty; bool m_compatibleWithGdr; bool m_usedTexturesDirty; @@ -158,12 +155,10 @@ struct Tr2EffectLibraryParameters : public PassParametersOwner Tr2MaterialStageInput m_localInput; Tr2MaterialStageInput m_globalInput; - Tr2ResourceSetDescriptionAL m_globalResourceSetDesc; - Tr2ResourceSetAL m_globalResourceSet; + Tr2StaticResourceBindingsAL m_globalStaticBindings; std::vector m_reroutedParameters; std::vector m_usedResources; Tr2BindlessResourcesAL m_usedTextures; - bool m_globalResourceSetDirty; bool m_usedTexturesDirty; void AddUsedResource( ITr2EffectValuePtr resource ) override; @@ -211,9 +206,8 @@ BLUE_CLASS( Tr2Material ) : void ApplyMaterialDataForPass( uint32_t techniqueIndex, unsigned int passIndex, Tr2RenderContext& renderContext ) const; void ApplyMaterialDataForPassWithOverride( uint32_t techniqueIndex, unsigned int passIndex, uint32_t overrideProgram, Tr2RenderContext& renderContext ) const; - void ApplyMaterialDataForRtState( uint32_t techniqueIndex, const Tr2RtPipelineStateAL& rtPipelineState, Tr2RenderContext& renderContext ) const; + void ApplyMaterialDataForRtState( uint32_t techniqueIndex, Tr2RenderContext& renderContext ) const; void ApplyMaterialDataForRtMaterial( uint32_t techniqueIndex, Tr2RtLocalMaterialDescriptionAL& localMaterial, Tr2RenderContext& renderContext ) const; - uint64_t GetSortValue() const; Tr2Shader* GetShaderStateInterface() const; @@ -221,9 +215,6 @@ BLUE_CLASS( Tr2Material ) : { } - Tr2EffectPassParameters* GetPassDescription( uint32_t techniqueIndex, uint32_t passIndex ); - - void InvalidateResourceSets(); void ResourceChanged(); void MarkConstantBuffersDirty(); @@ -236,19 +227,15 @@ BLUE_CLASS( Tr2Material ) : void ApplyConstantBuffers( uint32_t techniqueIndex, unsigned int passIndex, Tr2IndirectDrawBufferWriter& indirectBuffer, Tr2RenderContext& renderContext ); protected: - bool ApplyShaderInputs( uint32_t techniqueIndex, unsigned int passIndex, Tr2RenderContextEnum::ShaderType shaderType, Tr2RenderContext& renderContext ) const; - bool ApplyShaderInputs( Tr2EffectPassParameters & pp, Tr2RenderContextEnum::ShaderType shaderType, Tr2RenderContext & renderContext ) const; - void ApplyConstants( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput & input, bool hasReroutables, Tr2RenderContext& renderContext ) const; void UpdateConstants( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput & input, bool hasReroutables, Tr2RenderContext& renderContext ) const; - bool UpdateResourceSetDesc( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput & input, Tr2ResourceSetDescriptionAL & desc ) const; + void SetResources( Tr2RenderContextEnum::ShaderType shaderType, Tr2MaterialStageInput & input, Tr2RenderContext & renderContext ) const; Tr2ShaderPtr m_shader; Tr2EffectTechniqueParametersVector m_parametersForPasses; Tr2EffectTechniqueParametersVector m_parametersForLibraries; std::vector m_lodTextureParameters; - mutable uint32_t m_resourceSetHash; bool m_compatibleWithGdr; }; diff --git a/trinity/Sprite2d/Tr2Sprite2dDisplayList.cpp b/trinity/Sprite2d/Tr2Sprite2dDisplayList.cpp index 3504c0894..013971fd6 100644 --- a/trinity/Sprite2d/Tr2Sprite2dDisplayList.cpp +++ b/trinity/Sprite2d/Tr2Sprite2dDisplayList.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "Tr2Sprite2dDisplayList.h" #include "TriDevice.h" +#include "Tr2AtlasTexture.h" #include "Tr2Renderer.h" using namespace Tr2RenderContextEnum; @@ -65,6 +66,9 @@ void Tr2Sprite2dDisplayList::Entry::SubmitGeometry( Tr2RenderContext& renderCont transposedMatrixes[i] = Transpose( transformArray[i] ); } + renderContext.SetSrv( PIXEL_SHADER, textureRegisters[0], ( texture0 && texture0->GetTexture() ) ? *texture0->GetTexture() : Tr2TextureAL(), colorSpace ); + renderContext.SetSrv( PIXEL_SHADER, textureRegisters[1], ( texture1 && texture1->GetTexture() ) ? *texture1->GetTexture() : Tr2TextureAL(), colorSpace ); + FillAndSetConstants( *m_uiTransformsCb, transposedMatrixes, diff --git a/trinity/Sprite2d/Tr2Sprite2dDisplayList.h b/trinity/Sprite2d/Tr2Sprite2dDisplayList.h index c8799c2f9..6e08e587b 100644 --- a/trinity/Sprite2d/Tr2Sprite2dDisplayList.h +++ b/trinity/Sprite2d/Tr2Sprite2dDisplayList.h @@ -32,6 +32,8 @@ struct Tr2Sprite2dDisplayList : public Tr2DeviceResource Vector4 texelSize1; Tr2AtlasTexturePtr texture0; Tr2AtlasTexturePtr texture1; + uint32_t textureRegisters[2]; + Tr2RenderContextEnum::ColorSpace colorSpace; Tr2EffectPtr effect; //hardcoded due to need for CB slot//Tr2EffectConstant transformsHandle; Matrix transformArray[TR2_SS_MAX_TRANSFORM_COUNT]; diff --git a/trinity/Sprite2d/Tr2Sprite2dScene.cpp b/trinity/Sprite2d/Tr2Sprite2dScene.cpp index 29d9c2f12..09d4a6885 100644 --- a/trinity/Sprite2d/Tr2Sprite2dScene.cpp +++ b/trinity/Sprite2d/Tr2Sprite2dScene.cpp @@ -1125,27 +1125,6 @@ void Tr2Sprite2dScene::IssueDrawCall() } else { - if( auto desc = m_effect->GetPassDescription( 0, 0 ) ) - { - for( uint32_t i = 0; i < 2; ++i ) - { - Tr2TextureAL* texAL = nullptr; - if( m_texture[i] ) - { - texAL = m_texture[i]->GetTexture(); - if( !texAL ) - { - if( m_texture[i]->GetRenderTarget() ) - { - texAL = m_texture[i]->GetRenderTarget(); - } - } - } - auto colorSpace = m_useLinearColorSpace ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; - desc->m_resourceSetDirty |= desc->m_resourceSetDesc.SetSrv( PIXEL_SHADER, m_textureRegisters[i], texAL ? *texAL : Tr2TextureAL(), colorSpace ); - } - } - m_drawCallStartIndex /= sizeof( uint32_t ); renderContext.m_esm.ApplyStreamSource( 0, m_vertexBuffer.GetBuffer(), vertexBufferOffset, sizeof( Tr2Sprite2dD3DVertex ) ); renderContext.m_esm.ApplyIndexBuffer( m_indexBuffer.GetBuffer() ); @@ -1175,6 +1154,24 @@ void Tr2Sprite2dScene::SubmitGeometry( Tr2RenderContext& renderContext ) transposedMatrixes[i] = Transpose( m_transformArray[i] ); } + for( uint32_t i = 0; i < 2; ++i ) + { + Tr2TextureAL* texAL = nullptr; + if( m_texture[i] ) + { + texAL = m_texture[i]->GetTexture(); + if( !texAL ) + { + if( m_texture[i]->GetRenderTarget() ) + { + texAL = m_texture[i]->GetRenderTarget(); + } + } + } + auto colorSpace = m_useLinearColorSpace ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; + renderContext.SetSrv( PIXEL_SHADER, m_textureRegisters[i], texAL ? *texAL : Tr2TextureAL(), colorSpace ); + } + bool result = FillAndSetConstants( m_uiTransformsCb, transposedMatrixes, @@ -2112,10 +2109,9 @@ void Tr2Sprite2dScene::ReplayCapture( Tr2Sprite2dDisplayList* dl ) m_texelSizeVar[0] = entry.texelSize0; m_texelSizeVar[1] = entry.texelSize1; - auto desc = entry.effect->GetPassDescription( 0, 0 ); - auto colorSpace = m_useLinearColorSpace ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; - desc->m_resourceSetDirty |= desc->m_resourceSetDesc.SetSrv( PIXEL_SHADER, m_textureRegisters[0], ( entry.texture0 && entry.texture0->GetTexture() ) ? *entry.texture0->GetTexture() : Tr2TextureAL(), colorSpace ); - desc->m_resourceSetDirty |= desc->m_resourceSetDesc.SetSrv( PIXEL_SHADER, m_textureRegisters[1], ( entry.texture1 && entry.texture1->GetTexture() ) ? *entry.texture1->GetTexture() : Tr2TextureAL(), colorSpace ); + entry.textureRegisters[0] = m_textureRegisters[0]; + entry.textureRegisters[1] = m_textureRegisters[1]; + entry.colorSpace = m_useLinearColorSpace ? Tr2RenderContextEnum::COLOR_SPACE_SRGB : Tr2RenderContextEnum::COLOR_SPACE_LINEAR; CCP_STATS_INC( spriteSceneDrawCallCount ); diff --git a/trinity/Tr2LightManager.cpp b/trinity/Tr2LightManager.cpp index ae20b7c3f..9e8e3a89a 100644 --- a/trinity/Tr2LightManager.cpp +++ b/trinity/Tr2LightManager.cpp @@ -912,7 +912,7 @@ Tr2GpuResourcePool::Texture Tr2LightManager::RenderRaytracedShadows( const uint32_t clearValue[] = { 0, 0, 0, 0 }; renderContext.ClearUav( destTex, 0, clearValue ); - m_Raytracing.m_effect->ApplyMaterialDataForRtState( techniqueIndex, pipelineState, renderContext ); + m_Raytracing.m_effect->ApplyMaterialDataForRtState( techniqueIndex, renderContext ); renderContext.UseAccelerationStructure( geometry->GetTLAS() ); { diff --git a/trinity/Tr2VolumetricsRenderer.cpp b/trinity/Tr2VolumetricsRenderer.cpp index 064451f31..281eddf11 100644 --- a/trinity/Tr2VolumetricsRenderer.cpp +++ b/trinity/Tr2VolumetricsRenderer.cpp @@ -730,7 +730,7 @@ Tr2GpuResourcePool::Texture Tr2VolumetricsRenderer::RenderFog( resources.rtCalculateFroxels->SetParameter( BlueSharedString( "RtFroxelOutputTexture" ), fogFroxels ); resources.rtCalculateFroxels->SetParameter( BlueSharedString( "RtShadowScene" ), raytracingGeometry ); - resources.rtCalculateFroxels->ApplyMaterialDataForRtState( techniqueIndex, pipelineState, renderContext ); + resources.rtCalculateFroxels->ApplyMaterialDataForRtState( techniqueIndex, renderContext ); renderContext.UseAccelerationStructure( raytracingGeometry->GetTLAS() ); { diff --git a/trinity/TriVariable.cpp b/trinity/TriVariable.cpp index 4db1c2902..7870e5ace 100644 --- a/trinity/TriVariable.cpp +++ b/trinity/TriVariable.cpp @@ -22,11 +22,11 @@ const Be::ClassInfo* TriVariable::ExposeToBlue() EXPOSURE_END() } -bool TriVariable::CopyToResourceSet( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriVariable::UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const + ResourceFlags flags, + Tr2RenderContext& renderContext ) const { switch( m_type ) { @@ -39,12 +39,13 @@ bool TriVariable::CopyToResourceSet( } if( tex ) { - return resourceDesc.SetSrv( stage, registerIndex, *tex, colorSpace ); + renderContext.SetSrv( stage, registerIndex, *tex, colorSpace ); } else { - return resourceDesc.SetSrv( stage, registerIndex, Tr2TextureAL(), colorSpace ); + renderContext.SetSrv( stage, registerIndex, Tr2TextureAL(), colorSpace ); } + break; } case TRIVARIABLE_GPUBUFFER: { Tr2BufferAL* buffer = nullptr; @@ -54,22 +55,23 @@ bool TriVariable::CopyToResourceSet( } if( buffer ) { - return resourceDesc.SetSrv( stage, registerIndex, *buffer ); + renderContext.SetSrv( stage, registerIndex, *buffer ); } else { - return resourceDesc.SetSrv( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetSrv( stage, registerIndex, Tr2BufferAL() ); } + break; } default: - return false; + break; } } -bool TriVariable::ApplyUav( - Tr2ResourceSetDescriptionAL& resourceDesc, +void TriVariable::UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const { switch( m_type ) { @@ -81,13 +83,13 @@ bool TriVariable::ApplyUav( } if( tex ) { - return resourceDesc.SetUav( stage, registerIndex, *tex ); + renderContext.SetUav( stage, registerIndex, *tex ); } else { - return resourceDesc.SetUav( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetUav( stage, registerIndex, Tr2BufferAL() ); } - break; + return; } case TRIVARIABLE_GPUBUFFER: { Tr2BufferAL* buffer = nullptr; @@ -97,18 +99,18 @@ bool TriVariable::ApplyUav( } if( buffer ) { - return resourceDesc.SetUav( stage, registerIndex, *buffer ); + renderContext.SetUav( stage, registerIndex, *buffer ); } else { - return resourceDesc.SetUav( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetUav( stage, registerIndex, Tr2BufferAL() ); } - break; + return; } default: break; } - return resourceDesc.SetUav( stage, registerIndex, Tr2BufferAL() ); + renderContext.SetUav( stage, registerIndex, Tr2BufferAL() ); } void TriVariable::CopyValueToEffect( Tr2RenderContextEnum::ShaderType inputType, diff --git a/trinity/TriVariable.h b/trinity/TriVariable.h index aa15f9852..c4d2a3fcd 100644 --- a/trinity/TriVariable.h +++ b/trinity/TriVariable.h @@ -245,15 +245,15 @@ BLUE_CLASS( TriVariable ) : return GetTypeSize(); } - virtual bool CopyToResourceSet( - Tr2ResourceSetDescriptionAL & resourceDesc, + void UseSRV( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, - ResourceFlags flags ) const; - virtual bool ApplyUav( - Tr2ResourceSetDescriptionAL & resourceDesc, + ResourceFlags flags, + Tr2RenderContext& renderContext ) const override; + void UseUav( Tr2RenderContextEnum::ShaderType stage, - uint32_t registerIndex ) const; + uint32_t registerIndex, + Tr2RenderContext& renderContext ) const override; virtual void CopyValueToEffect( Tr2RenderContextEnum::ShaderType inputType, unsigned char* destHandle, diff --git a/trinityal/CMakeLists.txt b/trinityal/CMakeLists.txt index df722a787..2e59ad954 100644 --- a/trinityal/CMakeLists.txt +++ b/trinityal/CMakeLists.txt @@ -29,12 +29,13 @@ set(PUBLIC_AL_HEADER_FILES include/Tr2OcclusionQueryAL.h include/Tr2PipelineStatsQueryAL.h include/Tr2PrimaryRenderContextAL.h + include/Tr2RegisterMapAL.h include/Tr2RenderContextAL.h include/Tr2RenderPassAL.h - include/Tr2ResourceSetAL.h include/Tr2SamplerStateAL.h include/Tr2ShaderAL.h include/Tr2ShaderProgramAL.h + include/Tr2StaticResourceBindingsAL.h include/Tr2SwapChainAL.h include/Tr2TextureAL.h include/Tr2VertexLayoutAL.h @@ -90,8 +91,6 @@ set(_SOURCES dx11/Tr2RenderContextDx11.h dx11/Tr2RenderStateEmulationDx11.cpp dx11/Tr2RenderStateEmulationDx11.h - dx11/Tr2ResourceSetALDx11.cpp - dx11/Tr2ResourceSetALDx11.h dx11/Tr2SamplerStateALDx11.cpp dx11/Tr2SamplerStateALDx11.h dx11/Tr2ShaderALDx11.cpp @@ -129,8 +128,6 @@ set(_SOURCES dx12/Tr2RenderContextDx12.h dx12/Tr2ResourceHelper.cpp dx12/Tr2ResourceHelper.h - dx12/Tr2ResourceSetALDx12.cpp - dx12/Tr2ResourceSetALDx12.h dx12/Tr2RtBottomLevelAccelerationStructureALDx12.cpp dx12/Tr2RtBottomLevelAccelerationStructureALDx12.h dx12/Tr2RtPipelineStateALDx12.cpp @@ -193,13 +190,14 @@ set(_SOURCES include/Tr2RtTopLevelAccelerationStructureAL.h include/Tr2PipelineStatsQueryAL.h include/Tr2PrimaryRenderContextAL.h + include/Tr2RegisterMapAL.h include/Tr2RenderContextAL.h include/Tr2RenderPassAL.h - include/Tr2ResourceSetAL.h include/Tr2SamplerStateAL.h include/Tr2ShaderAL.h - include/Tr2ShaderProgramAL.h - include/Tr2StreamlineAL.h + include/Tr2ShaderProgramAL.h + include/Tr2StaticResourceBindingsAL.h + include/Tr2StreamlineAL.h include/Tr2SwapChainAL.h include/Tr2TextureAL.h include/Tr2VertexLayoutAL.h @@ -239,8 +237,6 @@ set(_SOURCES metal/Tr2PrimaryRenderContextMetal.mm metal/Tr2RenderContextMetal.h metal/Tr2RenderContextMetal.mm - metal/Tr2ResourceSetALMetal.h - metal/Tr2ResourceSetALMetal.mm metal/Tr2RtBottomLevelAccelerationStructureALMetal.mm metal/Tr2RtBottomLevelAccelerationStructureALMetal.h metal/Tr2RtPipelineStateALMetal.mm @@ -273,15 +269,16 @@ set(_SOURCES src/Tr2GpuTimerAl.cpp src/Tr2OcclusionQueryAL.cpp src/Tr2PipelineStatsQueryAL.cpp - src/Tr2ResourceSetAL.cpp + src/Tr2RegisterMapAL.cpp src/Tr2RtBottomLevelAccelerationStructureAL.cpp src/Tr2RtPipelineStateAL.cpp src/Tr2RtShaderTableAL.cpp src/Tr2RtTopLevelAccelerationStructureAL.cpp src/Tr2SamplerStateAL.cpp src/Tr2ShaderAL.cpp - src/Tr2ShaderProgramAL.cpp - src/Tr2StreamlineAL.cpp + src/Tr2ShaderProgramAL.cpp + src/Tr2StaticResourceBindingsAL.cpp + src/Tr2StreamlineAL.cpp src/Tr2SwapChainAL.cpp src/Tr2TextureAL.cpp src/Tr2VertexLayoutAL.cpp @@ -304,8 +301,6 @@ set(_SOURCES stub/Tr2PrimaryRenderContextStub.h stub/Tr2RenderContextStub.cpp stub/Tr2RenderContextStub.h - stub/Tr2ResourceSetALStub.cpp - stub/Tr2ResourceSetALStub.h stub/Tr2SamplerStateALStub.cpp stub/Tr2SamplerStateALStub.h stub/Tr2ShaderALStub.cpp diff --git a/trinityal/dx11/Tr2BufferALDx11.h b/trinityal/dx11/Tr2BufferALDx11.h index 0724f8e33..5cf674400 100644 --- a/trinityal/dx11/Tr2BufferALDx11.h +++ b/trinityal/dx11/Tr2BufferALDx11.h @@ -57,7 +57,6 @@ class Tr2BufferAL : public Tr2DeviceResourceAL friend class Tr2RenderContextAL; friend class Tr2PrimaryRenderContextAL; - friend class Tr2ResourceSetAL; }; } diff --git a/trinityal/dx11/Tr2RenderContextDx11.cpp b/trinityal/dx11/Tr2RenderContextDx11.cpp index 09fa4ea73..d894e5c96 100644 --- a/trinityal/dx11/Tr2RenderContextDx11.cpp +++ b/trinityal/dx11/Tr2RenderContextDx11.cpp @@ -14,7 +14,6 @@ #include "Tr2ShaderALDx11.h" #include "Tr2HalHelperStructures.h" #include "Tr2ShaderProgramALDx11.h" -#include "Tr2ResourceSetALDx11.h" #include "Tr2BufferALDx11.h" #include "Tr2TextureALDx11.h" #include "Tr2ConstantBufferALDx11.h" @@ -763,9 +762,19 @@ struct NullContext : ID3D11DeviceContext #pragma warning( default : 4100 ) Tr2RenderContextAL::Tr2RenderContextAL() throw() : - m_topology( TOP_INVALID ), m_lastSetTopology( TOP_INVALID ), m_renderTargetHighWaterMark( 1 ), m_lastSetVertexLayoutVSHash( 0 ), m_stackDS( "Tr2RenderContextAL::m_stackDS" ), m_useReadOnlyDepthView( false ), m_isDepthReadOnly( false ), m_isSrgbRenderTarget( false ), m_previouslyHadHullShader( false ), m_events( nullptr ), m_aftermathContext( nullptr ), m_assignedUavCount( 0 ), m_assignedUavOffset( 0 ), m_assignedPsUavs( false ) + m_topology( TOP_INVALID ), m_lastSetTopology( TOP_INVALID ), m_renderTargetHighWaterMark( 1 ), m_lastSetVertexLayoutVSHash( 0 ), m_stackDS( "Tr2RenderContextAL::m_stackDS" ), m_useReadOnlyDepthView( false ), m_isDepthReadOnly( false ), m_isSrgbRenderTarget( false ), m_previouslyHadHullShader( false ), m_events( nullptr ), m_aftermathContext( nullptr ), + m_assignedUavOffset( 0 ), m_assignedUavCount( 0 ), m_assignedPsUavs( false ), m_bindingsCommitted( false ), m_bindingsSealed( false ), m_committedProgram( nullptr ) { m_dirtyFlag.mask = 0; + + m_pendingSRVs.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_pendingUAVs.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_pendingSamplers.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + memset( m_boundSrvs, 0, sizeof( m_boundSrvs ) ); + memset( m_boundSamplers, 0, sizeof( m_boundSamplers ) ); m_context.Attach( &Tr2RenderContextImpl::s_nullContext ); static_assert( D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT >= MAX_RENDER_TARGET, @@ -790,9 +799,6 @@ Tr2RenderContextAL::Tr2RenderContextAL() throw() : m_renderStateEmulation.m_currentRasterizer = defaultRasterizer; - std::fill( std::begin( m_samplerHashes ), std::end( m_samplerHashes ), 0 ); - std::fill( std::begin( m_resourceHashes ), std::end( m_resourceHashes ), 0 ); - m_allRenderStates[RS_SRGBWRITEENABLE] = 0; } @@ -825,9 +831,6 @@ void Tr2RenderContextAL::Destroy() throw() } m_secondaryDevice11 = nullptr; - m_assignedUavCount = 0; - m_assignedUavOffset = 0; - m_assignedPsUavs = false; m_secondaryDefaultBackBuffer = Tr2TextureAL(); if( m_aftermathContext ) @@ -882,10 +885,10 @@ void Tr2RenderContextAL::Destroy() throw() m_shaderProgram = Tr2ShaderProgramAL(); + DiscardResourceBindings(); + memset( m_allRenderStates, 0xff, sizeof( m_allRenderStates ) ); m_allRenderStates[RS_SRGBWRITEENABLE] = 0; - std::fill( std::begin( m_samplerHashes ), std::end( m_samplerHashes ), 0 ); - std::fill( std::begin( m_resourceHashes ), std::end( m_resourceHashes ), 0 ); } PixelFormat Tr2RenderContextAL::GetBackBufferFormat() const throw() @@ -897,30 +900,9 @@ PixelFormat Tr2RenderContextAL::GetBackBufferFormat() const throw() ALResult Tr2RenderContextAL::BeginScene() throw() { m_shaderProgram = Tr2ShaderProgramAL(); - std::fill( std::begin( m_samplerHashes ), std::end( m_samplerHashes ), 0 ); - - decltype( &ID3D11DeviceContext::VSSetShaderResources ) setResources[] = { - &ID3D11DeviceContext::VSSetShaderResources, - &ID3D11DeviceContext::PSSetShaderResources, - &ID3D11DeviceContext::CSSetShaderResources, - &ID3D11DeviceContext::GSSetShaderResources, - &ID3D11DeviceContext::HSSetShaderResources, - &ID3D11DeviceContext::DSSetShaderResources, - }; - for( uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i ) - { - ID3D11ShaderResourceView* nullSrv[TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES] = {}; - if( m_resourceHashes[i] ) - { - m_resourceHashes[i] = 0; - ( m_context->*( setResources[i] ) )( - 0, - TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES, - nullSrv ); - } - } - m_currentResourceSet = Tr2ResourceSetAL(); + UnbindShaderResources( true ); + memset( m_boundSamplers, 0, sizeof( m_boundSamplers ) ); return S_OK; } @@ -986,6 +968,7 @@ ALResult Tr2RenderContextAL::DrawIndexedPrimitive( } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawIndexed( vc, startIndex, baseVertexLocation ); return S_OK; @@ -1009,6 +992,7 @@ ALResult Tr2RenderContextAL::DrawIndexedInstanced( } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawIndexedInstanced( vc, numInstances, startIndex, 0, 0 ); return S_OK; @@ -1031,6 +1015,7 @@ ALResult Tr2RenderContextAL::DrawIndexedInstanced( } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawIndexedInstanced( indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation ); return S_OK; @@ -1052,6 +1037,7 @@ ALResult Tr2RenderContextAL::DrawInstanced( } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawInstanced( vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation ); return S_OK; @@ -1070,6 +1056,7 @@ ALResult Tr2RenderContextAL::DrawIndexedInstancedIndirect( Tr2BufferAL& params, } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawIndexedInstancedIndirect( params.m_buffer->m_buffer, offset ); return S_OK; @@ -1087,6 +1074,7 @@ ALResult Tr2RenderContextAL::DrawInstancedIndirect( Tr2BufferAL& params, uint32_ } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->DrawInstancedIndirect( params.m_buffer->m_buffer, offset ); return S_OK; @@ -1106,6 +1094,7 @@ ALResult Tr2RenderContextAL::DrawPrimitive( uint32_t startVertex, uint32_t primi } ApplyReadOnlyDepth(); + UseResourceBindings(); m_context->Draw( vc, startVertex ); return S_OK; @@ -1153,6 +1142,7 @@ ALResult Tr2RenderContextAL::RunComputeShader( unsigned groupDimX, unsigned grou { return E_FAIL; } + UseResourceBindings(); m_context->Dispatch( groupDimX, groupDimY, groupDimZ ); return S_OK; } @@ -1164,6 +1154,7 @@ ALResult Tr2RenderContextAL::RunComputeShaderIndirect( Tr2BufferAL& indirectPara return E_FAIL; } + UseResourceBindings(); m_context->DispatchIndirect( indirectParams.m_buffer->m_buffer, offset ); return S_OK; } @@ -1321,24 +1312,8 @@ ALResult Tr2RenderContextAL::Clear( ALResult Tr2RenderContextAL::SetRtDsToDevice( uint32_t changedSlot ) throw() { - m_currentResourceSet = Tr2ResourceSetAL(); - std::fill( std::begin( m_samplerHashes ), std::end( m_samplerHashes ), 0 ); - std::fill( std::begin( m_resourceHashes ), std::end( m_resourceHashes ), 0 ); - decltype( &ID3D11DeviceContext::VSSetShaderResources ) setResources[] = { - &ID3D11DeviceContext::VSSetShaderResources, - &ID3D11DeviceContext::PSSetShaderResources, - &ID3D11DeviceContext::CSSetShaderResources, - &ID3D11DeviceContext::GSSetShaderResources, - &ID3D11DeviceContext::HSSetShaderResources, - &ID3D11DeviceContext::DSSetShaderResources, - }; - - ID3D11ShaderResourceView* nullViews[16] = { nullptr }; - - for( uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i ) - { - ( m_context->*( setResources[i] ) )( 0, 16, nullViews ); - } + // A texture becoming a render target may still be bound as an SRV from an earlier draw. + UnbindShaderResources( false ); ID3D11RenderTargetView* rtViews[MAX_RENDER_TARGET]; // Follow the DX9 behavior: null means 'default backbuffer' for slot 0, and 'nothing' for everything else. @@ -1601,6 +1576,7 @@ ALResult Tr2RenderContextAL::SetShaderProgram( const Tr2ShaderProgramAL& p ) thr } m_shaderProgram = p; + m_bindingsCommitted = false; return S_OK; } @@ -1974,20 +1950,69 @@ bool Tr2RenderContextAL::ApplyRasterizerState() throw() return true; } -ALResult Tr2RenderContextAL::SetResourceSet( const Tr2ResourceSetAL& resourceSet ) throw() +// -------------------------------------------------------------------------------------- +void Tr2RenderContextAL::BeginResourceBindingBatch() throw() { - if( m_currentResourceSet.m_resourceSet == resourceSet.m_resourceSet ) + if( !m_bindingsSealed ) { - return S_OK; + return; } - m_currentResourceSet = resourceSet; + m_bindingsSealed = false; + m_bindingsCommitted = false; + + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); +} + +// -------------------------------------------------------------------------------------- +void Tr2RenderContextAL::DiscardResourceBindings() throw() +{ + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + memset( m_boundSrvs, 0, sizeof( m_boundSrvs ) ); + memset( m_boundSamplers, 0, sizeof( m_boundSamplers ) ); + m_assignedUavOffset = 0; + m_assignedUavCount = 0; + m_assignedPsUavs = false; - auto& rs = *resourceSet.m_resourceSet; + m_bindingsCommitted = false; + m_bindingsSealed = false; + m_committedProgram = nullptr; +} - if( ( rs.m_empty || !rs.m_uavCount ) && m_assignedUavCount ) +// -------------------------------------------------------------------------------------- +void Tr2RenderContextAL::UnbindShaderResources( bool unbindUavs ) throw() +{ + decltype( &ID3D11DeviceContext::VSSetShaderResources ) setResources[] = { + &ID3D11DeviceContext::VSSetShaderResources, + &ID3D11DeviceContext::PSSetShaderResources, + &ID3D11DeviceContext::CSSetShaderResources, + &ID3D11DeviceContext::GSSetShaderResources, + &ID3D11DeviceContext::HSSetShaderResources, + &ID3D11DeviceContext::DSSetShaderResources, + }; + + ID3D11ShaderResourceView* nullSrvs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + for( uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i ) { - ID3D11UnorderedAccessView* nullUAVs[TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES] = {}; + if( memcmp( m_boundSrvs[i], nullSrvs, sizeof( nullSrvs ) ) != 0 ) + { + ( m_context->*( setResources[i] ) )( 0, Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE, nullSrvs ); + memset( m_boundSrvs[i], 0, sizeof( m_boundSrvs[i] ) ); + } + } + + if( unbindUavs && m_assignedUavCount ) + { + ID3D11UnorderedAccessView* nullUavs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; if( m_assignedPsUavs ) { m_context->OMSetRenderTargetsAndUnorderedAccessViews( @@ -1996,144 +2021,427 @@ ALResult Tr2RenderContextAL::SetResourceSet( const Tr2ResourceSetAL& resourceSet nullptr, m_assignedUavOffset, m_assignedUavCount, - nullUAVs, + nullUavs, nullptr ); } else { - m_context->CSSetUnorderedAccessViews( m_assignedUavOffset, m_assignedUavCount, nullUAVs, nullptr ); + m_context->CSSetUnorderedAccessViews( m_assignedUavOffset, m_assignedUavCount, nullUavs, nullptr ); } m_assignedUavCount = 0; + m_assignedPsUavs = false; + } + + m_bindingsCommitted = false; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.colorSpace = colorSpace; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; } + BeginResourceBindingBatch(); - if( rs.m_empty ) + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.mip = mip; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::HEAP_VIEW; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::SAMPLER; + entry.sampler = sampler; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::ResetResourceBindings() throw() +{ + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + m_bindingsCommitted = false; + m_bindingsSealed = false; + m_committedProgram = nullptr; + return S_OK; +} + +// -------------------------------------------------------------------------------------- +ALResult Tr2RenderContextAL::UseResourceBindings() throw() +{ + if( !m_shaderProgram.IsValid() ) + { + return S_OK; + } + const TrinityALImpl::Tr2ShaderProgramAL& program = *m_shaderProgram.m_program; + if( m_bindingsCommitted && m_committedProgram == &program ) { return S_OK; } - decltype( &ID3D11DeviceContext::VSSetShaderResources ) setResources[] = { - &ID3D11DeviceContext::VSSetShaderResources, - &ID3D11DeviceContext::PSSetShaderResources, - &ID3D11DeviceContext::CSSetShaderResources, - &ID3D11DeviceContext::GSSetShaderResources, - &ID3D11DeviceContext::HSSetShaderResources, - &ID3D11DeviceContext::DSSetShaderResources, - }; + const auto& registerMap = program.m_registerMap; - decltype( &ID3D11DeviceContext::VSSetSamplers ) setSamplers[] = { - &ID3D11DeviceContext::VSSetSamplers, - &ID3D11DeviceContext::PSSetSamplers, - &ID3D11DeviceContext::CSSetSamplers, - &ID3D11DeviceContext::GSSetSamplers, - &ID3D11DeviceContext::HSSetSamplers, - &ID3D11DeviceContext::DSSetSamplers, - }; + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + for( const auto& resource : m_pendingSRVs ) + { + uint32_t index = registerMap.srvs[resource.stage][resource.registerIndex]; + if( index < registerMap.srvCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedSRVs[index] = &resource; + } + } + for( const auto& resource : m_pendingUAVs ) + { + uint32_t index = registerMap.uavs[resource.stage][resource.registerIndex]; + if( index < registerMap.uavCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedUAVs[index] = &resource; + } + } + for( const auto& sampler : m_pendingSamplers ) + { + uint32_t index = registerMap.samplers[sampler.stage][sampler.registerIndex]; + if( index < registerMap.samplerCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedSamplers[index] = &sampler; + } + } - if( rs.m_uavCount ) + ID3D11ShaderResourceView* desiredSrvs[SHADER_TYPE_COUNT][Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + ID3D11SamplerState* desiredSamplers[SHADER_TYPE_COUNT][Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + ID3D11UnorderedAccessView* desiredUavs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + uint32_t uavBegin = Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE; + uint32_t uavEnd = 0; + bool csUavs = false; + + for( uint32_t stageIndex = 0; stageIndex < SHADER_TYPE_COUNT; ++stageIndex ) { - for( uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i ) + for( uint32_t registerIndex = 0; registerIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE; ++registerIndex ) { - ID3D11ShaderResourceView* nullSrv[TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES] = {}; - if( m_resourceHashes[i] ) + uint32_t srvIndex = registerMap.srvs[stageIndex][registerIndex]; + if( srvIndex < registerMap.srvCount ) + { + const Resource* resource = srvIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedSRVs[srvIndex] : nullptr; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::TEXTURE: + if( resource->texture.IsValid() ) + { + desiredSrvs[stageIndex][registerIndex] = resource->texture.m_texture->m_view[resource->colorSpace]; + } + break; + case Resource::BUFFER: + if( resource->buffer.IsValid() ) + { + desiredSrvs[stageIndex][registerIndex] = resource->buffer.m_buffer->m_srv; + } + break; + default: + break; + } + } + + uint32_t samplerIndex = registerMap.samplers[stageIndex][registerIndex]; + if( samplerIndex < registerMap.samplerCount ) { - m_resourceHashes[i] = 0; - ( m_context->*( setResources[i] ) )( - 0, - TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES, - nullSrv ); + const Sampler* sampler = samplerIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedSamplers[samplerIndex] : nullptr; + if( sampler && sampler->type == Sampler::SAMPLER && sampler->sampler.m_sampler ) + { + desiredSamplers[stageIndex][registerIndex] = sampler->sampler.m_sampler->m_samplerState; + } + } + + uint32_t uavIndex = registerMap.uavs[stageIndex][registerIndex]; + if( uavIndex < registerMap.uavCount && + ( stageIndex == PIXEL_SHADER || stageIndex == COMPUTE_SHADER ) ) + { + const Resource* resource = uavIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedUAVs[uavIndex] : nullptr; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::TEXTURE: + if( resource->texture.IsValid() && resource->mip < resource->texture.m_texture->m_uav.size() ) + { + desiredUavs[registerIndex] = resource->texture.m_texture->m_uav[resource->mip]; + } + break; + case Resource::BUFFER: + if( resource->buffer.IsValid() ) + { + desiredUavs[registerIndex] = resource->buffer.m_buffer->m_uav; + } + break; + default: + CCP_AL_LOGWARN( "Missing UAV resource binding for register %u, stage %u", registerIndex, stageIndex ); + break; + } + uavBegin = std::min( uavBegin, registerIndex ); + uavEnd = std::max( uavEnd, registerIndex + 1 ); + csUavs = stageIndex == COMPUTE_SHADER; } } + } - if( rs.m_csUavs ) + const bool haveUavs = uavEnd > uavBegin; + + if( !haveUavs && m_assignedUavCount ) + { + ID3D11UnorderedAccessView* nullUavs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + if( m_assignedPsUavs ) + { + m_context->OMSetRenderTargetsAndUnorderedAccessViews( + D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, + nullptr, + nullptr, + m_assignedUavOffset, + m_assignedUavCount, + nullUavs, + nullptr ); + } + else + { + m_context->CSSetUnorderedAccessViews( m_assignedUavOffset, m_assignedUavCount, nullUavs, nullptr ); + } + m_assignedUavCount = 0; + m_assignedPsUavs = false; + } + + if( haveUavs ) + { + // The resources entering UAV slots may still be bound as SRVs from an earlier draw; + // release every SRV slot first so the runtime doesn't have to force-unbind them. + UnbindShaderResources( false ); + + if( csUavs ) { if( m_assignedUavCount && m_assignedPsUavs ) { - ID3D11UnorderedAccessView* nullUAVs[TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES] = {}; + ID3D11UnorderedAccessView* nullUavs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; m_context->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, m_assignedUavOffset, m_assignedUavCount, - nullUAVs, + nullUavs, nullptr ); m_assignedUavCount = 0; } - uint32_t begin, end; - if( m_assignedUavCount ) - { - begin = std::min( rs.m_uavOffset, m_assignedUavOffset ); - end = std::max( rs.m_uavOffset + rs.m_uavCount, m_assignedUavOffset + m_assignedUavCount ); - } - else - { - begin = rs.m_uavOffset; - end = rs.m_uavOffset + rs.m_uavCount; - } - m_context->CSSetUnorderedAccessViews( - begin, - end - begin, - reinterpret_cast( rs.m_uavs + begin ), - nullptr ); - m_assignedUavCount = rs.m_uavCount; - m_assignedUavOffset = rs.m_uavOffset; + uint32_t begin = m_assignedUavCount ? std::min( uavBegin, m_assignedUavOffset ) : uavBegin; + uint32_t end = m_assignedUavCount ? std::max( uavEnd, m_assignedUavOffset + m_assignedUavCount ) : uavEnd; + m_context->CSSetUnorderedAccessViews( begin, end - begin, desiredUavs + begin, nullptr ); + m_assignedUavOffset = uavBegin; + m_assignedUavCount = uavEnd - uavBegin; m_assignedPsUavs = false; } else { if( m_assignedUavCount && !m_assignedPsUavs ) { - ID3D11UnorderedAccessView* nullUAVs[TrinityALImpl::Tr2ResourceSetAL::MAX_RESOURCES] = {}; - m_context->CSSetUnorderedAccessViews( m_assignedUavOffset, m_assignedUavCount, nullUAVs, nullptr ); + ID3D11UnorderedAccessView* nullUavs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE] = {}; + m_context->CSSetUnorderedAccessViews( m_assignedUavOffset, m_assignedUavCount, nullUavs, nullptr ); m_assignedUavCount = 0; } - uint32_t begin, end; - if( m_assignedUavCount ) - { - begin = std::min( rs.m_uavOffset, m_assignedUavOffset ); - end = std::max( rs.m_uavOffset + rs.m_uavCount, m_assignedUavOffset + m_assignedUavCount ); - } - else - { - begin = rs.m_uavOffset; - end = rs.m_uavOffset + rs.m_uavCount; - } - + uint32_t begin = m_assignedUavCount ? std::min( uavBegin, m_assignedUavOffset ) : uavBegin; + uint32_t end = m_assignedUavCount ? std::max( uavEnd, m_assignedUavOffset + m_assignedUavCount ) : uavEnd; m_context->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, begin, end - begin, - reinterpret_cast( rs.m_uavs + begin ), + desiredUavs + begin, nullptr ); - m_assignedUavCount = rs.m_uavCount; - m_assignedUavOffset = rs.m_uavOffset; + m_assignedUavOffset = uavBegin; + m_assignedUavCount = uavEnd - uavBegin; m_assignedPsUavs = true; } } - for( uint32_t i = 0; i < SHADER_TYPE_COUNT; ++i ) + decltype( &ID3D11DeviceContext::VSSetShaderResources ) setResources[] = { + &ID3D11DeviceContext::VSSetShaderResources, + &ID3D11DeviceContext::PSSetShaderResources, + &ID3D11DeviceContext::CSSetShaderResources, + &ID3D11DeviceContext::GSSetShaderResources, + &ID3D11DeviceContext::HSSetShaderResources, + &ID3D11DeviceContext::DSSetShaderResources, + }; + + decltype( &ID3D11DeviceContext::VSSetSamplers ) setSamplers[] = { + &ID3D11DeviceContext::VSSetSamplers, + &ID3D11DeviceContext::PSSetSamplers, + &ID3D11DeviceContext::CSSetSamplers, + &ID3D11DeviceContext::GSSetSamplers, + &ID3D11DeviceContext::HSSetSamplers, + &ID3D11DeviceContext::DSSetSamplers, + }; + + for( uint32_t stageIndex = 0; stageIndex < SHADER_TYPE_COUNT; ++stageIndex ) { - auto& stage = rs.m_stages[i]; - if( stage.resourceCount && stage.resourceHash != m_resourceHashes[i] ) + if( memcmp( desiredSrvs[stageIndex], m_boundSrvs[stageIndex], sizeof( desiredSrvs[stageIndex] ) ) != 0 ) { - ( m_context->*( setResources[i] ) )( - stage.resourceOffset, - stage.resourceCount, - reinterpret_cast( stage.resources + stage.resourceOffset ) ); - m_resourceHashes[i] = stage.resourceHash; + ( m_context->*( setResources[stageIndex] ) )( 0, Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE, desiredSrvs[stageIndex] ); + memcpy( m_boundSrvs[stageIndex], desiredSrvs[stageIndex], sizeof( desiredSrvs[stageIndex] ) ); } - if( stage.samplerCount && stage.samplerHash != m_samplerHashes[i] ) + // Sampler slots are capped at 16 in D3D11 (D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT); binding more is invalid. + if( memcmp( desiredSamplers[stageIndex], m_boundSamplers[stageIndex], D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT * sizeof( desiredSamplers[stageIndex][0] ) ) != 0 ) { - ( m_context->*( setSamplers[i] ) )( - stage.samplerOffset, - stage.samplerCount, - reinterpret_cast( stage.samplers + stage.samplerOffset ) ); - m_samplerHashes[i] = stage.samplerHash; + ( m_context->*( setSamplers[stageIndex] ) )( 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, desiredSamplers[stageIndex] ); + memcpy( m_boundSamplers[stageIndex], desiredSamplers[stageIndex], D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT * sizeof( desiredSamplers[stageIndex][0] ) ); } } + m_bindingsCommitted = true; + m_bindingsSealed = true; + m_committedProgram = &program; + return S_OK; } diff --git a/trinityal/dx11/Tr2RenderContextDx11.h b/trinityal/dx11/Tr2RenderContextDx11.h index b794d9e65..8d696ec27 100644 --- a/trinityal/dx11/Tr2RenderContextDx11.h +++ b/trinityal/dx11/Tr2RenderContextDx11.h @@ -5,10 +5,13 @@ #define Tr2RenderContextDx11_h_ +#include + #include "../Tr2RenderContextEnum.h" #include "../Tr2DrawUPHelper.h" #include "../include/Tr2ConstantBufferAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2BufferAL.h" +#include "../include/Tr2SamplerStateAL.h" #include "../include/Tr2TextureAL.h" #include "../include/Tr2ShaderAL.h" #include "../include/Tr2ShaderProgramAL.h" @@ -20,8 +23,7 @@ class Tr2ConstantBufferAL; struct ITr2RenderContextEvents; -class Tr2SamplerStateAL; -class Tr2BufferAL; +class Tr2RtPipelineStateAL; class Tr2RtShaderTableAL; struct Tr2Viewport; @@ -99,7 +101,16 @@ class Tr2RenderContextAL ALResult ClearUav( const Tr2TextureAL& rt, uint32_t mipLevel, const float values[4] ) throw(); ALResult ClearUav( const Tr2TextureAL& rt, uint32_t mipLevel, const uint32_t values[4] ) throw(); - ALResult SetResourceSet( const Tr2ResourceSetAL& resourceSet ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip = 0 ) throw(); + ALResult SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw(); + + ALResult ResetResourceBindings() throw(); ALResult DrawIndexedPrimitive( uint32_t numVertices, @@ -256,6 +267,66 @@ class Tr2RenderContextAL // Current shaders Tr2ShaderProgramAL m_shaderProgram; + struct Resource + { + enum Type + { + NONE, + BUFFER, + TEXTURE, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2TextureAL texture; + Tr2BufferAL buffer; + Type type = NONE; + union + { + Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR; + uint32_t mip; + }; + }; + + struct Sampler + { + enum Type + { + NONE, + SAMPLER, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2SamplerStateAL sampler; + Type type = NONE; + }; + + std::vector m_pendingSRVs; + std::vector m_pendingUAVs; + std::vector m_pendingSamplers; + + const Resource* m_sortedSRVs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Resource* m_sortedUAVs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Sampler* m_sortedSamplers[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + + ID3D11ShaderResourceView* m_boundSrvs[Tr2RenderContextEnum::SHADER_TYPE_COUNT][Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + ID3D11SamplerState* m_boundSamplers[Tr2RenderContextEnum::SHADER_TYPE_COUNT][Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + uint32_t m_assignedUavOffset; + uint32_t m_assignedUavCount; + bool m_assignedPsUavs; + + bool m_bindingsCommitted; + bool m_bindingsSealed; + const TrinityALImpl::Tr2ShaderProgramAL* m_committedProgram; + + ALResult UseResourceBindings() throw(); + void BeginResourceBindingBatch() throw(); + void DiscardResourceBindings() throw(); + void UnbindShaderResources( bool unbindUavs ) throw(); + Tr2RenderContextEnum::Topology m_topology; Tr2RenderContextEnum::Topology m_lastSetTopology; // If readonly depth buffer was requested @@ -328,19 +399,11 @@ class Tr2RenderContextAL ALResult SetRtDsToDevice( uint32_t changedSlot ) throw(); private: - uint32_t m_resourceHashes[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - uint32_t m_samplerHashes[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - Tr2ResourceSetAL m_currentResourceSet; - friend class Tr2PrimaryRenderContextAL; typedef TrackableStdStack TextureStack; TrackableStdStack m_stackRT[MAX_RENDER_TARGET]; TextureStack m_stackDS; - uint32_t m_assignedUavOffset; - uint32_t m_assignedUavCount; - bool m_assignedPsUavs; - Tr2RenderContextAL( const Tr2RenderContextAL& ) /* = delete */; Tr2RenderContextAL& operator=( const Tr2RenderContextAL& ) /* = delete */; diff --git a/trinityal/dx11/Tr2ResourceSetALDx11.cpp b/trinityal/dx11/Tr2ResourceSetALDx11.cpp deleted file mode 100644 index d335a3584..000000000 --- a/trinityal/dx11/Tr2ResourceSetALDx11.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#include "StdAfx.h" - -#if TRINITY_PLATFORM == TRINITY_DIRECTX11 - -#include "Tr2ResourceSetALDx11.h" -#include "Tr2BufferALDx11.h" -#include "Tr2TextureALDx11.h" -#include "Tr2SamplerStateALDx11.h" -#include "../include/Tr2ShaderProgramAL.h" - -using namespace Tr2RenderContextEnum; - -namespace TrinityALImpl -{ -Tr2ResourceSetAL::Tr2ResourceSetAL() : - m_isValid( false ), - m_empty( true ), - m_uavCount( 0 ), - m_csUavs( false ) -{ -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& /*renderContext*/ ) -{ - Destroy(); - - if( program.GetRegisterMap() != description.m_registerMap ) - { - return E_INVALIDARG; - } - - ON_BLOCK_EXIT_WITH_UNUSED( [&] { if( !IsValid() ) Destroy(); } ); - - for( auto it = std::begin( m_stages ); it != std::end( m_stages ); ++it ) - { - it->resourceOffset = MAX_RESOURCES; - it->samplerOffset = MAX_RESOURCES; - } - bool hasPsUavs = false; - m_uavOffset = MAX_RESOURCES; - for( uint32_t stageIndex = 0; stageIndex < SHADER_TYPE_COUNT; ++stageIndex ) - { - auto& stage = m_stages[stageIndex]; - for( uint32_t registerIndex = 0; registerIndex < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++registerIndex ) - { - if( description.m_registerMap.srvs[stageIndex][registerIndex] >= description.m_registerMap.srvCount ) - { - continue; - } - auto& desc = description.m_srv[description.m_registerMap.srvs[stageIndex][registerIndex]]; - switch( desc.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - stage.resources[registerIndex] = desc.buffer.m_buffer->m_srv; - break; - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - stage.resources[registerIndex] = desc.texture.m_texture->m_view[desc.colorSpace]; - break; - case Tr2ResourceSetDescriptionAL::Resource::NONE: - continue; - default: - return E_INVALIDARG; - } - stage.resourceOffset = std::min( stage.resourceOffset, registerIndex ); - stage.resourceCount = std::max( stage.resourceCount, registerIndex + 1 ); - } - for( uint32_t registerIndex = 0; registerIndex < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++registerIndex ) - { - if( description.m_registerMap.samplers[stageIndex][registerIndex] >= description.m_registerMap.samplerCount ) - { - continue; - } - auto& desc = description.m_samplers[description.m_registerMap.samplers[stageIndex][registerIndex]]; - if( desc.type == Tr2ResourceSetDescriptionAL::Sampler::SAMPLER ) - { - stage.samplers[registerIndex] = desc.sampler.m_sampler->m_samplerState; - stage.samplerOffset = std::min( stage.samplerOffset, registerIndex ); - stage.samplerCount = std::max( stage.samplerCount, registerIndex + 1 ); - } - } - for( uint32_t registerIndex = 0; registerIndex < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++registerIndex ) - { - if( description.m_registerMap.uavs[stageIndex][registerIndex] >= description.m_registerMap.uavCount ) - { - continue; - } - auto& desc = description.m_uav[description.m_registerMap.uavs[stageIndex][registerIndex]]; - if( desc.type == Tr2ResourceSetDescriptionAL::Resource::NONE ) - { - continue; - } - if( stageIndex != PIXEL_SHADER && stageIndex != COMPUTE_SHADER ) - { - return E_INVALIDARG; - } - if( stageIndex == PIXEL_SHADER ) - { - hasPsUavs = true; - } - else if( hasPsUavs ) - { - return E_INVALIDARG; - } - switch( desc.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - m_uavs[registerIndex] = desc.buffer.m_buffer->m_uav; - m_uavCount = registerIndex + 1; - m_uavOffset = std::min( m_uavOffset, registerIndex ); - break; - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - if( desc.mip < desc.texture.m_texture->m_uav.size() ) - { - m_uavs[registerIndex] = desc.texture.m_texture->m_uav[desc.mip]; - } - else - { - m_uavs[registerIndex] = nullptr; - } - m_uavCount = registerIndex + 1; - m_uavOffset = std::min( m_uavOffset, registerIndex ); - break; - default: - return E_INVALIDARG; - } - m_csUavs = stageIndex == COMPUTE_SHADER; - } - } - - if( m_uavCount ) - { - m_empty = false; - m_uavCount -= m_uavOffset; - } - else - { - m_empty = true; - m_uavOffset = 0; - } - - for( auto it = std::begin( m_stages ); it != std::end( m_stages ); ++it ) - { - if( it->resourceCount > it->resourceOffset ) - { - it->resourceHash = 0; - for( uint32_t i = it->resourceOffset; i != it->resourceCount; ++i ) - { - it->resourceHash ^= uint32_t( reinterpret_cast( it->resources[i].p ) & 0xffffffff ) << i; - } - it->resourceCount -= it->resourceOffset; - m_empty = false; - } - else - { - it->resourceCount = 0; - it->resourceHash = 0; - } - if( it->samplerCount > it->samplerOffset ) - { - it->samplerHash = 0; - for( uint32_t i = it->samplerOffset; i != it->samplerCount; ++i ) - { - it->samplerHash ^= uint32_t( reinterpret_cast( it->samplers[i].p ) & 0xffffffff ) << i; - } - it->samplerCount -= it->samplerOffset; - m_empty = false; - } - else - { - it->samplerCount = 0; - it->samplerHash = 0; - } - } - m_isValid = true; - return S_OK; -}; - -bool Tr2ResourceSetAL::IsValid() const -{ - return m_isValid; -} - -void Tr2ResourceSetAL::Destroy() -{ - for( auto it = std::begin( m_stages ); it != std::end( m_stages ); ++it ) - { - it->Destroy(); - } - std::fill_n( m_uavs, MAX_RESOURCES, nullptr ); - m_uavCount = 0; - m_uavOffset = 0; - m_isValid = false; - m_empty = true; - m_csUavs = false; -} - -Tr2ALMemoryType Tr2ResourceSetAL::GetMemoryClass() const -{ - return AL_MEMORY_MANAGED; -} - - -Tr2ResourceSetAL::StageInput::StageInput() : - resourceCount( 0 ), - resourceOffset( 0 ), - samplerCount( 0 ), - samplerOffset( 0 ), - resourceHash( 0 ), - samplerHash( 0 ) -{ -} - -void Tr2ResourceSetAL::StageInput::Destroy() -{ - std::fill_n( resources, MAX_RESOURCES, nullptr ); - std::fill_n( samplers, MAX_RESOURCES, nullptr ); - resourceCount = 0; - samplerCount = 0; - resourceHash = 0; - samplerHash = 0; -} - -void Tr2ResourceSetAL::Describe( Tr2DeviceResourceDescriptionAL& description ) const -{ - description["type"] = "Tr2ResourceSetAL"; - description["name"] = m_name; -} - -ALResult Tr2ResourceSetAL::SetName( const char* name ) -{ - m_name = name; - return S_OK; -} -} - -#endif \ No newline at end of file diff --git a/trinityal/dx11/Tr2ResourceSetALDx11.h b/trinityal/dx11/Tr2ResourceSetALDx11.h deleted file mode 100644 index d6aa4b9e7..000000000 --- a/trinityal/dx11/Tr2ResourceSetALDx11.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#pragma once - -#if TRINITY_PLATFORM == TRINITY_DIRECTX11 - -#include "../include/Tr2ResourceSetAL.h" - -namespace TrinityALImpl -{ -class Tr2ResourceSetAL : public Tr2DeviceResourceAL -{ -public: - Tr2ResourceSetAL(); - - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ); - bool IsValid() const; - - void Destroy(); - Tr2ALMemoryType GetMemoryClass() const; - void Describe( Tr2DeviceResourceDescriptionAL& description ) const; - ALResult SetName( const char* name ); - -private: - static const uint32_t MAX_RESOURCES = 32; - - struct StageInput - { - StageInput(); - void Destroy(); - - CComPtr resources[MAX_RESOURCES]; - CComPtr samplers[MAX_RESOURCES]; - - uint32_t resourceCount; - uint32_t resourceOffset; - uint32_t samplerCount; - uint32_t samplerOffset; - uint32_t resourceHash; - uint32_t samplerHash; - }; - - StageInput m_stages[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - - CComPtr m_uavs[MAX_RESOURCES]; - uint32_t m_uavOffset; - uint32_t m_uavCount; - std::string m_name; - bool m_csUavs; - - bool m_empty; - bool m_isValid; - - friend class Tr2RenderContextAL; -}; -} - -#endif \ No newline at end of file diff --git a/trinityal/dx11/Tr2SamplerStateALDx11.h b/trinityal/dx11/Tr2SamplerStateALDx11.h index 1c7ba9257..ec7a26425 100644 --- a/trinityal/dx11/Tr2SamplerStateALDx11.h +++ b/trinityal/dx11/Tr2SamplerStateALDx11.h @@ -29,7 +29,6 @@ class Tr2SamplerStateAL : public Tr2DeviceResourceAL CComPtr m_samplerState; std::string m_name; friend class Tr2RenderContextAL; - friend class Tr2ResourceSetAL; }; } diff --git a/trinityal/dx11/Tr2ShaderProgramALDx11.h b/trinityal/dx11/Tr2ShaderProgramALDx11.h index 399fbfb8d..7b3a6885f 100644 --- a/trinityal/dx11/Tr2ShaderProgramALDx11.h +++ b/trinityal/dx11/Tr2ShaderProgramALDx11.h @@ -4,7 +4,7 @@ #include "../include/Tr2ShaderProgramAL.h" #include "../include/Tr2ShaderAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2RegisterMapAL.h" #if ( TRINITY_PLATFORM == TRINITY_DIRECTX11 ) diff --git a/trinityal/dx11/Tr2TextureALDx11.h b/trinityal/dx11/Tr2TextureALDx11.h index b655adfcc..a3881a319 100644 --- a/trinityal/dx11/Tr2TextureALDx11.h +++ b/trinityal/dx11/Tr2TextureALDx11.h @@ -14,10 +14,6 @@ #endif -namespace TrinityALImpl -{ -class Tr2ResourceSetAL; -} @@ -108,7 +104,6 @@ class Tr2TextureAL : public Tr2DeviceResourceAL friend class Tr2PrimaryRenderContextAL; friend class Tr2RenderContextAL; - friend class Tr2ResourceSetAL; }; } diff --git a/trinityal/dx12/Tr2BufferALDx12.h b/trinityal/dx12/Tr2BufferALDx12.h index 2e2e5bd51..0893edff7 100644 --- a/trinityal/dx12/Tr2BufferALDx12.h +++ b/trinityal/dx12/Tr2BufferALDx12.h @@ -65,7 +65,6 @@ class Tr2BufferAL : public Tr2DeviceResourceAL std::shared_ptr m_clearUav; friend class Tr2RenderContextAL; - friend class TrinityALImpl::Tr2ResourceSetAL; friend class TrinityALImpl::Tr2RtShaderTableAL; }; } diff --git a/trinityal/dx12/Tr2PrimaryRenderContextDx12.cpp b/trinityal/dx12/Tr2PrimaryRenderContextDx12.cpp index 68c3e5ac3..deb9b7e89 100644 --- a/trinityal/dx12/Tr2PrimaryRenderContextDx12.cpp +++ b/trinityal/dx12/Tr2PrimaryRenderContextDx12.cpp @@ -867,7 +867,7 @@ ALResult Tr2PrimaryRenderContextAL::Present() std::remove_if( begin( m_pendingPresents ), end( m_pendingPresents ), []( const PendingPresent& p ) -> bool { return !p.backBuffer.IsValid(); } ), end( m_pendingPresents ) ); - SetResourceSet( Tr2ResourceSetAL() ); + ResetResourceBindings(); { std::vector barriers; diff --git a/trinityal/dx12/Tr2RenderContextDx12.cpp b/trinityal/dx12/Tr2RenderContextDx12.cpp index e13747566..2f7d2bea3 100644 --- a/trinityal/dx12/Tr2RenderContextDx12.cpp +++ b/trinityal/dx12/Tr2RenderContextDx12.cpp @@ -10,11 +10,12 @@ #include "Tr2VertexLayoutALDx12.h" #include "Tr2ShaderProgramALDx12.h" #include "Tr2PrimaryRenderContextDx12.h" -#include "Tr2ResourceSetALDx12.h" +#include "Tr2SamplerStateALDx12.h" #include "Tr2RtPipelineStateALDx12.h" #include "Tr2RtShaderTableALDx12.h" #include "Utilities.h" #include "util/AmdExtDevice.h" +#include "ALLog.h" extern bool g_requestDebugMarkers; @@ -95,9 +96,22 @@ Tr2RenderContextAL::Tr2RenderContextAL() throw() : m_separateAlphaBlendEnabled( false ), m_srgbWriteEnable( false ), m_topology( Tr2RenderContextEnum::TOP_TRIANGLES ), - m_uavBarriersDisabledCounter( 0 ) + m_uavBarriersDisabledCounter( 0 ), + m_bindingsCommitted( false ), + m_bindingsSealed( false ), + m_committedRootSignature( nullptr ) { std::fill( std::begin( m_vertexBuffers ), std::end( m_vertexBuffers ), VB() ); + + m_pendingSRVs.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_pendingUAVs.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_pendingSamplers.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_outTransitions.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + m_usedResources.reserve( Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); } Tr2RenderContextAL::~Tr2RenderContextAL() throw() @@ -113,6 +127,8 @@ void Tr2RenderContextAL::Destroy() throw() m_ownerDevice->UnRegisterFromCrashTracker( m_commandList2 ); } + DiscardResourceBindings(); + ResetDx12(); m_descriptorCache.clear(); @@ -327,6 +343,7 @@ ALResult Tr2RenderContextAL::SetShaderProgram( const Tr2ShaderProgramAL& shader { m_psoDescription.m_shaderProgram = shader; m_dirtyPso = true; + m_bindingsCommitted = false; } return S_OK; } @@ -489,40 +506,217 @@ ALResult Tr2RenderContextAL::SetRenderStates( const uint32_t* stateValuePairs, u return S_OK; } -ALResult Tr2RenderContextAL::SetResourceSet( const Tr2ResourceSetAL& resourceSet ) throw() +void Tr2RenderContextAL::BeginResourceBindingBatch() throw() { - if( m_resourceSet.IsValid() && !m_resourceSet.m_resourceSet->m_outTransitions.empty() ) + if( !m_bindingsSealed ) { - ResourceBarrierDx12( m_resourceSet.m_resourceSet->m_outTransitions.size(), m_resourceSet.m_resourceSet->m_outTransitions.data() ); + return; } - m_resourceSet = resourceSet; - if( !m_resourceSet.IsValid() ) + + m_bindingsSealed = false; + m_bindingsCommitted = false; + + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + if( !m_outTransitions.empty() ) { - return S_OK; + ResourceBarrierDx12( m_outTransitions.size(), m_outTransitions.data() ); + m_outTransitions.clear(); } - auto rs = resourceSet.m_resourceSet.get(); - if( !rs->m_inTransitions.empty() ) + m_usedResources.clear(); +} + +void Tr2RenderContextAL::DiscardResourceBindings() throw() +{ + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + m_outTransitions.clear(); + m_usedResources.clear(); + + m_bindingsCommitted = false; + m_bindingsSealed = false; + m_committedRootSignature = nullptr; +} + +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) { - ResourceBarrierDx12( rs->m_inTransitions.size(), rs->m_inTransitions.data() ); + return E_INVALIDARG; } + BeginResourceBindingBatch(); - uint32_t bufferIndex = GetPrimaryRenderContextPointer()->GetCurrentBackBufferIndex(); - m_descriptorCache[bufferIndex]->SetSamplers( 0, rs->m_samplerCount, rs->m_sampler ); + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} - // Because SRVs and UAVs are stacked in the resource slots, this will filter them out into the correct heap setup calls - // It's not great, but if the system is changed in the future to separate SRVs and UAVs then this is an easy change - for( uint32_t idx = 0; idx < rs->m_resourceCount; ++idx ) +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) { - if( ( rs->m_srvMask & ( 1 << idx ) ) != 0 ) - { - m_descriptorCache[bufferIndex]->SetShaderResources( idx, 1, &rs->m_srv[idx] ); - } - else if( ( rs->m_uavMask & ( 1 << idx ) ) != 0 ) - { - m_descriptorCache[bufferIndex]->SetUnorderedAccessViews( idx, 1, &rs->m_uav[idx] ); - } + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.colorSpace = colorSpace; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.mip = mip; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::SAMPLER; + entry.sampler = sampler; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() +{ + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::HEAP_VIEW; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; + return S_OK; +} + +ALResult Tr2RenderContextAL::ResetResourceBindings() throw() +{ + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + if( !m_outTransitions.empty() ) + { + ResourceBarrierDx12( m_outTransitions.size(), m_outTransitions.data() ); + m_outTransitions.clear(); } + m_usedResources.clear(); + m_bindingsCommitted = false; + m_bindingsSealed = false; + m_committedRootSignature = nullptr; return S_OK; } @@ -745,6 +939,7 @@ ALResult Tr2RenderContextAL::DispatchRays( Tr2RtPipelineStateAL& pipeline, Tr2Rt m_commandList->SetComputeRootSignature( p->GetGlobalRootSignature().m_rootSignature ); uint32_t bufferIndex = m_ownerDevice->GetCurrentBackBufferIndex(); + UseResourceBindings( p->GetGlobalRootSignature() ); m_descriptorCache[bufferIndex]->Commit( m_commandList, GetPrimaryRenderContextPointer()->GetGlobalSrvUavHeap(), GetPrimaryRenderContextPointer()->GetGlobalSamplerHeap(), &pipeline.TrinityALImpl_GetObject()->GetGlobalRootSignature() ); FlushComputeBarriersDx12(); @@ -805,8 +1000,231 @@ ID3D12PipelineState* Tr2RenderContextAL::GetPipelineState() return pipelineState; } +ALResult Tr2RenderContextAL::UseResourceBindings() throw() +{ + if( !m_psoDescription.m_shaderProgram.IsValid() ) + { + return S_OK; + } + return UseResourceBindings( m_psoDescription.m_shaderProgram.m_program->m_rootSignature ); +} + +ALResult Tr2RenderContextAL::UseResourceBindings( const TrinityALImpl::Tr2RootSignatureAL& rootSignature ) throw() +{ + if( m_bindingsCommitted && m_committedRootSignature == &rootSignature ) + { + return S_OK; + } + + Tr2PrimaryRenderContextAL& renderContext = GetPrimaryRenderContext(); + auto& registerMap = rootSignature.m_registerMap; + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + for( const auto& resource : m_pendingSRVs ) + { + uint32_t index = registerMap.srvs[resource.stage][resource.registerIndex]; + if( index < registerMap.srvCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedSRVs[index] = &resource; + } + } + for( const auto& resource : m_pendingUAVs ) + { + uint32_t index = registerMap.uavs[resource.stage][resource.registerIndex]; + if( index < registerMap.uavCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedUAVs[index] = &resource; + } + } + for( const auto& sampler : m_pendingSamplers ) + { + uint32_t index = registerMap.samplers[sampler.stage][sampler.registerIndex]; + if( index < registerMap.samplerCount && index < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + m_sortedSamplers[index] = &sampler; + } + } + + if( !m_outTransitions.empty() ) + { + ResourceBarrierDx12( m_outTransitions.size(), m_outTransitions.data() ); + m_outTransitions.clear(); + } + m_usedResources.clear(); + + D3D12_RESOURCE_BARRIER inTransitions[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + ID3D12Resource* transitioned[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + uint32_t inCount = 0; + uint32_t transitionedCount = 0; + + auto AddTransition = [&]( ID3D12Resource* res, D3D12_RESOURCE_STATES defaultState, D3D12_RESOURCE_STATES expectedState ) { + // TODO: verify state + if( ( defaultState & expectedState ) == 0 && defaultState != D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE ) + { + auto found = std::find( transitioned, transitioned + transitionedCount, res ); + if( found == transitioned + transitionedCount && transitionedCount < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + inTransitions[inCount++] = TrinityALImpl::Transition( res, defaultState, expectedState ); + m_outTransitions.push_back( TrinityALImpl::Transition( res, expectedState, defaultState ) ); + transitioned[transitionedCount++] = res; + } + } + m_usedResources.push_back( res ); + }; + + uint32_t bufferIndex = GetPrimaryRenderContextPointer()->GetCurrentBackBufferIndex(); + + for( const auto& reg : rootSignature.m_srvRegisters ) + { + uint32_t mapIndex = registerMap.srvs[reg.stage][reg.index]; + const Resource* resource = mapIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedSRVs[mapIndex] : nullptr; + auto stateFlag = reg.stage == Tr2RenderContextEnum::PIXEL_SHADER ? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + + std::shared_ptr srv; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::TEXTURE: + if( resource->texture.IsValid() && reg.registerType >= Tr2ShaderRegisterAL::SRV_TEXTURE1D ) + { + srv = resource->texture.m_texture->m_view[resource->colorSpace]; + } + if( !srv ) + { + srv = renderContext.GetNullSrvDx12( reg.registerType ); + } + else + { + AddTransition( resource->texture.m_texture->GetResourceDx12(), resource->texture.m_texture->m_defaultState, stateFlag ); + } + break; + case Resource::BUFFER: + if( resource->buffer.IsValid() && reg.registerType <= Tr2ShaderRegisterAL::SRV_STRUCTURED_BUFFER ) + { + srv = resource->buffer.m_buffer->m_srv; + } + if( !srv ) + { + srv = renderContext.GetNullSrvDx12( reg.registerType ); + } + else + { + AddTransition( resource->buffer.m_buffer->GetGpuResource(), resource->buffer.m_buffer->m_defaultState, stateFlag ); + } + break; + case Resource::HEAP_VIEW: + srv = renderContext.GetSrvHeapView(); + break; + default: + srv = renderContext.GetNullSrvDx12( reg.registerType ); + break; + } + + if( srv ) + { + m_descriptorCache[bufferIndex]->SetShaderResources( reg.parameter, 1, &srv ); + } + } + + for( const auto& reg : rootSignature.m_uavRegisters ) + { + uint32_t mapIndex = registerMap.uavs[reg.stage][reg.index]; + const Resource* resource = mapIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedUAVs[mapIndex] : nullptr; + + std::shared_ptr uav; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::TEXTURE: + if( resource->texture.IsValid() ) + { + if( reg.registerType >= Tr2ShaderRegisterAL::UAV_TEXTURE1D ) + { + uav = resource->texture.m_texture->m_uav[resource->mip]; + } + if( !uav ) + { + uav = renderContext.GetNullUavDx12( reg.registerType ); + } + else + { + AddTransition( resource->texture.m_texture->GetResourceDx12(), resource->texture.m_texture->m_defaultState, D3D12_RESOURCE_STATE_UNORDERED_ACCESS ); + } + } + break; + case Resource::BUFFER: + if( resource->buffer.IsValid() ) + { + if( reg.registerType <= Tr2ShaderRegisterAL::UAV_STRUCTURED_BUFFER ) + { + uav = resource->buffer.m_buffer->m_uav; + } + if( !uav ) + { + uav = renderContext.GetNullUavDx12( reg.registerType ); + } + else + { + AddTransition( resource->buffer.m_buffer->GetGpuResource(), resource->buffer.m_buffer->m_defaultState, D3D12_RESOURCE_STATE_UNORDERED_ACCESS ); + } + } + break; + case Resource::HEAP_VIEW: + uav = renderContext.GetUavHeapView(); + break; + default: + CCP_AL_LOGWARN( "Missing UAV resource binding for register %u, stage %u", reg.index, reg.stage ); + uav = renderContext.GetNullUavDx12( reg.registerType ); + break; + } + + if( uav ) + { + m_descriptorCache[bufferIndex]->SetUnorderedAccessViews( reg.parameter, 1, &uav ); + } + } + + std::shared_ptr samplers[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + uint32_t samplerCount = 0; + + for( const auto& reg : rootSignature.m_samplerRegisters ) + { + uint32_t mapIndex = registerMap.samplers[reg.stage][reg.index]; + const Sampler* sampler = mapIndex < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ? m_sortedSamplers[mapIndex] : nullptr; + + switch( sampler ? sampler->type : Sampler::NONE ) + { + case Sampler::SAMPLER: + samplers[reg.parameter] = sampler->sampler.m_sampler->m_samplerState; + break; + case Sampler::HEAP_VIEW: + samplers[reg.parameter] = renderContext.GetSamplerHeapView(); + break; + default: + samplers[reg.parameter] = renderContext.GetNullSamplerDx12(); + break; + } + samplerCount = std::max( reg.parameter + 1, samplerCount ); + } + + m_descriptorCache[bufferIndex]->SetSamplers( 0, samplerCount, samplers ); + + if( inCount ) + { + ResourceBarrierDx12( inCount, inTransitions ); + } + + m_bindingsCommitted = true; + m_bindingsSealed = true; + m_committedRootSignature = &rootSignature; + return S_OK; +} + ALResult Tr2RenderContextAL::SetAllState() { + UseResourceBindings(); + if( ( m_dynamicVBs & m_psoDescription.m_vertexStreamMask ) != 0 ) { D3D12_VERTEX_BUFFER_VIEW vb[4]; @@ -884,8 +1302,8 @@ void Tr2RenderContextAL::FlushGraphicsBarriersDx12( ID3D12Resource* resource ) return; } size_t count = 0; - // resource + m_boundRenderTargets + m_boundDepthStencil + m_vertexBuffers + m_indexBuffer + m_resourceSet - ID3D12Resource* resources[1 + RENDER_TARGET_COUNT + 1 + 4 + 1 + Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; + // resource + m_boundRenderTargets + m_boundDepthStencil + m_vertexBuffers + m_indexBuffer + m_usedResources + ID3D12Resource* resources[1 + RENDER_TARGET_COUNT + 1 + 4 + 1 + 2 * Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; if( resource ) { @@ -914,10 +1332,10 @@ void Tr2RenderContextAL::FlushGraphicsBarriersDx12( ID3D12Resource* resource ) resources[count++] = m_indexBuffer.m_buffer->m_buffer.GetResource(); } - if( m_resourceSet.IsValid() ) + if( !m_usedResources.empty() ) { - std::copy( begin( m_resourceSet.m_resourceSet->m_usedResources ), end( m_resourceSet.m_resourceSet->m_usedResources ), resources + count ); - count += m_resourceSet.m_resourceSet->m_usedResources.size(); + std::copy( begin( m_usedResources ), end( m_usedResources ), resources + count ); + count += m_usedResources.size(); } FlushBarriersDx12( count, resources ); @@ -929,25 +1347,22 @@ void Tr2RenderContextAL::FlushComputeBarriersDx12( ID3D12Resource* resource ) { return; } - if( !resource ) - { - if( m_resourceSet.IsValid() && !m_resourceSet.m_resourceSet->m_usedResources.empty() ) - { - FlushBarriersDx12( m_resourceSet.m_resourceSet->m_usedResources.size(), m_resourceSet.m_resourceSet->m_usedResources.data() ); - } - } - else + size_t count = 0; + ID3D12Resource* resources[1 + 2 * Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + + if( resource ) { - size_t count = 0; - ID3D12Resource* resources[1 + Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; resources[count++] = resource; + } - if( m_resourceSet.IsValid() && !m_resourceSet.m_resourceSet->m_usedResources.empty() ) - { - std::copy( begin( m_resourceSet.m_resourceSet->m_usedResources ), end( m_resourceSet.m_resourceSet->m_usedResources ), resources + count ); - count += m_resourceSet.m_resourceSet->m_usedResources.size(); - } + if( !m_usedResources.empty() ) + { + std::copy( begin( m_usedResources ), end( m_usedResources ), resources + count ); + count += m_usedResources.size(); + } + if( count ) + { FlushBarriersDx12( count, resources ); } } @@ -1534,10 +1949,7 @@ bool Tr2RenderContextAL::IsBoundDx12( const TrinityALImpl::Tr2TextureAL& texture void Tr2RenderContextAL::ResetDx12() { - if( m_resourceSet.IsValid() && !m_resourceSet.m_resourceSet->m_outTransitions.empty() ) - { - ResourceBarrierDx12( m_resourceSet.m_resourceSet->m_outTransitions.size(), m_resourceSet.m_resourceSet->m_outTransitions.data() ); - } + ResetResourceBindings(); for( uint32_t i = 0; i < 4; ++i ) { @@ -1547,8 +1959,6 @@ void Tr2RenderContextAL::ResetDx12() m_indexBuffer = Tr2BufferAL(); m_dynamicIB = false; - m_resourceSet = Tr2ResourceSetAL(); - m_psoDescription = TrinityALImpl::PSODescription(); m_topology = Tr2RenderContextEnum::TOP_INVALID; m_primitiveToVertexCount = std::make_pair( 0, 0 ); diff --git a/trinityal/dx12/Tr2RenderContextDx12.h b/trinityal/dx12/Tr2RenderContextDx12.h index 00e910a48..e9d639d9a 100644 --- a/trinityal/dx12/Tr2RenderContextDx12.h +++ b/trinityal/dx12/Tr2RenderContextDx12.h @@ -7,7 +7,9 @@ #include "../Tr2RenderContextEnum.h" #include "../Tr2DrawUPHelper.h" #include "../include/Tr2ConstantBufferAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2BufferAL.h" +#include "../include/Tr2RegisterMapAL.h" +#include "../include/Tr2SamplerStateAL.h" #include "../include/Tr2TextureAL.h" #include "../include/Tr2ShaderProgramAL.h" #include "../include/Tr2VertexLayoutAL.h" @@ -23,9 +25,8 @@ class Tr2ConstantBufferAL; struct ITr2RenderContextEvents; class Tr2ShaderAL; -class Tr2SamplerStateAL; -class Tr2BufferAL; class Tr2RtShaderTableAL; +class Tr2RtPipelineStateAL; struct Tr2Viewport; @@ -91,7 +92,16 @@ class Tr2RenderContextAL ALResult SetVertexLayout( const Tr2VertexLayoutAL& layout ) throw(); ALResult SetShaderProgram( const Tr2ShaderProgramAL& shader ) throw(); - ALResult SetResourceSet( const Tr2ResourceSetAL& resourceSet ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip = 0 ) throw(); + ALResult SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw(); + + ALResult ResetResourceBindings() throw(); ALResult DrawIndexedPrimitive( uint32_t numVertices, @@ -235,6 +245,11 @@ class Tr2RenderContextAL ALResult SetAllState(); protected: + ALResult UseResourceBindings() throw(); + ALResult UseResourceBindings( const TrinityALImpl::Tr2RootSignatureAL& rootSignature ) throw(); + void BeginResourceBindingBatch() throw(); + void DiscardResourceBindings() throw(); + ID3D12PipelineState* GetPipelineState(); /** Forcibly reset and dirty all descriptor caches (used for explicit synchronization) */ @@ -261,8 +276,60 @@ class Tr2RenderContextAL std::pair m_primitiveToVertexCount; - Tr2ResourceSetAL m_resourceSet; +private: + struct Resource + { + enum Type + { + NONE, + BUFFER, + TEXTURE, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2TextureAL texture; + Tr2BufferAL buffer; + Type type = NONE; + union + { + Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR; + uint32_t mip; + }; + }; + struct Sampler + { + enum Type + { + NONE, + SAMPLER, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2SamplerStateAL sampler; + Type type = NONE; + }; + + std::vector m_pendingSRVs; + std::vector m_pendingUAVs; + std::vector m_pendingSamplers; + + const Resource* m_sortedSRVs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Resource* m_sortedUAVs[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Sampler* m_sortedSamplers[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + + std::vector m_outTransitions; + std::vector m_usedResources; + + bool m_bindingsCommitted; + bool m_bindingsSealed; + const TrinityALImpl::Tr2RootSignatureAL* m_committedRootSignature; + +protected: bool GetRenderTargetHandles( D3D12_CPU_DESCRIPTOR_HANDLE* handles, uint32_t& count ); public: diff --git a/trinityal/dx12/Tr2ResourceSetALDx12.cpp b/trinityal/dx12/Tr2ResourceSetALDx12.cpp deleted file mode 100644 index 08fc52f84..000000000 --- a/trinityal/dx12/Tr2ResourceSetALDx12.cpp +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright © 2019 CCP ehf. - -#include "StdAfx.h" - -#if TRINITY_PLATFORM == TRINITY_DIRECTX12 - -#include "Tr2ResourceSetALDx12.h" -#include "Tr2PrimaryRenderContextDx12.h" -#include "Tr2ShaderProgramALDx12.h" -#include "Tr2BufferALDx12.h" -#include "Tr2TextureALDx12.h" -#include "Tr2SamplerStateALDx12.h" -#include "Tr2RtPipelineStateALDx12.h" -#include "Utilities.h" -#include "ALLog.h" - -using namespace Tr2RenderContextEnum; - -namespace -{ -D3D12_CPU_DESCRIPTOR_HANDLE operator+( const D3D12_CPU_DESCRIPTOR_HANDLE& handle, uint32_t offset ) -{ - D3D12_CPU_DESCRIPTOR_HANDLE result = { handle.ptr + offset }; - return result; -} -} - -namespace TrinityALImpl -{ -Tr2ResourceSetAL::Tr2ResourceSetAL() : - m_owner( nullptr ), - m_samplerCount( 0 ), - m_resourceCount( 0 ), - m_srvMask( 0 ), - m_uavMask( 0 ) -{ -} - -Tr2ResourceSetAL::~Tr2ResourceSetAL() -{ - Destroy(); -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ) -{ - Destroy(); - - if( !renderContext.IsValid() ) - { - return E_INVALIDARG; - } - if( !program.IsValid() ) - { - return E_INVALIDARG; - } - - return Create( description, program.m_program->m_rootSignature, renderContext, program.m_program->m_name.c_str() ); -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2RtPipelineStateAL& pipeline, Tr2PrimaryRenderContextAL& renderContext ) -{ - Destroy(); - - if( !renderContext.IsValid() ) - { - return E_INVALIDARG; - } - if( !pipeline.IsValid() ) - { - return E_INVALIDARG; - } - - return Create( description, pipeline.TrinityALImpl_GetObject()->GetGlobalRootSignature(), renderContext, "RtPipeline" ); -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const Tr2RootSignatureAL& rootSignature, Tr2PrimaryRenderContextAL& renderContext, const char* shaderName ) -{ - if( rootSignature.m_registerMap != description.m_registerMap ) - { - return E_INVALIDARG; - } - - std::vector transitioned; - - auto AddTransition = [&]( ID3D12Resource* res, D3D12_RESOURCE_STATES defaultState, D3D12_RESOURCE_STATES expectedState ) { - // TODO: verify state - if( ( defaultState & expectedState ) == 0 && defaultState != D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE ) - { - auto found = std::find( begin( transitioned ), end( transitioned ), res ); - if( found == transitioned.end() ) - { - m_inTransitions.push_back( Transition( res, defaultState, expectedState ) ); - m_outTransitions.push_back( Transition( res, expectedState, defaultState ) ); - transitioned.push_back( res ); - } - } - m_usedResources.push_back( res ); - }; - - for( auto it = begin( rootSignature.m_srvRegisters ); it != end( rootSignature.m_srvRegisters ); ++it ) - { - auto& reg = *it; - auto& resource = description.m_srv[description.m_registerMap.srvs[reg.stage][reg.index]]; - auto stateFlag = reg.stage == PIXEL_SHADER ? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; - m_resourceCount = std::max( reg.parameter + 1, m_resourceCount ); - m_srvMask |= 1 << reg.parameter; - switch( resource.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - if( resource.texture.IsValid() && it->registerType >= Tr2ShaderRegisterAL::SRV_TEXTURE1D ) - { - m_srv[reg.parameter] = resource.texture.m_texture->m_view[resource.colorSpace]; - } - else - { - m_srv[reg.parameter] = nullptr; - } - if( !m_srv[reg.parameter] ) - { - m_srv[reg.parameter] = renderContext.GetNullSrvDx12( it->registerType ); - } - else - { - AddTransition( resource.texture.m_texture->GetResourceDx12(), resource.texture.m_texture->m_defaultState, stateFlag ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - if( resource.buffer.IsValid() && it->registerType <= Tr2ShaderRegisterAL::SRV_STRUCTURED_BUFFER ) - { - m_srv[reg.parameter] = resource.buffer.m_buffer->m_srv; - } - else - { - m_srv[reg.parameter] = nullptr; - } - if( !m_srv[reg.parameter] ) - { - m_srv[reg.parameter] = renderContext.GetNullSrvDx12( it->registerType ); - } - else - { - AddTransition( resource.buffer.m_buffer->GetGpuResource(), resource.buffer.m_buffer->m_defaultState, stateFlag ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::HEAP_VIEW: - m_srv[reg.parameter] = renderContext.GetSrvHeapView(); - break; - default: - m_srv[reg.parameter] = renderContext.GetNullSrvDx12( it->registerType ); - break; - } - } - - for( auto it = begin( rootSignature.m_uavRegisters ); it != end( rootSignature.m_uavRegisters ); ++it ) - { - auto& reg = *it; - auto& resource = description.m_uav[description.m_registerMap.uavs[reg.stage][reg.index]]; - m_resourceCount = std::max( reg.parameter + 1, m_resourceCount ); - m_uavMask |= 1 << reg.parameter; - switch( resource.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - if( resource.texture.IsValid() ) - { - if( resource.texture.IsValid() && it->registerType >= Tr2ShaderRegisterAL::UAV_TEXTURE1D ) - { - m_uav[reg.parameter] = resource.texture.m_texture->m_uav[resource.mip]; - } - else - { - m_uav[reg.parameter] = nullptr; - } - if( !m_uav[reg.parameter] ) - { - m_uav[reg.parameter] = renderContext.GetNullUavDx12( it->registerType ); - } - else - { - AddTransition( resource.texture.m_texture->GetResourceDx12(), resource.texture.m_texture->m_defaultState, D3D12_RESOURCE_STATE_UNORDERED_ACCESS ); - } - } - break; - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - if( resource.buffer.IsValid() ) - { - if( resource.buffer.IsValid() && it->registerType <= Tr2ShaderRegisterAL::UAV_STRUCTURED_BUFFER ) - { - m_uav[reg.parameter] = resource.buffer.m_buffer->m_uav; - } - else - { - m_uav[reg.parameter] = nullptr; - } - if( !m_uav[reg.parameter] ) - { - m_uav[reg.parameter] = renderContext.GetNullUavDx12( it->registerType ); - } - else - { - AddTransition( resource.buffer.m_buffer->GetGpuResource(), resource.buffer.m_buffer->m_defaultState, D3D12_RESOURCE_STATE_UNORDERED_ACCESS ); - } - } - break; - case Tr2ResourceSetDescriptionAL::Resource::HEAP_VIEW: - m_uav[reg.parameter] = renderContext.GetUavHeapView(); - break; - default: - CCP_AL_LOGWARN( "Missing UAV resource in resource set for register %u, stage %u, shader '%s'", reg.index, reg.stage, shaderName ); - m_uav[reg.parameter] = renderContext.GetNullUavDx12( it->registerType ); - break; - } - } - - for( auto it = begin( rootSignature.m_samplerRegisters ); it != end( rootSignature.m_samplerRegisters ); ++it ) - { - auto& reg = *it; - auto& sampler = description.m_samplers[description.m_registerMap.samplers[reg.stage][reg.index]]; - switch( sampler.type ) - { - case Tr2ResourceSetDescriptionAL::Sampler::SAMPLER: - m_sampler[reg.parameter] = sampler.sampler.m_sampler->m_samplerState; - break; - case Tr2ResourceSetDescriptionAL::Sampler::HEAP_VIEW: - m_sampler[reg.parameter] = renderContext.GetSamplerHeapView(); - break; - default: - m_sampler[reg.parameter] = renderContext.GetNullSamplerDx12(); - break; - } - m_samplerCount = std::max( reg.parameter + 1, m_samplerCount ); - } - - m_owner = &renderContext; - - return S_OK; -} - -void Tr2ResourceSetAL::Destroy() -{ - for( uint32_t idx = 0; idx < m_resourceCount; ++idx ) - { - m_srv[idx] = nullptr; - m_uav[idx] = nullptr; - } - m_resourceCount = 0; - m_srvMask = 0; - m_uavMask = 0; - for( uint32_t idx = 0; idx < m_samplerCount; ++idx ) - { - m_sampler[idx] = nullptr; - } - m_samplerCount = 0; - - m_owner = nullptr; - m_inTransitions.clear(); - m_outTransitions.clear(); - m_usedResources.clear(); -} - -bool Tr2ResourceSetAL::IsValid() const -{ - return m_owner != nullptr; -} - -Tr2ALMemoryType Tr2ResourceSetAL::GetMemoryClass() const -{ - return AL_MEMORY_MANAGED; -} - -void Tr2ResourceSetAL::Describe( Tr2DeviceResourceDescriptionAL& description ) const -{ - description["type"] = "Tr2ResourceSetAL"; - description["name"] = m_name; -} - -ALResult Tr2ResourceSetAL::SetName( const char* name ) -{ - m_name = name; - return S_OK; -} -} - -#endif \ No newline at end of file diff --git a/trinityal/dx12/Tr2ResourceSetALDx12.h b/trinityal/dx12/Tr2ResourceSetALDx12.h deleted file mode 100644 index f20d5d227..000000000 --- a/trinityal/dx12/Tr2ResourceSetALDx12.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2019 CCP ehf. - -#pragma once - -#if TRINITY_PLATFORM == TRINITY_DIRECTX12 - -#include "../include/Tr2ResourceSetAL.h" -#include "util/DescriptorHeapViewDx12.h" - -namespace TrinityALImpl -{ -struct Tr2RootSignatureAL; -class Tr2ResourceSetAL : public Tr2DeviceResourceAL -{ -public: - Tr2ResourceSetAL(); - ~Tr2ResourceSetAL(); - - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ); - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2RtPipelineStateAL& pipeline, Tr2PrimaryRenderContextAL& renderContext ); - void Destroy(); - - bool IsValid() const; - Tr2ALMemoryType GetMemoryClass() const; - - void Describe( Tr2DeviceResourceDescriptionAL& description ) const; - ALResult SetName( const char* name ); - -private: - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const Tr2RootSignatureAL& signature, Tr2PrimaryRenderContextAL& renderContext, const char* shaderName ); - std::shared_ptr m_srv[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - std::shared_ptr m_uav[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - std::shared_ptr m_sampler[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - uint32_t m_samplerCount; - uint32_t m_resourceCount; - uint32_t m_srvMask; - uint32_t m_uavMask; - Tr2PrimaryRenderContextAL* m_owner; - - std::vector m_inTransitions; - std::vector m_outTransitions; - std::vector m_usedResources; - std::string m_name; - - friend class ::Tr2RenderContextAL; -}; -} - -#endif \ No newline at end of file diff --git a/trinityal/dx12/Tr2SamplerStateALDx12.h b/trinityal/dx12/Tr2SamplerStateALDx12.h index a66407662..2c69c279a 100644 --- a/trinityal/dx12/Tr2SamplerStateALDx12.h +++ b/trinityal/dx12/Tr2SamplerStateALDx12.h @@ -36,7 +36,6 @@ class Tr2SamplerStateAL : public Tr2DeviceResourceAL bool m_isValid; friend class Tr2RenderContextAL; - friend class Tr2ResourceSetAL; friend class TrinityALImpl::Tr2RtShaderTableAL; }; diff --git a/trinityal/dx12/Tr2ShaderProgramALDx12.h b/trinityal/dx12/Tr2ShaderProgramALDx12.h index ec664b71c..2ad98bfe4 100644 --- a/trinityal/dx12/Tr2ShaderProgramALDx12.h +++ b/trinityal/dx12/Tr2ShaderProgramALDx12.h @@ -5,7 +5,7 @@ #if TRINITY_PLATFORM == TRINITY_DIRECTX12 #include "../include/Tr2ShaderProgramAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2RegisterMapAL.h" #include "../include/Tr2ShaderAL.h" class DescriptorStateCache; @@ -111,7 +111,6 @@ class Tr2ShaderProgramAL : public Tr2DeviceResourceAL std::string m_name; friend class ::Tr2RenderContextAL; - friend class Tr2ResourceSetAL; friend class ::DescriptorStateCache; friend class PSODescription; }; diff --git a/trinityal/dx12/Tr2StreamlineALDx12.h b/trinityal/dx12/Tr2StreamlineALDx12.h index 84db96dc9..2663a36c7 100644 --- a/trinityal/dx12/Tr2StreamlineALDx12.h +++ b/trinityal/dx12/Tr2StreamlineALDx12.h @@ -13,7 +13,6 @@ #include "../include/Tr2TextureAL.h" #include "Tr2TextureALDx12.h" #include "Tr2RenderContextDx12.h" -#include "Tr2ResourceSetALDx12.h" #include "Tr2GpuTimerALDx12.h" #include "Tr2PrimaryRenderContextDx12.h" #include "Tr2RenderContextDx12.h" diff --git a/trinityal/dx12/Tr2TextureALDx12.cpp b/trinityal/dx12/Tr2TextureALDx12.cpp index c51a92174..d6ed6ed2c 100644 --- a/trinityal/dx12/Tr2TextureALDx12.cpp +++ b/trinityal/dx12/Tr2TextureALDx12.cpp @@ -1193,7 +1193,8 @@ ALResult Tr2TextureAL::GenerateMipMaps( Tr2RenderContextAL& renderContext ) return E_INVALIDCALL; } - renderContext.SetResourceSet( ::Tr2ResourceSetAL() ); + renderContext.ResetResourceBindings(); + renderContext.FlushBarriersDx12(); renderContext.FlushBarriersDx12( m_textures[0] ); renderContext.m_dirtyPso = true; diff --git a/trinityal/dx12/Tr2TextureALDx12.h b/trinityal/dx12/Tr2TextureALDx12.h index 18fcb21bc..a88313b27 100644 --- a/trinityal/dx12/Tr2TextureALDx12.h +++ b/trinityal/dx12/Tr2TextureALDx12.h @@ -17,7 +17,6 @@ namespace TrinityALImpl { -class Tr2ResourceSetAL; class Tr2RtShaderTableAL; } @@ -119,7 +118,6 @@ class Tr2TextureAL : public Tr2DeviceResourceAL struct MipMapGenerator; std::unique_ptr m_mipMapGenerator; - friend class Tr2ResourceSetAL; friend class Tr2RenderContextAL; friend class Tr2RtShaderTableAL; }; diff --git a/trinityal/dx12/upscaling/Tr2XessUpscaling.cpp b/trinityal/dx12/upscaling/Tr2XessUpscaling.cpp index 2a00d6428..a15b0de12 100644 --- a/trinityal/dx12/upscaling/Tr2XessUpscaling.cpp +++ b/trinityal/dx12/upscaling/Tr2XessUpscaling.cpp @@ -320,7 +320,7 @@ Tr2UpscalingAL::Result Tr2XessUpscalingContext::Dispatch( Tr2UpscalingAL::Dispat auto& renderContext = m_params.renderContext; // flush all barriers before changing the state of the textures - renderContext.SetResourceSet( Tr2ResourceSetAL() ); + renderContext.ResetResourceBindings(); renderContext.FlushBarriersDx12(); // transition from common to unordered access view, since the output texture must be in that state diff --git a/trinityal/dx12/util/DescriptorStateCacheDx12.cpp b/trinityal/dx12/util/DescriptorStateCacheDx12.cpp index 4b9de3f0b..a8beb96c4 100644 --- a/trinityal/dx12/util/DescriptorStateCacheDx12.cpp +++ b/trinityal/dx12/util/DescriptorStateCacheDx12.cpp @@ -41,7 +41,7 @@ DescriptorStateCache::DescriptorStateCache( CComPtr device, Tr2Pri /** Dirty all states and reset internal allocators */ void DescriptorStateCache::Reset() { - for( uint32_t slot = 0; slot < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++slot ) + for( uint32_t slot = 0; slot < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE; ++slot ) { m_srvUav[slot] = m_nullSrv; m_sampler[slot] = m_nullSampler; @@ -72,7 +72,7 @@ void DescriptorStateCache::Dirty() m_samplerDirty = true; // Pretend that nothing is currently bound forcing the next Commit() to re-assign every parameter - for( uint32_t slot = 0; slot < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++slot ) + for( uint32_t slot = 0; slot < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE; ++slot ) { m_parameterSlots[slot].SetNone(); m_parameterSlots[slot].SetNone(); diff --git a/trinityal/dx12/util/DescriptorStateCacheDx12.h b/trinityal/dx12/util/DescriptorStateCacheDx12.h index 238cdbc65..d25883296 100644 --- a/trinityal/dx12/util/DescriptorStateCacheDx12.h +++ b/trinityal/dx12/util/DescriptorStateCacheDx12.h @@ -9,7 +9,7 @@ #include "../Tr2ConstantBufferALDx12.h" #include "../Tr2ShaderProgramAlDx12.h" #include "../../Tr2RenderContextEnum.h" -#include "../../include/Tr2ResourceSetAL.h" +#include "../../include/Tr2RegisterMapAL.h" #include "DescriptorHeapViewDx12.h" #include "FrameLocalDescriptorHeapAllocatorDx12.h" @@ -129,9 +129,9 @@ class DescriptorStateCache CComPtr m_rootSignature; - std::shared_ptr m_srvUav[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - std::shared_ptr m_sampler[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - D3D12_GPU_VIRTUAL_ADDRESS m_cbv[Tr2RenderContextEnum::SHADER_TYPE_COUNT][Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; + std::shared_ptr m_srvUav[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + std::shared_ptr m_sampler[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + D3D12_GPU_VIRTUAL_ADDRESS m_cbv[Tr2RenderContextEnum::SHADER_TYPE_COUNT][Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; CComPtr m_globalSrvUavHeap; CComPtr m_globalSamplerHeap; @@ -139,7 +139,7 @@ class DescriptorStateCache bool m_srvUavDirty; bool m_samplerDirty; - RootParameterSlot m_parameterSlots[Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; + RootParameterSlot m_parameterSlots[Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; }; #endif diff --git a/trinityal/include/Tr2BufferAL.h b/trinityal/include/Tr2BufferAL.h index 588251b81..1c0b00cff 100644 --- a/trinityal/include/Tr2BufferAL.h +++ b/trinityal/include/Tr2BufferAL.h @@ -12,7 +12,6 @@ class Tr2RenderContextAL; namespace TrinityALImpl { class Tr2BufferAL; -class Tr2ResourceSetAL; } @@ -98,7 +97,6 @@ class Tr2BufferAL friend class Tr2RenderContextAL; friend class Tr2PrimaryRenderContextAL; - friend class TrinityALImpl::Tr2ResourceSetAL; }; diff --git a/trinityal/include/Tr2RegisterMapAL.h b/trinityal/include/Tr2RegisterMapAL.h new file mode 100644 index 000000000..27c726ec4 --- /dev/null +++ b/trinityal/include/Tr2RegisterMapAL.h @@ -0,0 +1,28 @@ +// Copyright © 2023 CCP ehf. + +#pragma once + +#include "../Tr2RenderContextEnum.h" + +class Tr2ShaderAL; +struct Tr2ShaderSignatureAL; + +struct Tr2RegisterMapAL +{ + Tr2RegisterMapAL(); + Tr2RegisterMapAL( Tr2RenderContextEnum::ShaderType stage, const Tr2ShaderSignatureAL& signature ); + Tr2RegisterMapAL( const Tr2ShaderAL* shaders, size_t shaderCount ); + Tr2RegisterMapAL( const Tr2RenderContextEnum::ShaderType* shaders, const Tr2ShaderSignatureAL* signatures, size_t signatureCount ); + + bool operator==( const Tr2RegisterMapAL& other ) const; + bool operator!=( const Tr2RegisterMapAL& other ) const; + + static const uint32_t MAX_RESOURCES_IN_STAGE = 32; + + uint32_t srvCount; + uint32_t uavCount; + uint32_t samplerCount; + uint8_t srvs[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; + uint8_t uavs[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; + uint8_t samplers[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; +}; diff --git a/trinityal/include/Tr2ResourceSetAL.h b/trinityal/include/Tr2ResourceSetAL.h deleted file mode 100644 index 261f9c02c..000000000 --- a/trinityal/include/Tr2ResourceSetAL.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#pragma once - -#include "../ALResult.h" -#include "../Tr2DeviceResourceAL.h" -#include "Tr2BufferAL.h" -#include "Tr2TextureAL.h" -#include "Tr2SamplerStateAL.h" - -class Tr2ShaderAL; -class Tr2ShaderProgramAL; -class Tr2PrimaryRenderContextAL; -class Tr2RtPipelineStateAL; -struct Tr2ShaderSignatureAL; - -namespace TrinityALImpl -{ -class Tr2ResourceSetAL; -class Tr2RtShaderTableAL; -} - -struct Tr2RegisterMapAL -{ - Tr2RegisterMapAL(); - Tr2RegisterMapAL( Tr2RenderContextEnum::ShaderType stage, const Tr2ShaderSignatureAL& signature ); - Tr2RegisterMapAL( const Tr2ShaderAL* shaders, size_t shaderCount ); - Tr2RegisterMapAL( const Tr2RenderContextEnum::ShaderType* shaders, const Tr2ShaderSignatureAL* signatures, size_t signatureCount ); - - bool operator==( const Tr2RegisterMapAL& other ) const; - bool operator!=( const Tr2RegisterMapAL& other ) const; - - static const uint32_t MAX_RESOURCES_IN_STAGE = 32; - - uint32_t srvCount; - uint32_t uavCount; - uint32_t samplerCount; - uint8_t srvs[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; - uint8_t uavs[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; - uint8_t samplers[Tr2RenderContextEnum::SHADER_TYPE_COUNT][MAX_RESOURCES_IN_STAGE]; -}; - - -class Tr2ResourceSetDescriptionAL -{ -public: - static const uint32_t MAX_RESOURCES_IN_STAGE = 32; - - Tr2ResourceSetDescriptionAL(); - Tr2ResourceSetDescriptionAL( const Tr2ResourceSetDescriptionAL& ); - Tr2ResourceSetDescriptionAL( Tr2ResourceSetDescriptionAL&& ); - explicit Tr2ResourceSetDescriptionAL( const Tr2ShaderProgramAL& program ); - explicit Tr2ResourceSetDescriptionAL( const Tr2RegisterMapAL& registers ); - Tr2ResourceSetDescriptionAL& operator=( const Tr2ResourceSetDescriptionAL& other ); - Tr2ResourceSetDescriptionAL& operator=( Tr2ResourceSetDescriptionAL&& other ); - - bool SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ); - bool SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR ); - bool SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ); - bool SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip = 0 ); - bool SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); - bool SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); - bool SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); - bool SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ); - void ClearResources(); - - uint32_t ComputeHash() const; - - bool operator==( const Tr2ResourceSetDescriptionAL& other ) const; - -private: - struct Resource - { - enum Type - { - NONE, - BUFFER, - TEXTURE, - HEAP_VIEW, - }; - - Resource(); - - bool operator==( const Resource& other ) const; - bool Is( const Tr2BufferAL& other ) const; - bool Is( const Tr2TextureAL& other, Tr2RenderContextEnum::ColorSpace otherColorSpace ) const; - bool Is( const Tr2TextureAL& other, uint32_t otherMip ) const; - void UpdateHash( uint32_t& hash ) const; - - Tr2TextureAL texture; - Tr2BufferAL buffer; - Type type; - union - { - Tr2RenderContextEnum::ColorSpace colorSpace; - uint32_t mip; - }; - }; - - struct Sampler - { - enum Type - { - NONE, - SAMPLER, - HEAP_VIEW, - }; - - Sampler(); - - bool operator==( const Sampler& other ) const; - bool operator==( const Tr2SamplerStateAL& other ) const; - - void UpdateHash( uint32_t& hash ) const; - - Tr2SamplerStateAL sampler; - Type type; - }; - - Tr2RegisterMapAL m_registerMap; - std::unique_ptr m_srv; - std::unique_ptr m_uav; - std::unique_ptr m_samplers; - - friend class TrinityALImpl::Tr2ResourceSetAL; - friend class TrinityALImpl::Tr2RtShaderTableAL; -}; - -class Tr2ResourceSetAL -{ -public: - Tr2ResourceSetAL(); - - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ); - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const Tr2RtPipelineStateAL& pipeline, Tr2PrimaryRenderContextAL& renderContext ); - bool IsValid() const; - - Tr2ALMemoryType GetMemoryClass() const; - - ALResult SetName( const char* name ); - -private: - std::shared_ptr m_resourceSet; - - friend class Tr2RenderContextAL; -}; diff --git a/trinityal/include/Tr2RtPipelineStateAL.h b/trinityal/include/Tr2RtPipelineStateAL.h index 8e2433b76..32a38e415 100644 --- a/trinityal/include/Tr2RtPipelineStateAL.h +++ b/trinityal/include/Tr2RtPipelineStateAL.h @@ -71,6 +71,4 @@ class Tr2RtPipelineStateAL private: std::shared_ptr m_pipeline; - - friend class TrinityALImpl::Tr2ResourceSetAL; }; diff --git a/trinityal/include/Tr2RtShaderTableAL.h b/trinityal/include/Tr2RtShaderTableAL.h index ba91f784b..d29e6f119 100644 --- a/trinityal/include/Tr2RtShaderTableAL.h +++ b/trinityal/include/Tr2RtShaderTableAL.h @@ -6,7 +6,6 @@ #include "../ALResult.h" #include "../Tr2DeviceResourceAL.h" #include "Tr2ConstantBufferAL.h" -#include "Tr2ResourceSetAL.h" namespace TrinityALImpl { diff --git a/trinityal/include/Tr2SamplerStateAL.h b/trinityal/include/Tr2SamplerStateAL.h index 583ee5506..008c8e498 100644 --- a/trinityal/include/Tr2SamplerStateAL.h +++ b/trinityal/include/Tr2SamplerStateAL.h @@ -11,7 +11,6 @@ struct Tr2SamplerDescription; namespace TrinityALImpl { class Tr2SamplerStateAL; -class Tr2ResourceSetAL; } class Tr2SamplerStateAL @@ -35,7 +34,6 @@ class Tr2SamplerStateAL private: std::shared_ptr m_sampler; friend class Tr2RenderContextAL; - friend class TrinityALImpl::Tr2ResourceSetAL; }; namespace TrinityALImpl diff --git a/trinityal/include/Tr2ShaderProgramAL.h b/trinityal/include/Tr2ShaderProgramAL.h index a65fd9410..5ebcff7e7 100644 --- a/trinityal/include/Tr2ShaderProgramAL.h +++ b/trinityal/include/Tr2ShaderProgramAL.h @@ -12,7 +12,6 @@ struct Tr2RegisterMapAL; namespace TrinityALImpl { class Tr2ShaderProgramAL; -class Tr2ResourceSetAL; class PSODescription; } @@ -54,6 +53,5 @@ class Tr2ShaderProgramAL friend class Tr2RenderContextAL; friend class Tr2PrimaryRenderContextAL; - friend class TrinityALImpl::Tr2ResourceSetAL; friend class TrinityALImpl::PSODescription; }; diff --git a/trinityal/include/Tr2StaticResourceBindingsAL.h b/trinityal/include/Tr2StaticResourceBindingsAL.h new file mode 100644 index 000000000..1f50dd51f --- /dev/null +++ b/trinityal/include/Tr2StaticResourceBindingsAL.h @@ -0,0 +1,49 @@ +// Copyright © 2023 CCP ehf. + +#pragma once + +#include + +#include "../ALResult.h" +#include "../Tr2RenderContextEnum.h" +#include "Tr2SamplerStateAL.h" + +class Tr2RenderContextAL; + +class Tr2StaticResourceBindingsAL +{ +public: + bool SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ); + bool SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); + bool SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); + bool SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ); + void Clear(); + bool IsEmpty() const; + + bool operator==( const Tr2StaticResourceBindingsAL& other ) const; + + ALResult Apply( Tr2RenderContextAL& renderContext ) const; + +private: + enum Kind : uint8_t + { + KIND_SAMPLER, + KIND_SRV_HEAP_VIEW, + KIND_UAV_HEAP_VIEW, + KIND_SAMPLER_HEAP_VIEW, + }; + + struct Entry + { + Tr2SamplerStateAL sampler; + uint8_t stage; + uint8_t registerIndex; + Kind kind; + }; + + static bool SharesRegisterSpace( Kind a, Kind b ); + + bool Set( Kind kind, Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ); + + std::vector m_entries; +}; diff --git a/trinityal/include/Tr2TextureAL.h b/trinityal/include/Tr2TextureAL.h index 67071be97..dd27bec4c 100644 --- a/trinityal/include/Tr2TextureAL.h +++ b/trinityal/include/Tr2TextureAL.h @@ -9,7 +9,6 @@ namespace TrinityALImpl { class Tr2TextureAL; -class Tr2ResourceSetAL; class Tr2SwapChainAL; } @@ -79,6 +78,5 @@ class Tr2TextureAL friend class Tr2PrimaryRenderContextAL; friend class Tr2RenderContextAL; friend class TrinityALImpl::Tr2SwapChainAL; - friend class TrinityALImpl::Tr2ResourceSetAL; friend class TrinityALImpl::Tr2TextureAL; }; diff --git a/trinityal/include/TrinityAL.h b/trinityal/include/TrinityAL.h index e9d4621c1..4a053243d 100644 --- a/trinityal/include/TrinityAL.h +++ b/trinityal/include/TrinityAL.h @@ -24,7 +24,8 @@ #include "Tr2FenceAL.h" #include "Tr2GpuTimerAL.h" #include "Tr2ShaderProgramAL.h" -#include "Tr2ResourceSetAL.h" +#include "Tr2RegisterMapAL.h" +#include "Tr2StaticResourceBindingsAL.h" #include "Tr2BufferAL.h" #include "Tr2PipelineStatsQueryAL.h" #include "Tr2RtBottomLevelAccelerationStructureAL.h" diff --git a/trinityal/include/upscaling/Tr2Fsr1Upscaling.h b/trinityal/include/upscaling/Tr2Fsr1Upscaling.h index f9bd0eed4..1943a4e0a 100644 --- a/trinityal/include/upscaling/Tr2Fsr1Upscaling.h +++ b/trinityal/include/upscaling/Tr2Fsr1Upscaling.h @@ -7,7 +7,7 @@ #include "Tr2UpscalingAL.h" #include "Tr2RenderContextAL.h" #include "Tr2ShaderAL.h" -#include "Tr2ResourceSetAL.h" +#include "Tr2SamplerStateAL.h" #include "Tr2ShaderProgramAL.h" #if TRINITY_PLATFORM == TRINITY_DIRECTX12 diff --git a/trinityal/metal/Tr2RenderContextMetal.h b/trinityal/metal/Tr2RenderContextMetal.h index 37a6ad952..12863a688 100644 --- a/trinityal/metal/Tr2RenderContextMetal.h +++ b/trinityal/metal/Tr2RenderContextMetal.h @@ -9,8 +9,8 @@ #include "../include/Tr2TextureAL.h" #include "../include/Tr2SwapChainAL.h" #include "../include/Tr2CapsAL.h" -#include "../include/Tr2ResourceSetAL.h" #include "../include/Tr2SamplerStateAL.h" +#include "../include/Tr2BufferAL.h" #include "../include/Tr2ShaderProgramAL.h" #include "../include/Tr2VertexLayoutAL.h" #include "../include/Tr2ConstantBufferAL.h" @@ -25,10 +25,6 @@ class Tr2ConstantBufferAL; class Tr2ShaderAL; -class Tr2SamplerStateAL; -class Tr2TextureAL; -class Tr2ResourceSetAL; -class Tr2BufferAL; class Tr2RtShaderTableAL; class Tr2RtPipelineStateAL; struct ITr2RenderContextEvents; @@ -94,7 +90,22 @@ class Tr2RenderContextAL ALResult SetTopology( Tr2RenderContextEnum::Topology topology ); ALResult SetShaderProgram( const Tr2ShaderProgramAL& shaderProgram ); - ALResult SetResourceSet( const Tr2ResourceSetAL& resourceSet ); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2TextureAL& texture, + Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2TextureAL& texture, + uint32_t mip = 0 ) throw(); + ALResult SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw(); + + ALResult ResetResourceBindings() throw(); ALResult DrawIndexedPrimitive( uint32_t numVertices, uint32_t startIndex, @@ -301,7 +312,6 @@ class Tr2RenderContextAL Tr2PresentParametersAL m_presentParameters; Tr2ShaderProgramAL m_shaderProgram; - Tr2ResourceSetAL m_resourceSet; Tr2VertexLayoutAL m_vertexLayout; bool m_needsDrawResourceCheck; diff --git a/trinityal/metal/Tr2RenderContextMetal.mm b/trinityal/metal/Tr2RenderContextMetal.mm index 349292d96..f1e962fb6 100644 --- a/trinityal/metal/Tr2RenderContextMetal.mm +++ b/trinityal/metal/Tr2RenderContextMetal.mm @@ -12,7 +12,6 @@ #include "Tr2ConstantBufferALMetal.h" #include "Tr2RenderContextMetal.h" #include "Tr2VertexLayoutALMetal.h" -#include "Tr2ResourceSetALMetal.h" #include "Tr2ShaderProgramALMetal.h" #include "Tr2TextureALMetal.h" #include "Tr2SwapChainALMetal.h" @@ -93,7 +92,6 @@ MTLClearColor MakeClearColor( uint32_t color ) } m_vertexLayout = Tr2VertexLayoutAL(); - m_resourceSet = Tr2ResourceSetAL(); m_shaderProgram = Tr2ShaderProgramAL(); std::fill( std::begin( m_boundRenderTargets ), std::end( m_boundRenderTargets ), BoundRT{} ); @@ -523,8 +521,8 @@ MTLClearColor MakeClearColor( uint32_t color ) void Tr2RenderContextAL::CheckDrawResources() { - // Only need to check resources if we don't have a resource set and the shader has changed since the last draw. - if( m_needsDrawResourceCheck && !m_resourceSet.IsValid() ) + // Only need to check resources if the shader has changed since the last draw. + if( m_needsDrawResourceCheck ) { m_shaderProgram.m_program->SetDummyResources( *m_workQueue ); m_needsDrawResourceCheck = false; @@ -869,7 +867,6 @@ MTLClearColor MakeClearColor( uint32_t color ) m_workQueue->EndFrame(); m_vertexLayout = Tr2VertexLayoutAL(); - m_resourceSet = Tr2ResourceSetAL(); m_shaderProgram = Tr2ShaderProgramAL(); m_needsDrawResourceCheck = true; @@ -1134,46 +1131,51 @@ MTLClearColor MakeClearColor( uint32_t color ) return S_OK; } -ALResult Tr2RenderContextAL::SetResourceSet( const Tr2ResourceSetAL& resourceSet ) +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() { -#if 0 - if( m_resourceSet.m_resourceSet == resourceSet.m_resourceSet ) - { - return S_OK; - } -#endif + return S_OK; +} - TrinityALImpl::MetalContext* metalContext = GetMetalContext(); +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, + uint32_t, + const Tr2TextureAL&, + Tr2RenderContextEnum::ColorSpace ) throw() +{ + return S_OK; +} - m_resourceSet = resourceSet; - auto& rs = *resourceSet.m_resourceSet; +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() +{ + return S_OK; +} - if( rs.IsValid() ) - { - const ShaderType stages[] = { VERTEX_SHADER, PIXEL_SHADER, COMPUTE_SHADER }; - for( auto stage : stages ) - { - m_workQueue->SetBuffers( stage, - rs.m_buffers[stage], - rs.m_buffersMask[stage], - GetMetalContext()->GetHeapViewBuffer(), - rs.m_heapViewMask[stage] ); - m_workQueue->SetTextures( stage, rs.m_textures[stage], rs.m_texturesRange[stage] ); - m_workQueue->SetSamplers( stage, rs.m_samplers[stage], rs.m_samplersRange[stage] ); - } - } - else - { - const ShaderType stages[] = { VERTEX_SHADER, PIXEL_SHADER, COMPUTE_SHADER }; - for( auto stage : stages ) - { - m_workQueue->ResetBuffers( stage ); - m_workQueue->ResetTextures( stage ); - m_workQueue->ResetSamplers( stage ); - } - } +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2TextureAL&, uint32_t ) throw() +{ + return S_OK; +} - m_needsDrawResourceCheck = true; +ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2SamplerStateAL& ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::ResetResourceBindings() throw() +{ return S_OK; } @@ -1399,7 +1401,6 @@ MTLClearColor MakeClearColor( uint32_t color ) context->m_depthCompareFunction = m_depthCompareFunction; context->m_vertexLayout = Tr2VertexLayoutAL(); - context->m_resourceSet = Tr2ResourceSetAL(); context->m_shaderProgram = Tr2ShaderProgramAL(); context->m_needsDrawResourceCheck = true; diff --git a/trinityal/metal/Tr2ResourceSetALMetal.h b/trinityal/metal/Tr2ResourceSetALMetal.h deleted file mode 100644 index 95c64d45d..000000000 --- a/trinityal/metal/Tr2ResourceSetALMetal.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#pragma once - -#if TRINITY_PLATFORM == TRINITY_METAL - -#include "../include/Tr2ResourceSetAL.h" -#include "MetalContext.h" -#include "../include/Tr2RtPipelineStateAL.h" -#include "../include/Tr2ShaderProgramAL.h" - - -namespace TrinityALImpl -{ - -class Tr2ResourceSetAL : public Tr2DeviceResourceAL -{ -public: - Tr2ResourceSetAL(); - ~Tr2ResourceSetAL(); - - ALResult Create( const Tr2ResourceSetDescriptionAL& description, - const ::Tr2ShaderProgramAL& program, - Tr2PrimaryRenderContextAL& renderContext ); - ALResult Create( const Tr2ResourceSetDescriptionAL& description, - const ::Tr2RtPipelineStateAL& pipeline, - Tr2PrimaryRenderContextAL& renderContext ); - bool IsValid() const; - - void Destroy(); - Tr2ALMemoryType GetMemoryClass() const; - void Describe( Tr2DeviceResourceDescriptionAL& description ) const; - ALResult SetName( const char* name ); - -private: - id m_buffers[Tr2RenderContextEnum::SHADER_TYPE_COUNT] - [Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - id m_textures[Tr2RenderContextEnum::SHADER_TYPE_COUNT] - [Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - id m_samplers[Tr2RenderContextEnum::SHADER_TYPE_COUNT] - [Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE]; - - uint32_t m_buffersMask[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - uint32_t m_heapViewMask[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - NSRange m_texturesRange[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - NSRange m_samplersRange[Tr2RenderContextEnum::SHADER_TYPE_COUNT]; - std::string m_name; - - bool m_isValid; - - friend class ::Tr2RenderContextAL; - friend class ::Tr2RtPipelineStateAL; -}; -} - -#endif diff --git a/trinityal/metal/Tr2ResourceSetALMetal.mm b/trinityal/metal/Tr2ResourceSetALMetal.mm deleted file mode 100644 index cf09886cf..000000000 --- a/trinityal/metal/Tr2ResourceSetALMetal.mm +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#include "StdAfx.h" - -#if TRINITY_PLATFORM == TRINITY_METAL - -#include "Tr2ResourceSetALMetal.h" -#include "Tr2BufferALMetal.h" -#include "Tr2RenderContextMetal.h" -#include "Tr2SamplerStateALMetal.h" -#include "Tr2TextureALMetal.h" -#include "Tr2ShaderProgramALMetal.h" -#include "Tr2RtPipelineStateALMetal.h" -#include "ALLog.h" - -static_assert( sizeof( TrinityALImpl::ShaderResourceMask::constantBufferMask ) * 8 >= METAL_MAX_BOUND_BUFFERS, - "Please use a type with more bits for ShaderResourceMask::constantBufferMask." ); -static_assert( sizeof( TrinityALImpl::ShaderResourceMask::bufferMask ) * 8 >= METAL_MAX_BOUND_BUFFERS, - "Please use a type with more bits for ShaderResourceMask::bufferMask." ); -static_assert( sizeof( TrinityALImpl::ShaderResourceMask::textureMask ) * 8 >= METAL_MAX_BOUND_TEXTURES, - "Please use a type with more bits for ShaderResourceMask::textureMask." ); -static_assert( sizeof( TrinityALImpl::ShaderResourceMask::samplerMask ) * 8 >= METAL_MAX_BOUND_SAMPLERS, - "Please use a type with more bits for ShaderResourceMask::samplerMask." ); - - -namespace TrinityALImpl -{ -Tr2ResourceSetAL::Tr2ResourceSetAL() : m_isValid( false ) -{ - static_assert( sizeof( m_buffersMask ) * 8 >= METAL_MAX_BOUND_BUFFERS, - "Please use a type with more bits for m_buffersMask." ); - - Destroy(); -} - -Tr2ResourceSetAL::~Tr2ResourceSetAL() -{ - Destroy(); -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, - const ::Tr2RtPipelineStateAL& pipeline, - Tr2PrimaryRenderContextAL& renderContext ) -{ - Destroy(); - - if( !renderContext.IsValid() || !pipeline.IsValid() ) - { - return E_INVALIDARG; - } - - const ::Tr2ShaderProgramAL program = pipeline.m_pipeline->GetShaderProgram( 0 ); - - return Create( description, program, renderContext ); -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, - const ::Tr2ShaderProgramAL& program, - Tr2PrimaryRenderContextAL& renderContext ) -{ - Destroy(); - - if( !renderContext.IsValid() || !program.IsValid() ) - { - return E_INVALIDARG; - } - - using namespace Tr2RenderContextEnum; - const ShaderType stages[] = { VERTEX_SHADER, PIXEL_SHADER, COMPUTE_SHADER }; - for( auto stage : stages ) - { - uint32_t buffersMask = 0; - uint32_t heapViewMask = 0; - NSUInteger texturesMin = NSUIntegerMax; - NSUInteger texturesMax = 0; - - // Init required resource mask to that required by the shader. - // uint32_t bufferMask = program.m_program->m_resourceMask[stage].bufferMask; - uint32_t textureMask = program.m_program->m_resourceMask[stage].textureMask; - uint32_t samplerMask = program.m_program->m_resourceMask[stage].samplerMask; - - for( int i = 0; i < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++i ) - { - if( description.m_registerMap.srvs[stage][i] >= description.m_registerMap.srvCount ) - { - continue; - } - const Tr2ResourceSetDescriptionAL::Resource& resource = - description.m_srv[description.m_registerMap.srvs[stage][i]]; - - switch( resource.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - if( resource.buffer.IsValid() ) - { - CCP_ASSERT( i < METAL_SRV_BUFFER_COUNT ); - - const NSUInteger bufferIndex = METAL_SRV_BUFFER_OFFSET + i; - m_buffers[stage][bufferIndex] = resource.buffer.m_buffer->GetMetalBuffer(); - buffersMask |= ( 1 << bufferIndex ); - - // Remove this resource from mask. - // bufferMask &= ~(1 << bufferIndex); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::HEAP_VIEW: { - CCP_ASSERT( i < METAL_SRV_BUFFER_COUNT ); - - const NSUInteger bufferIndex = METAL_SRV_BUFFER_OFFSET + i; - heapViewMask |= ( 1 << bufferIndex ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - if( resource.texture.IsValid() ) - { - CCP_ASSERT( i < METAL_SRV_TEXTURE_COUNT ); - - const NSUInteger texIndex = METAL_SRV_TEXTURE_OFFSET + i; - - if( resource.colorSpace == COLOR_SPACE_SRGB ) - { - m_textures[stage][texIndex] = resource.texture.m_texture->GetSRGBViewMetalTexture(); - } - else - { - m_textures[stage][texIndex] = resource.texture.m_texture->GetMetalTexture(); - } - - texturesMin = std::min( texturesMin, texIndex ); - texturesMax = std::max( texturesMax, texIndex ); - // Remove this resource from mask. - textureMask &= ~( 1 << texIndex ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::NONE: - continue; - default: - CCP_AL_LOGWARN( "Unknown SRV resource type in resource set for register %d, stage %d", i, stage ); - return E_INVALIDARG; - } - } - - for( int i = 0; i < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++i ) - { - if( description.m_registerMap.uavs[stage][i] >= description.m_registerMap.uavCount ) - { - continue; - } - const Tr2ResourceSetDescriptionAL::Resource& resource = - description.m_uav[description.m_registerMap.uavs[stage][i]]; - - switch( resource.type ) - { - case Tr2ResourceSetDescriptionAL::Resource::BUFFER: - if( resource.buffer.IsValid() ) - { - CCP_ASSERT( i < METAL_UAV_BUFFER_COUNT ); - - const NSUInteger bufferIndex = METAL_UAV_BUFFER_OFFSET + i; - m_buffers[stage][bufferIndex] = resource.buffer.m_buffer->GetMetalBuffer(); - buffersMask |= ( 1 << bufferIndex ); - - // Remove this resource from mask. - // bufferMask &= ~(1 << bufferIndex); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::HEAP_VIEW: { - CCP_ASSERT( i < METAL_UAV_BUFFER_COUNT ); - - const NSUInteger bufferIndex = METAL_UAV_BUFFER_OFFSET + i; - heapViewMask |= ( 1 << bufferIndex ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::TEXTURE: - if( resource.texture.IsValid() ) - { - CCP_ASSERT( i < METAL_UAV_TEXTURE_COUNT ); - - const NSUInteger texIndex = METAL_UAV_TEXTURE_OFFSET + i; - m_textures[stage][texIndex] = resource.texture.m_texture->GetUAVMetalTexture( resource.mip ); - texturesMin = std::min( texturesMin, texIndex ); - texturesMax = std::max( texturesMax, texIndex ); - // Remove this resource from mask. - textureMask &= ~( 1 << texIndex ); - } - break; - case Tr2ResourceSetDescriptionAL::Resource::NONE: - continue; - default: - CCP_AL_LOGWARN( "Unknown UAV resource type in resource set for register %d, stage %d", i, stage ); - return E_INVALIDARG; - } - } - - NSUInteger samplersMin = NSUIntegerMax; - NSUInteger samplersMax = 0; - - for( int i = 0; i < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++i ) - { - if( description.m_registerMap.samplers[stage][i] >= description.m_registerMap.samplerCount ) - { - continue; - } - const Tr2ResourceSetDescriptionAL::Sampler& sampler = - description.m_samplers[description.m_registerMap.samplers[stage][i]]; - - if( sampler.type == Tr2ResourceSetDescriptionAL::Sampler::SAMPLER ) - { - m_samplers[stage][i] = sampler.sampler.m_sampler->GetMetalSamplerState(); - samplersMin = std::min( samplersMin, i ); - samplersMax = std::max( samplersMax, i ); - // Remove this resource from mask. - samplerMask &= ~( 1 << i ); - } - else if( sampler.type == Tr2ResourceSetDescriptionAL::Sampler::HEAP_VIEW ) - { - CCP_ASSERT( i < METAL_SRV_BUFFER_COUNT ); - const NSUInteger bufferIndex = METAL_SRV_BUFFER_OFFSET + i; - heapViewMask |= ( 1 << bufferIndex ); - } - } - - // Replace any missing resources with dummy ones. - - MetalContext* metalContext = renderContext.GetMetalContext(); - unsigned int index = 0; - // Buffers not supported yet. -#if 0 - while( bufferMask ) - { - if( bufferMask & 0x1 ) - { - // Note - Buffers for vertex shaders are NOT set via a resource set, so you if you re-set them here trouble will ensue. - } - bufferMask >>= 1; - ++index; - } -#endif - - index = 0; - while( textureMask ) - { - if( textureMask & 0x1 ) - { - m_textures[stage][index] = metalContext->GetDummyTexture( - MTLTextureType( program.m_program->m_resourceMask[stage].textureTypes[index] ) ); - texturesMin = std::min( texturesMin, index ); - texturesMax = std::max( texturesMax, index ); - } - textureMask >>= 1; - ++index; - } - - index = 0; - while( samplerMask ) - { - if( samplerMask & 0x1 ) - { - m_samplers[stage][index] = metalContext->GetDummySampler(); - samplersMin = std::min( samplersMin, index ); - samplersMax = std::max( samplersMax, index ); - } - samplerMask >>= 1; - ++index; - } - - m_buffersMask[stage] = buffersMask; - m_heapViewMask[stage] = heapViewMask; - m_texturesRange[stage] = ( texturesMin != NSUIntegerMax ) ? - NSMakeRange( texturesMin, texturesMax - texturesMin + 1 ) : - NSMakeRange( 0, 0 ); - m_samplersRange[stage] = ( samplersMin != NSUIntegerMax ) ? - NSMakeRange( samplersMin, samplersMax - samplersMin + 1 ) : - NSMakeRange( 0, 0 ); - } - - m_isValid = true; - return S_OK; -} - -bool Tr2ResourceSetAL::IsValid() const -{ - return m_isValid; -} - -void Tr2ResourceSetAL::Destroy() -{ - m_isValid = false; - - using namespace Tr2RenderContextEnum; - const ShaderType stages[] = { VERTEX_SHADER, PIXEL_SHADER, COMPUTE_SHADER }; - for( auto stage : stages ) - { - for( int i = 0; i < Tr2ResourceSetDescriptionAL::MAX_RESOURCES_IN_STAGE; ++i ) - { - m_buffers[stage][i] = nil; - m_textures[stage][i] = nil; - m_samplers[stage][i] = nil; - } - - m_buffersMask[stage] = 0; - m_heapViewMask[stage] = 0; - m_texturesRange[stage] = NSMakeRange( 0, 0 ); - m_samplersRange[stage] = NSMakeRange( 0, 0 ); - } -} - -Tr2ALMemoryType Tr2ResourceSetAL::GetMemoryClass() const -{ - return AL_MEMORY_MANAGED; -} - -void Tr2ResourceSetAL::Describe( Tr2DeviceResourceDescriptionAL& description ) const -{ - description["type"] = "Tr2ResourceSetAL"; - description["name"] = m_name; -} - -ALResult Tr2ResourceSetAL::SetName( const char* name ) -{ - m_name = name; - return S_OK; -} -} - -#endif diff --git a/trinityal/metal/Tr2RtPipelineStateALMetal.h b/trinityal/metal/Tr2RtPipelineStateALMetal.h index 680f2510a..c8e191c08 100644 --- a/trinityal/metal/Tr2RtPipelineStateALMetal.h +++ b/trinityal/metal/Tr2RtPipelineStateALMetal.h @@ -14,7 +14,6 @@ //#include "StdAfx.h" #include "Tr2ShaderProgramALMetal.h" #include "../include/Tr2RtPipelineStateAL.h" -#include "../include/Tr2ResourceSetAL.h" #include "Tr2ShaderAL.h" #include diff --git a/trinityal/metal/Tr2ShaderALMetal.h b/trinityal/metal/Tr2ShaderALMetal.h index 8bf29c80b..267242d3c 100644 --- a/trinityal/metal/Tr2ShaderALMetal.h +++ b/trinityal/metal/Tr2ShaderALMetal.h @@ -5,7 +5,6 @@ #if TRINITY_PLATFORM == TRINITY_METAL #include "../include/Tr2ShaderAL.h" -#include "Tr2ResourceSetALMetal.h" namespace TrinityALImpl diff --git a/trinityal/metal/Tr2ShaderProgramALMetal.h b/trinityal/metal/Tr2ShaderProgramALMetal.h index cb01c9748..23bb01931 100644 --- a/trinityal/metal/Tr2ShaderProgramALMetal.h +++ b/trinityal/metal/Tr2ShaderProgramALMetal.h @@ -5,9 +5,8 @@ #if TRINITY_PLATFORM == TRINITY_METAL #include "../include/Tr2ShaderProgramAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2RegisterMapAL.h" #include "Tr2ShaderALMetal.h" -#include "Tr2ResourceSetALMetal.h" #include "MetalContext.h" namespace TrinityALImpl @@ -59,7 +58,6 @@ class Tr2ShaderProgramAL : public Tr2DeviceResourceAL bool m_isValid; friend class Tr2RenderContextAL; - friend class Tr2ResourceSetAL; }; } diff --git a/trinityal/src/Tr2RegisterMapAL.cpp b/trinityal/src/Tr2RegisterMapAL.cpp new file mode 100644 index 000000000..757697f0b --- /dev/null +++ b/trinityal/src/Tr2RegisterMapAL.cpp @@ -0,0 +1,125 @@ +// Copyright © 2023 CCP ehf. + +#include "StdAfx.h" +#include "../include/Tr2RegisterMapAL.h" +#include "../include/Tr2ShaderAL.h" + + +Tr2RegisterMapAL::Tr2RegisterMapAL() : // cppcheck-suppress uninitMemberVar + srvCount( 0 ), + uavCount( 0 ), + samplerCount( 0 ) +{ +} + +Tr2RegisterMapAL::Tr2RegisterMapAL( Tr2RenderContextEnum::ShaderType stage, const Tr2ShaderSignatureAL& signature ) : + srvCount( 0 ), + uavCount( 0 ), + samplerCount( 0 ) +{ + memset( srvs, -1, sizeof( srvs ) ); + memset( uavs, -1, sizeof( uavs ) ); + memset( samplers, -1, sizeof( samplers ) ); + + for( auto it = begin( signature.registers ); it != end( signature.registers ); ++it ) + { + if( it->IsSrv() ) + { + srvs[stage][it->registerIndex] = uint8_t( srvCount++ ); + } + else if( it->IsUav() ) + { + uavs[stage][it->registerIndex] = uint8_t( uavCount++ ); + } + else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) + { + samplers[stage][it->registerIndex] = uint8_t( samplerCount++ ); + } + } +} + +Tr2RegisterMapAL::Tr2RegisterMapAL( const Tr2ShaderAL* shaders, size_t shaderCount ) : + srvCount( 0 ), + uavCount( 0 ), + samplerCount( 0 ) +{ + memset( srvs, -1, sizeof( srvs ) ); + memset( uavs, -1, sizeof( uavs ) ); + memset( samplers, -1, sizeof( samplers ) ); + + for( size_t i = 0; i < shaderCount; ++i ) + { + auto shaderType = shaders[i].GetType(); + auto& signature = shaders[i].GetSignature(); + for( auto it = begin( signature.registers ); it != end( signature.registers ); ++it ) + { + if( it->IsSrv() ) + { + srvs[shaderType][it->registerIndex] = uint8_t( srvCount++ ); + } + else if( it->IsUav() ) + { + uavs[shaderType][it->registerIndex] = uint8_t( uavCount++ ); + } + else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) + { + samplers[shaderType][it->registerIndex] = uint8_t( samplerCount++ ); + } + } + } +} + +Tr2RegisterMapAL::Tr2RegisterMapAL( const Tr2RenderContextEnum::ShaderType* shaders, const Tr2ShaderSignatureAL* signatures, size_t signatureCount ) : + srvCount( 0 ), + uavCount( 0 ), + samplerCount( 0 ) +{ + memset( srvs, -1, sizeof( srvs ) ); + memset( uavs, -1, sizeof( uavs ) ); + memset( samplers, -1, sizeof( samplers ) ); + + for( size_t i = 0; i < signatureCount; ++i ) + { + for( auto it = begin( signatures[i].registers ); it != end( signatures[i].registers ); ++it ) + { + if( it->IsSrv() ) + { + srvs[shaders[i]][it->registerIndex] = uint8_t( srvCount++ ); + } + else if( it->IsUav() ) + { + uavs[shaders[i]][it->registerIndex] = uint8_t( uavCount++ ); + } + else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) + { + samplers[shaders[i]][it->registerIndex] = uint8_t( samplerCount++ ); + } + } + } +} + +bool Tr2RegisterMapAL::operator==( const Tr2RegisterMapAL& other ) const +{ + if( srvCount != other.srvCount || uavCount != other.uavCount || samplerCount != other.samplerCount ) + { + return false; + } + if( srvCount > 0 && memcmp( srvs, other.srvs, sizeof( srvs ) ) ) + { + return false; + } + if( uavCount > 0 && memcmp( uavs, other.uavs, sizeof( uavs ) ) ) + { + return false; + } + if( samplerCount > 0 && memcmp( samplers, other.samplers, sizeof( samplers ) ) ) + { + return false; + } + return true; +} + +bool Tr2RegisterMapAL::operator!=( const Tr2RegisterMapAL& other ) const +{ + return !( *this == other ); +} diff --git a/trinityal/src/Tr2ResourceSetAL.cpp b/trinityal/src/Tr2ResourceSetAL.cpp deleted file mode 100644 index da64763b6..000000000 --- a/trinityal/src/Tr2ResourceSetAL.cpp +++ /dev/null @@ -1,605 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#include "StdAfx.h" -#include "../include/Tr2ResourceSetAL.h" -#include "../include/Tr2TextureAL.h" -#include "../include/Tr2ShaderAL.h" -#include "../include/Tr2ShaderProgramAL.h" -#include "../include/Tr2CapsAL.h" - - -#include TRINITY_AL_PLATFORM_INCLUDE( Tr2ResourceSetAL ) - - -namespace -{ - -template -void HashResourcePtr( const T& resource, uint32_t& hash ) -{ - auto p = resource.TrinityALImpl_GetObject(); - hash = CcpHashFNV1( &p, sizeof( p ), hash ); -} - -} - - -Tr2RegisterMapAL::Tr2RegisterMapAL() : // cppcheck-suppress uninitMemberVar - srvCount( 0 ), - uavCount( 0 ), - samplerCount( 0 ) -{ -} - -Tr2RegisterMapAL::Tr2RegisterMapAL( Tr2RenderContextEnum::ShaderType stage, const Tr2ShaderSignatureAL& signature ) : - srvCount( 0 ), - uavCount( 0 ), - samplerCount( 0 ) -{ - memset( srvs, -1, sizeof( srvs ) ); - memset( uavs, -1, sizeof( uavs ) ); - memset( samplers, -1, sizeof( samplers ) ); - - for( auto it = begin( signature.registers ); it != end( signature.registers ); ++it ) - { - if( it->IsSrv() ) - { - srvs[stage][it->registerIndex] = uint8_t( srvCount++ ); - } - else if( it->IsUav() ) - { - uavs[stage][it->registerIndex] = uint8_t( uavCount++ ); - } - else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) - { - samplers[stage][it->registerIndex] = uint8_t( samplerCount++ ); - } - } -} - -Tr2RegisterMapAL::Tr2RegisterMapAL( const Tr2ShaderAL* shaders, size_t shaderCount ) : - srvCount( 0 ), - uavCount( 0 ), - samplerCount( 0 ) -{ - memset( srvs, -1, sizeof( srvs ) ); - memset( uavs, -1, sizeof( uavs ) ); - memset( samplers, -1, sizeof( samplers ) ); - - for( size_t i = 0; i < shaderCount; ++i ) - { - auto shaderType = shaders[i].GetType(); - auto& signature = shaders[i].GetSignature(); - for( auto it = begin( signature.registers ); it != end( signature.registers ); ++it ) - { - if( it->IsSrv() ) - { - srvs[shaderType][it->registerIndex] = uint8_t( srvCount++ ); - } - else if( it->IsUav() ) - { - uavs[shaderType][it->registerIndex] = uint8_t( uavCount++ ); - } - else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) - { - samplers[shaderType][it->registerIndex] = uint8_t( samplerCount++ ); - } - } - } -} - -Tr2RegisterMapAL::Tr2RegisterMapAL( const Tr2RenderContextEnum::ShaderType* shaders, const Tr2ShaderSignatureAL* signatures, size_t signatureCount ) : - srvCount( 0 ), - uavCount( 0 ), - samplerCount( 0 ) -{ - memset( srvs, -1, sizeof( srvs ) ); - memset( uavs, -1, sizeof( uavs ) ); - memset( samplers, -1, sizeof( samplers ) ); - - for( size_t i = 0; i < signatureCount; ++i ) - { - for( auto it = begin( signatures[i].registers ); it != end( signatures[i].registers ); ++it ) - { - if( it->IsSrv() ) - { - srvs[shaders[i]][it->registerIndex] = uint8_t( srvCount++ ); - } - else if( it->IsUav() ) - { - uavs[shaders[i]][it->registerIndex] = uint8_t( uavCount++ ); - } - else if( it->registerType == Tr2ShaderRegisterAL::SAMPLER ) - { - samplers[shaders[i]][it->registerIndex] = uint8_t( samplerCount++ ); - } - } - } -} - -bool Tr2RegisterMapAL::operator==( const Tr2RegisterMapAL& other ) const -{ - if( srvCount != other.srvCount || uavCount != other.uavCount || samplerCount != other.samplerCount ) - { - return false; - } - if( srvCount > 0 && memcmp( srvs, other.srvs, sizeof( srvs ) ) ) - { - return false; - } - if( uavCount > 0 && memcmp( uavs, other.uavs, sizeof( uavs ) ) ) - { - return false; - } - if( samplerCount > 0 && memcmp( samplers, other.samplers, sizeof( samplers ) ) ) - { - return false; - } - return true; -} - -bool Tr2RegisterMapAL::operator!=( const Tr2RegisterMapAL& other ) const -{ - return !( *this == other ); -} - - -Tr2ResourceSetDescriptionAL::Tr2ResourceSetDescriptionAL() -{ -} - -Tr2ResourceSetDescriptionAL::Tr2ResourceSetDescriptionAL( const Tr2ResourceSetDescriptionAL& other ) : - m_registerMap( other.m_registerMap ) -{ - if( m_registerMap.srvCount > 0 ) - { - m_srv.reset( new Resource[m_registerMap.srvCount] ); - std::copy_n( other.m_srv.get(), m_registerMap.srvCount, m_srv.get() ); - } - if( m_registerMap.uavCount > 0 ) - { - m_uav.reset( new Resource[m_registerMap.uavCount] ); - std::copy_n( other.m_uav.get(), m_registerMap.uavCount, m_uav.get() ); - } - if( m_registerMap.samplerCount > 0 ) - { - m_samplers.reset( new Sampler[m_registerMap.samplerCount] ); - std::copy_n( other.m_samplers.get(), m_registerMap.samplerCount, m_samplers.get() ); - } -} - -Tr2ResourceSetDescriptionAL::Tr2ResourceSetDescriptionAL( Tr2ResourceSetDescriptionAL&& other ) : - m_registerMap( other.m_registerMap ) -{ - std::swap( m_srv, other.m_srv ); - std::swap( m_uav, other.m_uav ); - std::swap( m_samplers, other.m_samplers ); -} - -Tr2ResourceSetDescriptionAL::Tr2ResourceSetDescriptionAL( const Tr2ShaderProgramAL& program ) : - m_registerMap( program.GetRegisterMap() ) -{ - if( m_registerMap.srvCount > 0 ) - { - m_srv.reset( new Resource[m_registerMap.srvCount] ); - } - if( m_registerMap.uavCount > 0 ) - { - m_uav.reset( new Resource[m_registerMap.uavCount] ); - } - if( m_registerMap.samplerCount > 0 ) - { - m_samplers.reset( new Sampler[m_registerMap.samplerCount] ); - } -} - -Tr2ResourceSetDescriptionAL::Tr2ResourceSetDescriptionAL( const Tr2RegisterMapAL& registers ) : - m_registerMap( registers ) -{ - if( m_registerMap.srvCount > 0 ) - { - m_srv.reset( new Resource[m_registerMap.srvCount] ); - } - if( m_registerMap.uavCount > 0 ) - { - m_uav.reset( new Resource[m_registerMap.uavCount] ); - } - if( m_registerMap.samplerCount > 0 ) - { - m_samplers.reset( new Sampler[m_registerMap.samplerCount] ); - } -} - -Tr2ResourceSetDescriptionAL& Tr2ResourceSetDescriptionAL::operator=( const Tr2ResourceSetDescriptionAL& other ) -{ - if( &other == this ) - { - return *this; - } - m_registerMap = other.m_registerMap; - if( m_registerMap.srvCount > 0 ) - { - m_srv.reset( new Resource[m_registerMap.srvCount] ); - std::copy_n( other.m_srv.get(), m_registerMap.srvCount, m_srv.get() ); - } - else - { - m_srv.reset(); - } - if( m_registerMap.uavCount > 0 ) - { - m_uav.reset( new Resource[m_registerMap.uavCount] ); - std::copy_n( other.m_uav.get(), m_registerMap.uavCount, m_uav.get() ); - } - else - { - m_uav.reset(); - } - if( m_registerMap.samplerCount > 0 ) - { - m_samplers.reset( new Sampler[m_registerMap.samplerCount] ); - std::copy_n( other.m_samplers.get(), m_registerMap.samplerCount, m_samplers.get() ); - } - else - { - m_samplers.reset(); - } - return *this; -} - -Tr2ResourceSetDescriptionAL& Tr2ResourceSetDescriptionAL::operator=( Tr2ResourceSetDescriptionAL&& other ) -{ - if( &other == this ) - { - return *this; - } - m_registerMap = other.m_registerMap; - std::swap( m_srv, other.m_srv ); - other.m_srv.reset(); - std::swap( m_uav, other.m_uav ); - other.m_uav.reset(); - std::swap( m_samplers, other.m_samplers ); - other.m_samplers.reset(); - return *this; -} - - -bool Tr2ResourceSetDescriptionAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) -{ - if( m_registerMap.srvCount == 0 ) - { - return false; - } - auto index = m_registerMap.srvs[stage][registerIndex]; - if( index >= m_registerMap.srvCount ) - { - return false; - } - auto& resource = m_srv[index]; - if( resource.Is( buffer ) ) - { - return false; - } - resource.type = Resource::BUFFER; - resource.buffer = buffer; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace ) -{ - if( m_registerMap.srvCount == 0 ) - { - return false; - } - auto index = m_registerMap.srvs[stage][registerIndex]; - if( index >= m_registerMap.srvCount ) - { - return false; - } - auto& resource = m_srv[index]; - if( resource.Is( texture, colorSpace ) ) - { - return false; - } - resource.type = Resource::TEXTURE; - resource.texture = texture; - resource.colorSpace = colorSpace; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) -{ - if( m_registerMap.uavCount == 0 ) - { - return false; - } - auto index = m_registerMap.uavs[stage][registerIndex]; - if( index >= m_registerMap.uavCount ) - { - return false; - } - auto& resource = m_uav[index]; - if( resource.Is( buffer ) ) - { - return false; - } - resource.type = Resource::BUFFER; - resource.buffer = buffer; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip ) -{ - if( m_registerMap.uavCount == 0 ) - { - return false; - } - auto index = m_registerMap.uavs[stage][registerIndex]; - if( index >= m_registerMap.uavCount ) - { - return false; - } - auto& resource = m_uav[index]; - if( resource.Is( texture, mip ) ) - { - return false; - } - resource.type = Resource::TEXTURE; - resource.texture = texture; - resource.mip = mip; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) -{ - if( m_registerMap.srvCount == 0 ) - { - return false; - } - auto index = m_registerMap.srvs[stage][registerIndex]; - if( index >= m_registerMap.srvCount ) - { - return false; - } - auto& resource = m_srv[index]; - if( resource.type == Resource::HEAP_VIEW ) - { - return false; - } - resource.type = Resource::HEAP_VIEW; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) -{ - if( m_registerMap.uavCount == 0 ) - { - return false; - } - auto index = m_registerMap.uavs[stage][registerIndex]; - if( index >= m_registerMap.uavCount ) - { - return false; - } - auto& resource = m_uav[index]; - if( resource.type == Resource::HEAP_VIEW ) - { - return false; - } - resource.type = Resource::HEAP_VIEW; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) -{ - if( m_registerMap.samplerCount == 0 ) - { - return false; - } - auto index = m_registerMap.samplers[stage][registerIndex]; - if( index >= m_registerMap.samplerCount ) - { - return false; - } - auto& resource = m_samplers[index]; - if( resource.type == Sampler::HEAP_VIEW ) - { - return false; - } - resource.type = Sampler::HEAP_VIEW; - return true; -} - -bool Tr2ResourceSetDescriptionAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) -{ - if( m_registerMap.samplerCount == 0 ) - { - return false; - } - auto index = m_registerMap.samplers[stage][registerIndex]; - if( index >= m_registerMap.samplerCount ) - { - return false; - } - auto& resource = m_samplers[index]; - if( resource.type == Sampler::SAMPLER && resource.sampler == sampler ) - { - return false; - } - resource.sampler = sampler; - resource.type = Sampler::SAMPLER; - return true; -} - -bool Tr2ResourceSetDescriptionAL::operator==( const Tr2ResourceSetDescriptionAL& other ) const -{ - return m_srv == other.m_srv && m_uav == other.m_uav && m_samplers == other.m_samplers; -} - -void Tr2ResourceSetDescriptionAL::ClearResources() -{ - for( uint32_t i = 0; i < m_registerMap.srvCount; ++i ) - { - auto& srv = m_srv[i]; - srv.type = Resource::NONE; - srv.texture = Tr2TextureAL(); - srv.buffer = Tr2BufferAL(); - } - for( uint32_t i = 0; i < m_registerMap.uavCount; ++i ) - { - auto& uav = m_uav[i]; - uav.type = Resource::NONE; - uav.texture = Tr2TextureAL(); - uav.buffer = Tr2BufferAL(); - } -} - -uint32_t Tr2ResourceSetDescriptionAL::ComputeHash() const -{ - uint32_t hash = 0; - for( uint32_t i = 0; i < m_registerMap.srvCount; ++i ) - { - m_srv[i].UpdateHash( hash ); - } - for( uint32_t i = 0; i < m_registerMap.uavCount; ++i ) - { - m_uav[i].UpdateHash( hash ); - } - for( uint32_t i = 0; i < m_registerMap.samplerCount; ++i ) - { - m_samplers[i].UpdateHash( hash ); - } - return hash; -} - - -Tr2ResourceSetDescriptionAL::Resource::Resource() : - type( NONE ), - colorSpace( Tr2RenderContextEnum::COLOR_SPACE_LINEAR ) -{ -} - -bool Tr2ResourceSetDescriptionAL::Resource::operator==( const Resource& other ) const -{ - return type == other.type && buffer == other.buffer && texture == other.texture; -} - -bool Tr2ResourceSetDescriptionAL::Resource::Is( const Tr2BufferAL& other ) const -{ - return type == BUFFER && buffer == other; -} - -bool Tr2ResourceSetDescriptionAL::Resource::Is( const Tr2TextureAL& other, Tr2RenderContextEnum::ColorSpace otherColorSpace ) const -{ - return type == TEXTURE && texture == other && colorSpace == otherColorSpace; -} - -bool Tr2ResourceSetDescriptionAL::Resource::Is( const Tr2TextureAL& other, uint32_t otherMip ) const -{ - return type == TEXTURE && texture == other && mip == otherMip; -} - -void Tr2ResourceSetDescriptionAL::Resource::UpdateHash( uint32_t& hash ) const -{ - if( type == BUFFER ) - { - HashResourcePtr( buffer, hash ); - } - else if( type == TEXTURE ) - { - HashResourcePtr( texture, hash ); - } - else if( type == HEAP_VIEW ) - { - hash = CcpHashFNV1( &type, sizeof( type ), hash ); - } -} - -Tr2ResourceSetDescriptionAL::Sampler::Sampler() : - type( NONE ) -{ -} - -bool Tr2ResourceSetDescriptionAL::Sampler::operator==( const Sampler& other ) const -{ - return sampler == other.sampler && type == other.type; -} - -bool Tr2ResourceSetDescriptionAL::Sampler::operator==( const Tr2SamplerStateAL& other ) const -{ - return sampler == other && type == SAMPLER; -} - -void Tr2ResourceSetDescriptionAL::Sampler::UpdateHash( uint32_t& hash ) const -{ - if( type == SAMPLER ) - { - HashResourcePtr( sampler, hash ); - } - else if( type == HEAP_VIEW ) - { - hash = CcpHashFNV1( &type, sizeof( type ), hash ); - } -} - - -namespace -{ -std::shared_ptr nullRS = std::make_shared(); -} - - -Tr2ResourceSetAL::Tr2ResourceSetAL() : - m_resourceSet( nullRS ) -{ -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ) -{ - m_resourceSet = std::make_shared(); - auto result = m_resourceSet->Create( description, program, renderContext ); - if( FAILED( result ) ) - { - m_resourceSet = nullRS; - } - return result; -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL& description, const Tr2RtPipelineStateAL& pipeline, Tr2PrimaryRenderContextAL& renderContext ) -{ -#if TRINITY_PLATFORM_SUPPORTS_RAY_TRACING - m_resourceSet = std::make_shared(); - auto result = m_resourceSet->Create( description, pipeline, renderContext ); - if( FAILED( result ) ) - { - m_resourceSet = nullRS; - } - return result; -#else - m_resourceSet = nullRS; - return E_FAIL; -#endif -} - -bool Tr2ResourceSetAL::IsValid() const -{ - return m_resourceSet->IsValid(); -} - -Tr2ALMemoryType Tr2ResourceSetAL::GetMemoryClass() const -{ - return m_resourceSet->GetMemoryClass(); -} - -ALResult Tr2ResourceSetAL::SetName( const char* name ) -{ - if( !IsValid() ) - { - return E_INVALIDCALL; - } - if( !name ) - { - return E_INVALIDARG; - } - return m_resourceSet->SetName( name ); -} diff --git a/trinityal/src/Tr2StaticResourceBindingsAL.cpp b/trinityal/src/Tr2StaticResourceBindingsAL.cpp new file mode 100644 index 000000000..c441518f2 --- /dev/null +++ b/trinityal/src/Tr2StaticResourceBindingsAL.cpp @@ -0,0 +1,117 @@ +// Copyright © 2023 CCP ehf. + +#include "StdAfx.h" +#include "../include/Tr2StaticResourceBindingsAL.h" +#include "../include/Tr2RenderContextAL.h" + + +bool Tr2StaticResourceBindingsAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) +{ + return Set( KIND_SAMPLER, stage, registerIndex, sampler ); +} + +bool Tr2StaticResourceBindingsAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) +{ + return Set( KIND_SRV_HEAP_VIEW, stage, registerIndex, Tr2SamplerStateAL() ); +} + +bool Tr2StaticResourceBindingsAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) +{ + return Set( KIND_UAV_HEAP_VIEW, stage, registerIndex, Tr2SamplerStateAL() ); +} + +bool Tr2StaticResourceBindingsAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) +{ + return Set( KIND_SAMPLER_HEAP_VIEW, stage, registerIndex, Tr2SamplerStateAL() ); +} + +void Tr2StaticResourceBindingsAL::Clear() +{ + m_entries.clear(); +} + +bool Tr2StaticResourceBindingsAL::IsEmpty() const +{ + return m_entries.empty(); +} + +bool Tr2StaticResourceBindingsAL::operator==( const Tr2StaticResourceBindingsAL& other ) const +{ + if( m_entries.size() != other.m_entries.size() ) + { + return false; + } + for( size_t i = 0; i < m_entries.size(); ++i ) + { + auto& entry = m_entries[i]; + auto& otherEntry = other.m_entries[i]; + if( entry.kind != otherEntry.kind || entry.stage != otherEntry.stage || entry.registerIndex != otherEntry.registerIndex ) + { + return false; + } + if( !( entry.sampler == otherEntry.sampler ) ) + { + return false; + } + } + return true; +} + +ALResult Tr2StaticResourceBindingsAL::Apply( Tr2RenderContextAL& renderContext ) const +{ + for( const auto& entry : m_entries ) + { + auto stage = Tr2RenderContextEnum::ShaderType( entry.stage ); + switch( entry.kind ) + { + case KIND_SAMPLER: + CR_RETURN_HR( renderContext.SetSampler( stage, entry.registerIndex, entry.sampler ) ); + break; + case KIND_SRV_HEAP_VIEW: + CR_RETURN_HR( renderContext.SetSrvHeapView( stage, entry.registerIndex ) ); + break; + case KIND_UAV_HEAP_VIEW: + CR_RETURN_HR( renderContext.SetUavHeapView( stage, entry.registerIndex ) ); + break; + case KIND_SAMPLER_HEAP_VIEW: + CR_RETURN_HR( renderContext.SetSamplerHeapView( stage, entry.registerIndex ) ); + break; + } + } + return S_OK; +} + +bool Tr2StaticResourceBindingsAL::SharesRegisterSpace( Kind a, Kind b ) +{ + if( a == b ) + { + return true; + } + return ( a == KIND_SAMPLER || a == KIND_SAMPLER_HEAP_VIEW ) && ( b == KIND_SAMPLER || b == KIND_SAMPLER_HEAP_VIEW ); +} + +bool Tr2StaticResourceBindingsAL::Set( Kind kind, Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) +{ + for( auto& entry : m_entries ) + { + if( entry.stage != uint8_t( stage ) || entry.registerIndex != uint8_t( registerIndex ) || !SharesRegisterSpace( entry.kind, kind ) ) + { + continue; + } + if( entry.kind == kind && entry.sampler == sampler ) + { + return false; + } + entry.kind = kind; + entry.sampler = sampler; + return true; + } + + Entry entry; + entry.sampler = sampler; + entry.stage = uint8_t( stage ); + entry.registerIndex = uint8_t( registerIndex ); + entry.kind = kind; + m_entries.push_back( entry ); + return true; +} diff --git a/trinityal/src/upscaling/Tr2Fsr1Upscaling.cpp b/trinityal/src/upscaling/Tr2Fsr1Upscaling.cpp index 8611290af..42a4a266d 100644 --- a/trinityal/src/upscaling/Tr2Fsr1Upscaling.cpp +++ b/trinityal/src/upscaling/Tr2Fsr1Upscaling.cpp @@ -182,15 +182,9 @@ Tr2UpscalingAL::Result Tr2Fsr1UpscalingContext::Dispatch( Tr2UpscalingAL::Dispat renderContext.SetShaderProgram( m_easuProgram ); - Tr2ResourceSetDescriptionAL desc( m_easuProgram ); - desc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, FSR1::SRV_REGISTER_INDEX, *dispatchParameters.input ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, FSR1::UAV_REGISTER_INDEX, *dispatchParameters.output ); - desc.SetSampler( Tr2RenderContextEnum::COMPUTE_SHADER, 0, m_sampler ); - - Tr2ResourceSetAL resourceSet; - resourceSet.Create( desc, m_easuProgram, m_params.renderContext.GetPrimaryRenderContext() ); - - renderContext.SetResourceSet( resourceSet ); + renderContext.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, FSR1::SRV_REGISTER_INDEX, *dispatchParameters.input ); + renderContext.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, FSR1::UAV_REGISTER_INDEX, *dispatchParameters.output ); + renderContext.SetSampler( Tr2RenderContextEnum::COMPUTE_SHADER, 0, m_sampler ); renderContext.SetConstants( m_constantBuffer, Tr2RenderContextEnum::COMPUTE_SHADER, 0 ); diff --git a/trinityal/stub/Tr2RenderContextStub.cpp b/trinityal/stub/Tr2RenderContextStub.cpp index 797c1a342..eaff70566 100644 --- a/trinityal/stub/Tr2RenderContextStub.cpp +++ b/trinityal/stub/Tr2RenderContextStub.cpp @@ -305,7 +305,47 @@ ALResult Tr2RenderContextAL::SetRenderStates( const uint32_t*, uint32_t ) return S_OK; } -ALResult Tr2RenderContextAL::SetResourceSet( const Tr2ResourceSetAL& ) +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2TextureAL&, Tr2RenderContextEnum::ColorSpace ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2TextureAL&, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2SamplerStateAL& ) throw() +{ + return S_OK; +} + +ALResult Tr2RenderContextAL::ResetResourceBindings() throw() { return S_OK; } diff --git a/trinityal/stub/Tr2RenderContextStub.h b/trinityal/stub/Tr2RenderContextStub.h index 2d781346b..c702b4997 100644 --- a/trinityal/stub/Tr2RenderContextStub.h +++ b/trinityal/stub/Tr2RenderContextStub.h @@ -20,7 +20,6 @@ class Tr2VertexLayoutAL; class Tr2ShaderAL; class Tr2SamplerStateAL; class Tr2TextureAL; -class Tr2ResourceSetAL; class Tr2BufferAL; class Tr2RtShaderTableAL; class Tr2RtPipelineStateAL; @@ -111,7 +110,16 @@ class Tr2RenderContextAL return E_FAIL; } - ALResult SetResourceSet( const Tr2ResourceSetAL& resourceSet ); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetSrv( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2BufferAL& buffer ) throw(); + ALResult SetUav( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2TextureAL& texture, uint32_t mip = 0 ) throw(); + ALResult SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw(); + ALResult SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) throw(); + + ALResult ResetResourceBindings() throw(); ALResult DrawIndexedPrimitive( uint32_t numVertices, diff --git a/trinityal/stub/Tr2ResourceSetALStub.cpp b/trinityal/stub/Tr2ResourceSetALStub.cpp deleted file mode 100644 index 91c54f6ef..000000000 --- a/trinityal/stub/Tr2ResourceSetALStub.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#include "StdAfx.h" - -#if TRINITY_PLATFORM == TRINITY_STUB - -#include "Tr2ResourceSetALStub.h" - -namespace TrinityALImpl -{ -Tr2ResourceSetAL::Tr2ResourceSetAL() : - m_isValid( false ) -{ -} - -ALResult Tr2ResourceSetAL::Create( const Tr2ResourceSetDescriptionAL&, const ::Tr2ShaderProgramAL&, Tr2PrimaryRenderContextAL& ) -{ - m_isValid = true; - return S_OK; -} - -bool Tr2ResourceSetAL::IsValid() const -{ - return m_isValid; -} - -void Tr2ResourceSetAL::Destroy() -{ - m_isValid = false; -} - -Tr2ALMemoryType Tr2ResourceSetAL::GetMemoryClass() const -{ - return AL_MEMORY_MANAGED; -} - -void Tr2ResourceSetAL::Describe( Tr2DeviceResourceDescriptionAL& ) const -{ -} - -ALResult Tr2ResourceSetAL::SetName( const char* ) -{ - return S_OK; -} -} - -#endif \ No newline at end of file diff --git a/trinityal/stub/Tr2ResourceSetALStub.h b/trinityal/stub/Tr2ResourceSetALStub.h deleted file mode 100644 index 19198aca9..000000000 --- a/trinityal/stub/Tr2ResourceSetALStub.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright © 2023 CCP ehf. - -#pragma once - -#if TRINITY_PLATFORM == TRINITY_STUB - -#include "../include/Tr2ResourceSetAL.h" - -namespace TrinityALImpl -{ -class Tr2ResourceSetAL : public Tr2DeviceResourceAL -{ -public: - Tr2ResourceSetAL(); - - ALResult Create( const Tr2ResourceSetDescriptionAL& description, const ::Tr2ShaderProgramAL& program, Tr2PrimaryRenderContextAL& renderContext ); - bool IsValid() const; - - void Destroy(); - Tr2ALMemoryType GetMemoryClass() const; - void Describe( Tr2DeviceResourceDescriptionAL& description ) const; - ALResult SetName( const char* name ); - -private: - bool m_isValid; -}; -} - -#endif \ No newline at end of file diff --git a/trinityal/stub/Tr2ShaderProgramALStub.h b/trinityal/stub/Tr2ShaderProgramALStub.h index a40bb55ec..8135bdc7f 100644 --- a/trinityal/stub/Tr2ShaderProgramALStub.h +++ b/trinityal/stub/Tr2ShaderProgramALStub.h @@ -5,7 +5,7 @@ #if TRINITY_PLATFORM == TRINITY_STUB #include "../include/Tr2ShaderProgramAL.h" -#include "../include/Tr2ResourceSetAL.h" +#include "../include/Tr2RegisterMapAL.h" namespace TrinityALImpl { diff --git a/trinityal/tests/Compute.cpp b/trinityal/tests/Compute.cpp index bfa33a5da..4a9320bad 100644 --- a/trinityal/tests/Compute.cpp +++ b/trinityal/tests/Compute.cpp @@ -31,17 +31,12 @@ TEST_F( Compute, CanReadCSResult ) Tr2BufferAL output; ASSERT_HRESULT_SUCCEEDED( output.Create( PIXEL_FORMAT_R32G32B32A32_FLOAT, 1, Tr2GpuUsage::UNORDERED_ACCESS, Tr2CpuUsage::READ, nullptr, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ); - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->RunComputeShader( 1, 1, 1 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( Tr2ResourceSetAL() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->ResetResourceBindings() ); const float* data; ASSERT_HRESULT_SUCCEEDED( output.MapForReading( data, *renderContext ) ); @@ -84,21 +79,14 @@ TEST_F( Compute, DISABLED_CanAddInCS ) Tr2BufferAL output; ASSERT_HRESULT_SUCCEEDED( output.Create( PIXEL_FORMAT_R32G32B32A32_FLOAT, 1, Tr2GpuUsage::UNORDERED_ACCESS, Tr2CpuUsage::READ, nullptr, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, arg1 ); - desc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, arg2 ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, arg1 ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, arg2 ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->RunComputeShader( 1, 1, 1 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( Tr2ResourceSetAL() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->ResetResourceBindings() ); const float* data; ASSERT_HRESULT_SUCCEEDED( output.MapForReading( data, *renderContext ) ); @@ -146,23 +134,15 @@ TEST_F( Compute, CanAddConstantInCS ) Tr2BufferAL output; ASSERT_HRESULT_SUCCEEDED( output.Create( PIXEL_FORMAT_R32G32B32A32_FLOAT, 1, Tr2GpuUsage::UNORDERED_ACCESS, Tr2CpuUsage::READ, nullptr, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, arg1 ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); - + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, arg1 ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( arg2, COMPUTE_SHADER, 1 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->RunComputeShader( 1, 1, 1 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( Tr2ResourceSetAL() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->ResetResourceBindings() ); const float* readData = nullptr; ASSERT_HRESULT_SUCCEEDED( output.MapForReading( readData, *renderContext ) ); @@ -222,21 +202,14 @@ TEST_F( Compute, DISABLED_CanRead2DTextureInCS ) Tr2BufferAL output; ASSERT_HRESULT_SUCCEEDED( output.Create( PIXEL_FORMAT_R32G32B32A32_FLOAT, 1, Tr2GpuUsage::UNORDERED_ACCESS, Tr2CpuUsage::READ, nullptr, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, input ); - desc.SetSampler( Tr2RenderContextEnum::COMPUTE_SHADER, 0, sampl ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 0, input ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::COMPUTE_SHADER, 0, sampl ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->RunComputeShader( 1, 1, 1 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( Tr2ResourceSetAL() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->ResetResourceBindings() ); const float* data; ASSERT_HRESULT_SUCCEEDED( output.MapForReading( data, *renderContext ) ); @@ -267,19 +240,12 @@ TEST_F( Compute, CanDispatchCSGroups ) Tr2BufferAL output; ASSERT_HRESULT_SUCCEEDED( output.Create( PIXEL_FORMAT_R32_UINT, 1, Tr2GpuUsage::UNORDERED_ACCESS, Tr2CpuUsage::READ, nullptr, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, output ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->RunComputeShader( 2, 2, 2 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( Tr2ResourceSetAL() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->ResetResourceBindings() ); const uint32_t* data; ASSERT_HRESULT_SUCCEEDED( output.MapForReading( data, *renderContext ) ); diff --git a/trinityal/tests/Raytracing.cpp b/trinityal/tests/Raytracing.cpp index 5ac5c879f..cef48ebb6 100644 --- a/trinityal/tests/Raytracing.cpp +++ b/trinityal/tests/Raytracing.cpp @@ -337,8 +337,7 @@ struct QuadRenderer }; CR_RETURN_HR( m_quadVb.Create( VB_STRIDE, sizeof( quad ) / VB_STRIDE, Tr2GpuUsage::VERTEX_BUFFER, Tr2CpuUsage::NONE, quad, *renderContext ) ); - Tr2SamplerStateAL sampl; - CR_RETURN_HR( sampl.Create( + CR_RETURN_HR( m_sampler.Create( Tr2SamplerDescription( Tr2RenderContextEnum::TF_POINT, Tr2RenderContextEnum::TA_WRAP, @@ -347,11 +346,7 @@ struct QuadRenderer 0.0f ), *renderContext ) ); - Tr2ResourceSetDescriptionAL resourceSetDescription( m_shaderProgram ); - resourceSetDescription.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, texture ); - resourceSetDescription.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - CR_RETURN_HR( m_resourceSet.Create( resourceSetDescription, m_shaderProgram, *renderContext ) ); + m_texture = texture; return S_OK; } @@ -364,7 +359,8 @@ struct QuadRenderer CR_RETURN_HR( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); CR_RETURN_HR( renderContext->SetStreamSource( 0, m_quadVb, 0, VB_STRIDE ) ); CR_RETURN_HR( renderContext->SetShaderProgram( m_shaderProgram ) ); - CR_RETURN_HR( renderContext->SetResourceSet( m_resourceSet ) ); + CR_RETURN_HR( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, m_texture ) ); + CR_RETURN_HR( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, m_sampler ) ); CR_RETURN_HR( renderContext->DrawPrimitive( 0, 2 ) ); return S_OK; } @@ -396,7 +392,8 @@ struct QuadRenderer } Tr2ShaderProgramAL m_shaderProgram; - Tr2ResourceSetAL m_resourceSet; + Tr2TextureAL m_texture; + Tr2SamplerStateAL m_sampler; Tr2BufferAL m_quadVb; Tr2VertexLayoutAL m_vertexLayout; static const uint32_t VB_STRIDE = 5 * sizeof( float ); @@ -503,17 +500,6 @@ TEST_F( Raytracing, TraceRays ) Tr2RtTopLevelAccelerationStructureAL tlas; ASSERT_HRESULT_SUCCEEDED( tlas.Create( 1, &instance, Tr2RtBuildFlags::PREFER_FAST_TRACE, *renderContext ) ); - auto shaderType = Tr2RenderContextEnum::COMPUTE_SHADER; - Tr2RegisterMapAL registerMap = Tr2RegisterMapAL( &shaderType, &signature, 1 ); - - // We need to insert a UAV barrier before using the acceleration structures in a raytracing - Tr2ResourceSetDescriptionAL rsDesc( registerMap ); - rsDesc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ); // accelerationStructure - rsDesc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, resultTex ); // RTOutput - - Tr2ResourceSetAL rs; - rs.Create( rsDesc, state, *renderContext ); - QuadRenderer quadRenderer; ASSERT_HRESULT_SUCCEEDED( quadRenderer.Create( resultTex, renderContext ) ); @@ -546,7 +532,9 @@ TEST_F( Raytracing, TraceRays ) ASSERT_HRESULT_SUCCEEDED( renderContext->ClearUav( resultTex, 0, clearColor ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::COMPUTE_SHADER, 0 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( rs ) ); + // We need to insert a UAV barrier before using the acceleration structures in a raytracing + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ) ); // accelerationStructure + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, resultTex ) ); // RTOutput // mac specific renderContext->UseAccelerationStructure( tlas ); @@ -629,17 +617,6 @@ TEST_F( Raytracing, CanUpdateBlas ) Tr2RtTopLevelAccelerationStructureAL tlas; ASSERT_HRESULT_SUCCEEDED( tlas.Create( 1, &instance, Tr2RtBuildFlags::PREFER_FAST_TRACE, *renderContext ) ); - auto shaderType = Tr2RenderContextEnum::COMPUTE_SHADER; - Tr2RegisterMapAL registerMap = Tr2RegisterMapAL( &shaderType, &signature, 1 ); - - // We need to insert a UAV barrier before using the acceleration structures in a raytracing - Tr2ResourceSetDescriptionAL rsDesc( registerMap ); - rsDesc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ); // accelerationStructure - rsDesc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, resultTex ); // RTOutput - - Tr2ResourceSetAL rs; - rs.Create( rsDesc, state, *renderContext ); - QuadRenderer quadRenderer; ASSERT_HRESULT_SUCCEEDED( quadRenderer.Create( resultTex, renderContext ) ); @@ -689,7 +666,9 @@ TEST_F( Raytracing, CanUpdateBlas ) ASSERT_HRESULT_SUCCEEDED( renderContext->ClearUav( resultTex, 0, clearColor ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::COMPUTE_SHADER, 0 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( rs ) ); + // We need to insert a UAV barrier before using the acceleration structures in a raytracing + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ) ); // accelerationStructure + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, resultTex ) ); // RTOutput // mac specific renderContext->UseAccelerationStructure( tlas ); @@ -805,16 +784,6 @@ TEST_F( Raytracing, CanUseLocalConstants ) Tr2RtTopLevelAccelerationStructureAL tlas; ASSERT_HRESULT_SUCCEEDED( tlas.Create( 2, instances, Tr2RtBuildFlags::PREFER_FAST_TRACE, *renderContext ) ); - auto shaderType = Tr2RenderContextEnum::COMPUTE_SHADER; - Tr2RegisterMapAL registerMap = Tr2RegisterMapAL( &shaderType, &globalSignature, 1 ); - - Tr2ResourceSetDescriptionAL rsDesc( registerMap ); - rsDesc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ); - rsDesc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, result ); - - Tr2ResourceSetAL rs; - rs.Create( rsDesc, state, *renderContext ); - QuadRenderer quadRenderer; ASSERT_HRESULT_SUCCEEDED( quadRenderer.Create( result, renderContext ) ); @@ -850,7 +819,8 @@ TEST_F( Raytracing, CanUseLocalConstants ) ASSERT_HRESULT_SUCCEEDED( renderContext->ClearUav( result, 0, clearColor ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::COMPUTE_SHADER, 0 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( rs ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, result ) ); renderContext->UseAccelerationStructure( tlas ); @@ -990,16 +960,6 @@ TEST_F( Raytracing, CanUsePerObjectData ) Tr2RtTopLevelAccelerationStructureAL tlas; ASSERT_HRESULT_SUCCEEDED( tlas.Create( 2, instances, Tr2RtBuildFlags::PREFER_FAST_TRACE, *renderContext ) ); - auto shaderType = Tr2RenderContextEnum::COMPUTE_SHADER; - Tr2RegisterMapAL registerMap = Tr2RegisterMapAL( &shaderType, &globalSignature, 1 ); - - Tr2ResourceSetDescriptionAL rsDesc( registerMap ); - rsDesc.SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ); - rsDesc.SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, result ); - - Tr2ResourceSetAL rs; - rs.Create( rsDesc, state, *renderContext ); - QuadRenderer quadRenderer; ASSERT_HRESULT_SUCCEEDED( quadRenderer.Create( result, renderContext ) ); @@ -1035,7 +995,8 @@ TEST_F( Raytracing, CanUsePerObjectData ) ASSERT_HRESULT_SUCCEEDED( renderContext->ClearUav( result, 0, clearColor ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::COMPUTE_SHADER, 0 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( rs ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::COMPUTE_SHADER, 1, tlas.GetBuffer() ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::COMPUTE_SHADER, 0, result ) ); renderContext->UseAccelerationStructure( tlas ); diff --git a/trinityal/tests/Rendering.cpp b/trinityal/tests/Rendering.cpp index 0d520b75e..8a2211438 100644 --- a/trinityal/tests/Rendering.cpp +++ b/trinityal/tests/Rendering.cpp @@ -521,13 +521,6 @@ TEST_F( Rendering, CanSampleTexture ) uint32_t g = 127; - Tr2ResourceSetDescriptionAL resourceSetDescription( sp ); - resourceSetDescription.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - resourceSetDescription.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( resourceSetDescription, sp, *renderContext ) ); - auto frame = [&] { ASSERT_HRESULT_SUCCEEDED( renderContext->BeginScene() ); ASSERT_HRESULT_SUCCEEDED( renderContext->Clear( Tr2RenderContextEnum::CLEARFLAGS_TARGET, 0xff000000 | ( g & 0xff ), 1.0f ) ); @@ -538,7 +531,8 @@ TEST_F( Rendering, CanSampleTexture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 1 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -648,14 +642,6 @@ TEST_F( Rendering, CanSampleMipMappedTexture ) std::numeric_limits::max() ), *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - ASSERT_HRESULT_SUCCEEDED( renderContext->BeginScene() ); ASSERT_HRESULT_SUCCEEDED( renderContext->Clear( Tr2RenderContextEnum::CLEARFLAGS_TARGET, 0xff000000 | ( g & 0xff ), 1.0f ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetStreamSource( 0, vb, 0, vbStride ) ); @@ -665,7 +651,8 @@ TEST_F( Rendering, CanSampleMipMappedTexture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 1 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -898,14 +885,6 @@ TEST_F( Rendering, CanClearRenderTarget ) Tr2TextureAL rt; ASSERT_HRESULT_SUCCEEDED( rt.Create( Tr2BitmapDimensions( 128, 64, 1, Tr2RenderContextEnum::PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2GpuUsage::RENDER_TARGET | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - - uint32_t g = 127; auto frame = [&] { @@ -926,7 +905,8 @@ TEST_F( Rendering, CanClearRenderTarget ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -1017,14 +997,6 @@ TEST_F( Rendering, CanRenderToRenderTarget ) Tr2TextureAL rt; ASSERT_HRESULT_SUCCEEDED( rt.Create( Tr2BitmapDimensions( 128, 64, 1, Tr2RenderContextEnum::PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2GpuUsage::RENDER_TARGET | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -1055,7 +1027,8 @@ TEST_F( Rendering, CanRenderToRenderTarget ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -1149,14 +1122,6 @@ TEST_F( Rendering, CanRenderToMsaaRenderTarget ) Tr2TextureAL readableRt; ASSERT_HRESULT_SUCCEEDED( readableRt.Create( Tr2BitmapDimensions( 128, 64, 1, Tr2RenderContextEnum::PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2GpuUsage::RENDER_TARGET | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, readableRt ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -1189,7 +1154,8 @@ TEST_F( Rendering, CanRenderToMsaaRenderTarget ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, readableRt ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -1481,14 +1447,6 @@ TEST_F( Rendering, CanSampleDepthBuffer ) Tr2GpuUsage::DEPTH_STENCIL | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - Tr2ResourceSetDescriptionAL resourceSetDescription( sp2 ); - resourceSetDescription.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, depthBuffer ); - resourceSetDescription.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( resourceSetDescription, sp2, *renderContext ) ); - - uint32_t g = 127; auto frame = [&] { @@ -1514,7 +1472,8 @@ TEST_F( Rendering, CanSampleDepthBuffer ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetStreamSource( 0, quadVb, 0, vbStride ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp2 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, depthBuffer ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); renderContext->SetReadOnlyDepth( false ); @@ -2002,14 +1961,6 @@ TEST_F( Rendering, CanPerformAlphaBlend ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2024,7 +1975,8 @@ TEST_F( Rendering, CanPerformAlphaBlend ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_SRCBLEND, Tr2RenderContextEnum::BM_SRCALPHA ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_DESTBLEND, Tr2RenderContextEnum::BM_INVSRCALPHA ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -2160,14 +2112,6 @@ TEST_F( Rendering, CanGenerateRenderTargetMips ) std::numeric_limits::max() ); ASSERT_HRESULT_SUCCEEDED( sampler.Create( samplerDesc, *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampler ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2199,7 +2143,8 @@ TEST_F( Rendering, CanGenerateRenderTargetMips ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampler ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); for( uint32_t i = 0; i < 8; ++i ) @@ -2304,14 +2249,6 @@ TEST_F( Rendering, CanCopyRenderTargetRegion ) Tr2TextureAL rt2; ASSERT_HRESULT_SUCCEEDED( rt2.Create( Tr2BitmapDimensions( 256, 256, 1, Tr2RenderContextEnum::PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2GpuUsage::RENDER_TARGET | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt2 ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2351,7 +2288,8 @@ TEST_F( Rendering, CanCopyRenderTargetRegion ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt2 ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -2436,14 +2374,6 @@ TEST_F( Rendering, CanSampleBc1Texture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2456,7 +2386,8 @@ TEST_F( Rendering, CanSampleBc1Texture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); @@ -2612,14 +2543,6 @@ TEST_F( Rendering, CanSampleBc2Texture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2632,7 +2555,8 @@ TEST_F( Rendering, CanSampleBc2Texture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); @@ -2719,14 +2643,6 @@ TEST_F( Rendering, CanSampleBc3Texture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -2739,7 +2655,8 @@ TEST_F( Rendering, CanSampleBc3Texture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); @@ -2827,14 +2744,6 @@ TEST_F( Rendering, CanSampleVolumeTexture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; @@ -2857,7 +2766,8 @@ TEST_F( Rendering, CanSampleVolumeTexture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::PIXEL_SHADER, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); @@ -2946,14 +2856,6 @@ TEST_F( Rendering, CanSampleBc3VolumeTexture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; @@ -2976,7 +2878,8 @@ TEST_F( Rendering, CanSampleBc3VolumeTexture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetConstants( cb, Tr2RenderContextEnum::PIXEL_SHADER, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLE_STRIP ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); @@ -3161,14 +3064,6 @@ TEST_F( Rendering, CanLockTextureTwice ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -3187,7 +3082,8 @@ TEST_F( Rendering, CanLockTextureTwice ) *reinterpret_cast( data ) = 0xffff0000; tex.UnmapForWriting( *renderContext ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetStreamSource( 0, vb1, 0, vbStride ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); @@ -3294,14 +3190,6 @@ TEST_F( Rendering, CanSampleSrgbTexture ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex, Tr2RenderContextEnum::COLOR_SPACE_SRGB ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -3314,7 +3202,8 @@ TEST_F( Rendering, CanSampleSrgbTexture ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex, Tr2RenderContextEnum::COLOR_SPACE_SRGB ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -3410,14 +3299,6 @@ TEST_F( Rendering, CanOutputToSrgbTarget ) 0.0f ), *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex, Tr2RenderContextEnum::COLOR_SPACE_SRGB ); - desc.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -3431,7 +3312,8 @@ TEST_F( Rendering, CanOutputToSrgbTarget ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, tex, Tr2RenderContextEnum::COLOR_SPACE_SRGB ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); @@ -3493,14 +3375,6 @@ TEST_F( Rendering, CanUsePsUavs ) Tr2TextureAL rwTexture; ASSERT_HRESULT_SUCCEEDED( rwTexture.Create( Tr2BitmapDimensions( 64, 64, 1, PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2GpuUsage::SHADER_RESOURCE | Tr2GpuUsage::UNORDERED_ACCESS, *renderContext ) ); - Tr2ResourceSetAL uavResourceSet; - { - Tr2ResourceSetDescriptionAL resourceSetDescription( sp ); - resourceSetDescription.SetUav( Tr2RenderContextEnum::PIXEL_SHADER, 1, rwTexture ); - ASSERT_HRESULT_SUCCEEDED( uavResourceSet.Create( resourceSetDescription, sp, *renderContext ) ); - } - - float quad[] = { 0, 0, @@ -3555,15 +3429,6 @@ TEST_F( Rendering, CanUsePsUavs ) Tr2ShaderProgramAL sp2; ASSERT_HRESULT_SUCCEEDED( sp2.Create( shaders2, 2, *renderContext ) ); - - Tr2ResourceSetDescriptionAL resourceSetDescription( sp2 ); - resourceSetDescription.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rwTexture ); - resourceSetDescription.SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( resourceSetDescription, sp2, *renderContext ) ); - - uint32_t g = 127; auto frame = [&] { @@ -3576,7 +3441,7 @@ TEST_F( Rendering, CanUsePsUavs ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetStreamSource( 0, vb, 0, vbStride ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetVertexLayout( vertexLayout ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( uavResourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetUav( Tr2RenderContextEnum::PIXEL_SHADER, 1, rwTexture ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetTopology( Tr2RenderContextEnum::TOP_TRIANGLES ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); @@ -3584,7 +3449,8 @@ TEST_F( Rendering, CanUsePsUavs ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetStreamSource( 0, quadVb, 0, vbStride ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetShaderProgram( sp2 ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rwTexture ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSampler( Tr2RenderContextEnum::PIXEL_SHADER, 0, sampl ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); @@ -4017,13 +3883,6 @@ TEST_F( Rendering, CanLoadMsaaRenderTarget ) Tr2TextureAL rt; ASSERT_HRESULT_SUCCEEDED( rt.Create( Tr2BitmapDimensions( 128, 64, 1, Tr2RenderContextEnum::PIXEL_FORMAT_B8G8R8A8_UNORM ), Tr2MsaaDesc( 4 ), Tr2GpuUsage::RENDER_TARGET | Tr2GpuUsage::SHADER_RESOURCE, *renderContext ) ); - - Tr2ResourceSetDescriptionAL desc( sp ); - desc.SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ); - - Tr2ResourceSetAL resourceSet; - ASSERT_HRESULT_SUCCEEDED( resourceSet.Create( desc, sp, *renderContext ) ); - uint32_t g = 127; auto frame = [&] { @@ -4054,7 +3913,7 @@ TEST_F( Rendering, CanLoadMsaaRenderTarget ) ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ZENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_ALPHABLENDENABLE, 0 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->SetRenderState( Tr2RenderContextEnum::RS_CULLMODE, Tr2RenderContextEnum::CULLMODE_NONE ) ); - ASSERT_HRESULT_SUCCEEDED( renderContext->SetResourceSet( resourceSet ) ); + ASSERT_HRESULT_SUCCEEDED( renderContext->SetSrv( Tr2RenderContextEnum::PIXEL_SHADER, 0, rt ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->DrawPrimitive( 0, 2 ) ); ASSERT_HRESULT_SUCCEEDED( renderContext->EndScene() ); MakeTestScreenShot(); From 4d1c907975f3d9bd4e0c3dea6d06d4c744229e4a Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Wed, 9 Sep 2026 12:29:39 +0100 Subject: [PATCH 22/23] PLAT-9853: Metal direct resource bindings replace resource sets --- .../Eve/SpaceObject/Children/EveChildMesh.cpp | 2 +- trinityal/metal/Tr2RenderContextMetal.h | 56 ++- trinityal/metal/Tr2RenderContextMetal.mm | 406 +++++++++++++++++- trinityal/metal/Tr2ShaderALMetal.h | 1 + trinityal/metal/Tr2ShaderProgramALMetal.h | 2 - trinityal/metal/Tr2ShaderProgramALMetal.mm | 39 -- 6 files changed, 441 insertions(+), 65 deletions(-) diff --git a/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp b/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp index a8d8aa20f..7eed6cfa1 100644 --- a/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp +++ b/trinity/Eve/SpaceObject/Children/EveChildMesh.cpp @@ -883,7 +883,7 @@ Tr2PerObjectData* EveChildMesh::GetPerObjectData( ITriRenderBatchAccumulator* ac if( m_animationUpdater && m_animationUpdater->IsInitialized() ) { auto meshIndex = m_mesh->GetMeshIndex(); - if( auto mesh = m_mesh->GetGeometryResource()->GetMeshData( meshIndex ) ) + if( m_mesh->GetGeometryResource()->GetMeshData( meshIndex ) ) { auto lod = m_mesh->GetGeometryResource()->GetMeshLod( meshIndex, m_currentScreenSize ); if( lod->m_morphTargetAllocation.IsValid() ) diff --git a/trinityal/metal/Tr2RenderContextMetal.h b/trinityal/metal/Tr2RenderContextMetal.h index 12863a688..d880fb3c3 100644 --- a/trinityal/metal/Tr2RenderContextMetal.h +++ b/trinityal/metal/Tr2RenderContextMetal.h @@ -12,6 +12,7 @@ #include "../include/Tr2SamplerStateAL.h" #include "../include/Tr2BufferAL.h" #include "../include/Tr2ShaderProgramAL.h" +#include "../include/Tr2RegisterMapAL.h" #include "../include/Tr2VertexLayoutAL.h" #include "../include/Tr2ConstantBufferAL.h" #include "../include/Tr2RenderPassAL.h" @@ -314,8 +315,61 @@ class Tr2RenderContextAL Tr2ShaderProgramAL m_shaderProgram; Tr2VertexLayoutAL m_vertexLayout; - bool m_needsDrawResourceCheck; +private: + struct Resource + { + enum Type + { + NONE, + BUFFER, + TEXTURE, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2TextureAL texture; + Tr2BufferAL buffer; + Type type = NONE; + union + { + Tr2RenderContextEnum::ColorSpace colorSpace = Tr2RenderContextEnum::COLOR_SPACE_LINEAR; + uint32_t mip; + }; + }; + + struct Sampler + { + enum Type + { + NONE, + SAMPLER, + HEAP_VIEW, + }; + + Tr2RenderContextEnum::ShaderType stage = Tr2RenderContextEnum::INVALID_SHADER; + uint32_t registerIndex = 0; + Tr2SamplerStateAL sampler; + Type type = NONE; + }; + + std::vector m_pendingSRVs; + std::vector m_pendingUAVs; + std::vector m_pendingSamplers; + + const Resource* m_sortedSRVs[Tr2RenderContextEnum::SHADER_TYPE_COUNT * Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Resource* m_sortedUAVs[Tr2RenderContextEnum::SHADER_TYPE_COUNT * Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + const Sampler* m_sortedSamplers[Tr2RenderContextEnum::SHADER_TYPE_COUNT * Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE]; + bool m_bindingsCommitted; + bool m_bindingsSealed; + const TrinityALImpl::Tr2ShaderProgramAL* m_committedProgram; + + ALResult UseResourceBindings() throw(); + void BeginResourceBindingBatch() throw(); + void DiscardResourceBindings() throw(); + +protected: struct MetalPrimitiveInfo { MTLPrimitiveType metalPrimitiveType; diff --git a/trinityal/metal/Tr2RenderContextMetal.mm b/trinityal/metal/Tr2RenderContextMetal.mm index f1e962fb6..aa525010b 100644 --- a/trinityal/metal/Tr2RenderContextMetal.mm +++ b/trinityal/metal/Tr2RenderContextMetal.mm @@ -14,6 +14,7 @@ #include "Tr2VertexLayoutALMetal.h" #include "Tr2ShaderProgramALMetal.h" #include "Tr2TextureALMetal.h" +#include "Tr2SamplerStateALMetal.h" #include "Tr2SwapChainALMetal.h" #include "Tr2RtPipelineStateALMetal.h" #include "Tr2RtShaderTableALMetal.h" @@ -77,7 +78,10 @@ MTLClearColor MakeClearColor( uint32_t color ) m_srgbWriteEnable( false ), m_isPrimary( false ), m_caps(), - m_upscalingTechnique( nullptr ) + m_upscalingTechnique( nullptr ), + m_bindingsCommitted( false ), + m_bindingsSealed( false ), + m_committedProgram( nullptr ) { } @@ -119,7 +123,6 @@ MTLClearColor MakeClearColor( uint32_t color ) m_caMetalLayer = nil; m_defaultBackBuffer.m_texture = std::make_shared(); m_boundDepthStencil.m_texture = nullptr; - m_needsDrawResourceCheck = true; m_swapChain.m_swapChain = std::make_shared(); } @@ -151,6 +154,7 @@ MTLClearColor MakeClearColor( uint32_t color ) m_boundRenderTargets[i] = {}; } m_boundDepthStencil = Tr2TextureAL(); + DiscardResourceBindings(); m_isValid = false; } @@ -521,12 +525,7 @@ MTLClearColor MakeClearColor( uint32_t color ) void Tr2RenderContextAL::CheckDrawResources() { - // Only need to check resources if the shader has changed since the last draw. - if( m_needsDrawResourceCheck ) - { - m_shaderProgram.m_program->SetDummyResources( *m_workQueue ); - m_needsDrawResourceCheck = false; - } + UseResourceBindings(); if( m_vertexLayout.IsValid() ) { @@ -615,6 +614,8 @@ MTLClearColor MakeClearColor( uint32_t color ) ALResult Tr2RenderContextAL::RunComputeShader( unsigned groupDimX, unsigned groupDimY, unsigned groupDimZ ) { + UseResourceBindings(); + m_workQueue->Dispatch( groupDimX, groupDimY, groupDimZ ); return S_OK; @@ -627,6 +628,8 @@ MTLClearColor MakeClearColor( uint32_t color ) return E_FAIL; } + UseResourceBindings(); + m_workQueue->Dispatch( indirectParams.m_buffer->GetMetalBuffer(), offset ); return S_OK; @@ -652,6 +655,7 @@ MTLClearColor MakeClearColor( uint32_t color ) { // pass on shaderTable to bind it to the RayGen shader SetShaderProgram( pipeline.TrinityALImpl_GetObject()->GetShaderProgram( *rayGen ) ); + UseResourceBindings(); m_workQueue->DispatchRays( pipeline.TrinityALImpl_GetObject(), shaderTable.TrinityALImpl_GetObject(), *rayGen, width, height, depth ); } @@ -868,7 +872,6 @@ MTLClearColor MakeClearColor( uint32_t color ) m_vertexLayout = Tr2VertexLayoutAL(); m_shaderProgram = Tr2ShaderProgramAL(); - m_needsDrawResourceCheck = true; return S_OK; } @@ -911,7 +914,7 @@ MTLClearColor MakeClearColor( uint32_t color ) shaderProgram.m_program->GetThreadGroupSize(), shaderProgram.m_program->GetResourceMasks() ); - m_needsDrawResourceCheck = true; + m_bindingsCommitted = false; return S_OK; } @@ -1131,51 +1134,411 @@ MTLClearColor MakeClearColor( uint32_t color ) return S_OK; } -ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2BufferAL& buffer ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType, - uint32_t, - const Tr2TextureAL&, - Tr2RenderContextEnum::ColorSpace ) throw() +ALResult Tr2RenderContextAL::SetSrv( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2TextureAL& texture, + Tr2RenderContextEnum::ColorSpace colorSpace ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.colorSpace = colorSpace; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2BufferAL& ) throw() +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2BufferAL& buffer ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::BUFFER; + resource.buffer = buffer; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2TextureAL&, uint32_t ) throw() +ALResult Tr2RenderContextAL::SetUav( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2TextureAL& texture, + uint32_t mip ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::TEXTURE; + resource.texture = texture; + resource.mip = mip; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +ALResult Tr2RenderContextAL::SetSrvHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingSRVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +ALResult Tr2RenderContextAL::SetUavHeapView( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Resource resource; + resource.stage = stage; + resource.registerIndex = registerIndex; + resource.type = Resource::HEAP_VIEW; + m_pendingUAVs.push_back( resource ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType, uint32_t ) throw() +ALResult Tr2RenderContextAL::SetSamplerHeapView( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::HEAP_VIEW; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; return S_OK; } -ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType, uint32_t, const Tr2SamplerStateAL& ) throw() +ALResult Tr2RenderContextAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, + uint32_t registerIndex, + const Tr2SamplerStateAL& sampler ) throw() { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return E_INVALIDARG; + } + BeginResourceBindingBatch(); + + Sampler entry; + entry.stage = stage; + entry.registerIndex = registerIndex; + entry.type = Sampler::SAMPLER; + entry.sampler = sampler; + m_pendingSamplers.push_back( entry ); + + m_bindingsCommitted = false; return S_OK; } ALResult Tr2RenderContextAL::ResetResourceBindings() throw() { + DiscardResourceBindings(); + return S_OK; +} + +void Tr2RenderContextAL::BeginResourceBindingBatch() throw() +{ + if( !m_bindingsSealed ) + { + return; + } + + m_bindingsSealed = false; + m_bindingsCommitted = false; + + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); +} + +void Tr2RenderContextAL::DiscardResourceBindings() throw() +{ + m_pendingSRVs.clear(); + m_pendingUAVs.clear(); + m_pendingSamplers.clear(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + m_bindingsCommitted = false; + m_bindingsSealed = false; + m_committedProgram = nullptr; +} + +ALResult Tr2RenderContextAL::UseResourceBindings() throw() +{ + if( !m_shaderProgram.IsValid() ) + { + return S_OK; + } + + const TrinityALImpl::Tr2ShaderProgramAL& program = *m_shaderProgram.m_program; + if( m_bindingsCommitted && m_committedProgram == &program ) + { + return S_OK; + } + + const Tr2RegisterMapAL& registerMap = program.GetRegisterMap(); + const TrinityALImpl::ShaderResourceMask* resourceMasks = program.GetResourceMasks(); + + std::fill( std::begin( m_sortedSRVs ), std::end( m_sortedSRVs ), nullptr ); + std::fill( std::begin( m_sortedUAVs ), std::end( m_sortedUAVs ), nullptr ); + std::fill( std::begin( m_sortedSamplers ), std::end( m_sortedSamplers ), nullptr ); + + for( const auto& resource : m_pendingSRVs ) + { + uint32_t index = registerMap.srvs[resource.stage][resource.registerIndex]; + if( index < registerMap.srvCount ) + { + m_sortedSRVs[index] = &resource; + } + } + for( const auto& resource : m_pendingUAVs ) + { + uint32_t index = registerMap.uavs[resource.stage][resource.registerIndex]; + if( index < registerMap.uavCount ) + { + m_sortedUAVs[index] = &resource; + } + } + for( const auto& sampler : m_pendingSamplers ) + { + uint32_t index = registerMap.samplers[sampler.stage][sampler.registerIndex]; + if( index < registerMap.samplerCount ) + { + m_sortedSamplers[index] = &sampler; + } + } + + TrinityALImpl::MetalContext* metalContext = GetMetalContext(); + id heapView = metalContext->GetHeapViewBuffer(); + + const ShaderType stages[] = { VERTEX_SHADER, PIXEL_SHADER, COMPUTE_SHADER }; + for( auto stage : stages ) + { + id buffers[METAL_MAX_BOUND_BUFFERS] = {}; + id textures[METAL_MAX_BOUND_TEXTURES] = {}; + id samplers[METAL_MAX_BOUND_SAMPLERS] = {}; + + uint32_t buffersMask = 0; + uint32_t heapViewMask = 0; + NSUInteger texturesMin = NSUIntegerMax; + NSUInteger texturesMax = 0; + NSUInteger samplersMin = NSUIntegerMax; + NSUInteger samplersMax = 0; + + // Resources the shader declares but nothing bound; filled with dummies below. + uint32_t missingTextureMask = resourceMasks[stage].textureMask; + uint32_t missingSamplerMask = resourceMasks[stage].samplerMask; + + for( uint32_t reg = 0; reg < Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE; ++reg ) + { + const uint32_t srvIndex = registerMap.srvs[stage][reg]; + if( srvIndex < registerMap.srvCount ) + { + const Resource* resource = m_sortedSRVs[srvIndex]; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::BUFFER: + if( resource->buffer.IsValid() && reg < METAL_SRV_BUFFER_COUNT ) + { + const NSUInteger bufferIndex = METAL_SRV_BUFFER_OFFSET + reg; + buffers[bufferIndex] = resource->buffer.m_buffer->GetMetalBuffer(); + buffersMask |= ( 1u << bufferIndex ); + } + break; + case Resource::TEXTURE: + if( resource->texture.IsValid() && reg < METAL_SRV_TEXTURE_COUNT ) + { + const NSUInteger texIndex = METAL_SRV_TEXTURE_OFFSET + reg; + textures[texIndex] = ( resource->colorSpace == COLOR_SPACE_SRGB ) ? + resource->texture.m_texture->GetSRGBViewMetalTexture() : + resource->texture.m_texture->GetMetalTexture(); + texturesMin = std::min( texturesMin, texIndex ); + texturesMax = std::max( texturesMax, texIndex ); + missingTextureMask &= ~( 1u << texIndex ); + } + break; + case Resource::HEAP_VIEW: + if( reg < METAL_SRV_BUFFER_COUNT ) + { + heapViewMask |= ( 1u << ( METAL_SRV_BUFFER_OFFSET + reg ) ); + } + break; + default: + break; + } + } + + const uint32_t uavIndex = registerMap.uavs[stage][reg]; + if( uavIndex < registerMap.uavCount ) + { + const Resource* resource = m_sortedUAVs[uavIndex]; + switch( resource ? resource->type : Resource::NONE ) + { + case Resource::BUFFER: + if( resource->buffer.IsValid() && reg < METAL_UAV_BUFFER_COUNT ) + { + const NSUInteger bufferIndex = METAL_UAV_BUFFER_OFFSET + reg; + buffers[bufferIndex] = resource->buffer.m_buffer->GetMetalBuffer(); + buffersMask |= ( 1u << bufferIndex ); + } + break; + case Resource::TEXTURE: + if( resource->texture.IsValid() && reg < METAL_UAV_TEXTURE_COUNT ) + { + const NSUInteger texIndex = METAL_UAV_TEXTURE_OFFSET + reg; + textures[texIndex] = resource->texture.m_texture->GetUAVMetalTexture( resource->mip ); + texturesMin = std::min( texturesMin, texIndex ); + texturesMax = std::max( texturesMax, texIndex ); + missingTextureMask &= ~( 1u << texIndex ); + } + break; + case Resource::HEAP_VIEW: + if( reg < METAL_UAV_BUFFER_COUNT ) + { + heapViewMask |= ( 1u << ( METAL_UAV_BUFFER_OFFSET + reg ) ); + } + break; + default: + break; + } + } + + const uint32_t samplerIndex = registerMap.samplers[stage][reg]; + if( samplerIndex < registerMap.samplerCount ) + { + const Sampler* sampler = m_sortedSamplers[samplerIndex]; + switch( sampler ? sampler->type : Sampler::NONE ) + { + case Sampler::SAMPLER: + if( sampler->sampler.IsValid() && reg < METAL_MAX_BOUND_SAMPLERS ) + { + samplers[reg] = sampler->sampler.m_sampler->GetMetalSamplerState(); + samplersMin = std::min( samplersMin, reg ); + samplersMax = std::max( samplersMax, reg ); + missingSamplerMask &= ~( 1u << reg ); + } + break; + case Sampler::HEAP_VIEW: + if( reg < METAL_SRV_BUFFER_COUNT ) + { + heapViewMask |= ( 1u << ( METAL_SRV_BUFFER_OFFSET + reg ) ); + } + break; + default: + break; + } + } + } + + for( uint32_t index = 0; missingTextureMask && index < METAL_MAX_BOUND_TEXTURES; + missingTextureMask >>= 1, ++index ) + { + if( missingTextureMask & 0x1 ) + { + textures[index] = metalContext->GetDummyTexture( MTLTextureType( resourceMasks[stage].textureTypes[index] ) ); + texturesMin = std::min( texturesMin, index ); + texturesMax = std::max( texturesMax, index ); + } + } + + for( uint32_t index = 0; missingSamplerMask && index < METAL_MAX_BOUND_SAMPLERS; + missingSamplerMask >>= 1, ++index ) + { + if( missingSamplerMask & 0x1 ) + { + samplers[index] = metalContext->GetDummySampler(); + samplersMin = std::min( samplersMin, index ); + samplersMax = std::max( samplersMax, index ); + } + } + + m_workQueue->SetBuffers( stage, buffers, buffersMask, heapView, heapViewMask ); + m_workQueue->SetTextures( stage, + textures, + ( texturesMin != NSUIntegerMax ) ? + NSMakeRange( texturesMin, texturesMax - texturesMin + 1 ) : + NSMakeRange( 0, 0 ) ); + m_workQueue->SetSamplers( stage, + samplers, + ( samplersMin != NSUIntegerMax ) ? + NSMakeRange( samplersMin, samplersMax - samplersMin + 1 ) : + NSMakeRange( 0, 0 ) ); + } + + m_bindingsCommitted = true; + m_bindingsSealed = true; + m_committedProgram = &program; return S_OK; } @@ -1402,7 +1765,6 @@ MTLClearColor MakeClearColor( uint32_t color ) context->m_vertexLayout = Tr2VertexLayoutAL(); context->m_shaderProgram = Tr2ShaderProgramAL(); - context->m_needsDrawResourceCheck = true; return S_OK; } diff --git a/trinityal/metal/Tr2ShaderALMetal.h b/trinityal/metal/Tr2ShaderALMetal.h index 267242d3c..11a1f6219 100644 --- a/trinityal/metal/Tr2ShaderALMetal.h +++ b/trinityal/metal/Tr2ShaderALMetal.h @@ -5,6 +5,7 @@ #if TRINITY_PLATFORM == TRINITY_METAL #include "../include/Tr2ShaderAL.h" +#include "MetalWorkQueue.h" namespace TrinityALImpl diff --git a/trinityal/metal/Tr2ShaderProgramALMetal.h b/trinityal/metal/Tr2ShaderProgramALMetal.h index 23bb01931..a525160b6 100644 --- a/trinityal/metal/Tr2ShaderProgramALMetal.h +++ b/trinityal/metal/Tr2ShaderProgramALMetal.h @@ -37,8 +37,6 @@ class Tr2ShaderProgramAL : public Tr2DeviceResourceAL const std::vector& GetInputs() const; size_t GetInputsHash() const; - void SetDummyResources( TrinityALImpl::MetalWorkQueue& workQueue ); - private: id CompileShader( const ::Tr2ShaderAL& shader, NSString* entryFunction, Tr2PrimaryRenderContextAL& renderContext ); diff --git a/trinityal/metal/Tr2ShaderProgramALMetal.mm b/trinityal/metal/Tr2ShaderProgramALMetal.mm index f61fc9981..3629caf19 100644 --- a/trinityal/metal/Tr2ShaderProgramALMetal.mm +++ b/trinityal/metal/Tr2ShaderProgramALMetal.mm @@ -262,44 +262,5 @@ } return S_OK; } - -void Tr2ShaderProgramAL::SetDummyResources( TrinityALImpl::MetalWorkQueue& workQueue ) -{ - for( uint32_t i = 0; i < Tr2RenderContextEnum::SHADER_TYPE_COUNT; ++i ) - { - Tr2RenderContextEnum::ShaderType shaderType = (Tr2RenderContextEnum::ShaderType)i; - - // If there's not resource set then we need to set dummies for all textures and samplers. - uint32_t missingTextureMask = m_resourceMask[i].textureMask; - uint32_t missingSamplerMask = m_resourceMask[i].samplerMask; - - if( !missingTextureMask && !missingSamplerMask ) - { - continue; - } - - // Set any missing textures and samplers to the dummy object. - uint32_t index = 0; - while( missingTextureMask && missingSamplerMask ) - { - if( missingTextureMask & 0x1 ) - { - auto dummyTexture = - m_metalContext->GetDummyTexture( MTLTextureType( m_resourceMask[i].textureTypes[index] ) ); - workQueue.SetTextures( shaderType, &dummyTexture, NSMakeRange( index, 1 ) ); - } - missingTextureMask >>= 1; - - if( missingSamplerMask & 0x1 ) - { - auto dummySampler = m_metalContext->GetDummySampler(); - workQueue.SetSamplers( shaderType, &dummySampler, NSMakeRange( index, 1 ) ); - } - missingSamplerMask >>= 1; - - ++index; - } - } -} } #endif From 08329658d79455be95bb49020e1ea75f10622dcb Mon Sep 17 00:00:00 2001 From: JohnGreenCCP Date: Thu, 27 Aug 2026 10:56:10 +0100 Subject: [PATCH 23/23] Skip invalid sampler registers in static resource bindings Bindless sampler handles appear as fake sampler registers (100+) in the effect description. Binding them failed and stopped the remaining static bindings, including the bindless texture heap view, from being applied, so shaders like specialfx/ubershader read the wrong textures. --- trinityal/src/Tr2StaticResourceBindingsAL.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/trinityal/src/Tr2StaticResourceBindingsAL.cpp b/trinityal/src/Tr2StaticResourceBindingsAL.cpp index c441518f2..2f6622b68 100644 --- a/trinityal/src/Tr2StaticResourceBindingsAL.cpp +++ b/trinityal/src/Tr2StaticResourceBindingsAL.cpp @@ -3,6 +3,7 @@ #include "StdAfx.h" #include "../include/Tr2StaticResourceBindingsAL.h" #include "../include/Tr2RenderContextAL.h" +#include "../include/Tr2RegisterMapAL.h" bool Tr2StaticResourceBindingsAL::SetSampler( Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) @@ -92,6 +93,10 @@ bool Tr2StaticResourceBindingsAL::SharesRegisterSpace( Kind a, Kind b ) bool Tr2StaticResourceBindingsAL::Set( Kind kind, Tr2RenderContextEnum::ShaderType stage, uint32_t registerIndex, const Tr2SamplerStateAL& sampler ) { + if( stage >= Tr2RenderContextEnum::SHADER_TYPE_COUNT || registerIndex >= Tr2RegisterMapAL::MAX_RESOURCES_IN_STAGE ) + { + return false; + } for( auto& entry : m_entries ) { if( entry.stage != uint8_t( stage ) || entry.registerIndex != uint8_t( registerIndex ) || !SharesRegisterSpace( entry.kind, kind ) )