Files
GTASource/game/renderer/SortPVSAsync.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

89 lines
2.9 KiB
C++

// SortPVSAsync
// jlandry: 02/10/2012
#if __WIN32 || __SPU || RSG_ORBIS
#define g_auxDmaTag (0)
#include <algorithm>
#include "profile/profiler.h"
#include "system/eaptr.h"
#include "../renderer/PostScan.h"
static bool CompareLodSortVal(const CGtaPvsEntry& a, const CGtaPvsEntry& b) {
return a.GetVisFlags().GetLodSortVal() < b.GetVisFlags().GetLodSortVal();
}
inline bool isValidEntry(const CGtaPvsEntry& entry)
{
return entry.GetEntity() != NULL;
}
static u32 g_CurrentSortVal = 0;
inline bool IsEqualToCurrentSortVal(const CGtaPvsEntry& entry)
{
return entry.GetVisFlags().GetLodSortVal() == g_CurrentSortVal;
}
namespace SortPVSAsyncStats
{
PF_PAGE(SortPVSAsyncPage,"SortPVSAsync");
PF_GROUP(SortPVSAsync);
PF_LINK(SortPVSAsyncPage, SortPVSAsync);
PF_TIMER(SortPVSAsyncRun, SortPVSAsync);
}
using namespace SortPVSAsyncStats;
bool SortPVSAsync_Dependency(const sysDependency& dependency)
{
PF_FUNC(SortPVSAsyncRun);
CGtaPvsEntry* const pStart = (CGtaPvsEntry*)(dependency.m_Params[0].m_AsPtr);
CGtaPvsEntry* const pStop = (CGtaPvsEntry*)((u8*)pStart + dependency.m_DataSizes[0]);
sysEaPtr< CGtaPvsEntry* > pvsEndEa = static_cast< CGtaPvsEntry** >( dependency.m_Params[1].m_AsPtr );
sysEaPtr< u32 > dependencyRunningEa = static_cast< u32* >( dependency.m_Params[2].m_AsPtr );
// First, partition out the invalid entries.
CGtaPvsEntry* const startInvalidEntries = std::partition(pStart, pStop, isValidEntry);
const bool bDoPartitionInsteadOfSort = dependency.m_Params[3].m_AsBool;
if(bDoPartitionInsteadOfSort)
{
const u32 minSortVal = (u32) dependency.m_Params[4].m_AsInt;
const u32 maxSortVal = (u32) dependency.m_Params[5].m_AsInt;
// Next, loop from min sort val -> max sort val, partitioning the valid PVS entries from low -> high
// LOD sort value. We actually don't need to include the value of maxSortVal, since once we get to the
// last sort val, all the remaining PVS entries should be of that sort value anyways, by design of the
// partitioning.
CGtaPvsEntry* currentPartitionStart = pStart;
for(u32 i = minSortVal; i < maxSortVal; i++)
{
g_CurrentSortVal = i;
currentPartitionStart = std::partition(currentPartitionStart, startInvalidEntries, IsEqualToCurrentSortVal);
}
}
else
{
// If we're using the old std::sort() code-path, then sort from start up until the invalidated entries.
std::sort(pStart, startInvalidEntries, &CompareLodSortVal);
}
#if __SPU
sysDmaLargePutAndWait(pStart, uptr(dependency.m_Params[6].m_AsPtr), dependency.m_DataSizes[0], 1);
#endif
// Finally, we can also be efficient and write-back the pvs end pointer as the start of all the invalidated
// entries, so that any subsequent loops don't need to loop over the junk at the end.
sysInterlockedAddPointer((volatile void**)pvsEndEa.ToPtr(), sizeof(CGtaPvsEntry) * (startInvalidEntries - pStop));
// Signal that the sort job is done.
sysInterlockedExchange(dependencyRunningEa.ToPtr(), 0);
return true;
}
#endif