1895 lines
59 KiB
C++
1895 lines
59 KiB
C++
// Title : Renderer.cpp
|
|
// Author : Richard Jobling
|
|
// Started : 10/05/99
|
|
|
|
#include "renderer/Renderer.h"
|
|
|
|
// Rage headers
|
|
#include "bank/bank.h"
|
|
#include "bank/bkmgr.h"
|
|
#include "fragment/instance.h"
|
|
#include "fragment/type.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "grcore/device.h"
|
|
#include "grcore/effect_config.h"
|
|
#include "grcore/indexbuffer.h"
|
|
#include "grcore/vertexbuffer.h"
|
|
#include "grcore/wrapper_gcm.h"
|
|
#include "grmodel/shaderfx.h"
|
|
#include "grmodel/geometry.h"
|
|
#include "phbound/boundcomposite.h"
|
|
#include "profile/cputrace.h"
|
|
#include "profile/timebars.h"
|
|
#include "system/cache.h"
|
|
#include "system/nelem.h"
|
|
#include "system/param.h"
|
|
#include "system/task.h"
|
|
#include "system/xtl.h"
|
|
#include "grprofile/pix.h"
|
|
#include "system/system.h"
|
|
#include "system/taskscheduler.h"
|
|
#include "vector/geometry.h"
|
|
|
|
// Framework headers
|
|
#include "fwanimation/directorcomponentmotiontree.h"
|
|
#include "fwmaths/angle.h"
|
|
#include "fwmaths/vector.h"
|
|
#include "fwpheffects/ropemanager.h"
|
|
#include "fwrenderer/renderlistbuilder.h"
|
|
#include "fwrenderer/renderlistgroup.h"
|
|
#include "fwscene/world/EntityDesc.h"
|
|
#include "fwscene/search/SearchVolumes.h"
|
|
#include "fwscene/scan/Scan.h"
|
|
#include "vfx/ptfx/ptfxdebug.h"
|
|
|
|
// Game headers
|
|
#include "audio/northaudioengine.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/base/BaseCamera.h"
|
|
#include "camera/gameplay/GameplayDirector.h"
|
|
#include "camera/viewports/ViewportManager.h"
|
|
#include "core/game.h"
|
|
#include "debug/blockview.h"
|
|
#include "debug/debugglobals.h"
|
|
#include "debug/debugscene.h"
|
|
#include "debug/vectormap.h"
|
|
#include "debug/Rendering/DebugRendering.h"
|
|
#include "debug/Rendering/DebugLighting.h"
|
|
#include "debug/Rendering/DebugLights.h"
|
|
#include "debug/debugdraw/debugvolume.h"
|
|
#include "debug/textureviewer/textureviewer.h"
|
|
#include "game/clock.h"
|
|
#include "frontend/GolfTrail.h"
|
|
#include "frontend/VideoEditor/VideoEditorInterface.h"
|
|
#include "modelinfo/MLOModelInfo.h"
|
|
#include "modelinfo/TimeModelInfo.h"
|
|
#include "modelinfo/VehicleModelInfo.h"
|
|
#include "objects/Object.h"
|
|
#include "peds/Ped.h"
|
|
#include "peds/pedpopulation.h"
|
|
#include "peds/rendering/PedHeadshotManager.h"
|
|
#include "physics/GtaInst.h"
|
|
#include "renderer/occlusion.h"
|
|
#include "renderer/clip_stat.h"
|
|
#include "renderer/Deferred/DeferredLighting.h"
|
|
#include "renderer/DrawLists/drawlistMgr.h"
|
|
#include "renderer/Entities/EntityBatchDrawHandler.h"
|
|
#include "renderer/Lights/AsyncLightOcclusionMgr.h"
|
|
#include "renderer/lights/lights.h"
|
|
#include "renderer/lights/TiledLighting.h"
|
|
#include "renderer/MeshBlendManager.h"
|
|
#include "renderer/OcclusionQueries.h"
|
|
#include "renderer/PlantsMgr.h"
|
|
#include "renderer/PlantsGrassRenderer.h"
|
|
#include "renderer/PostProcessFX.h"
|
|
#include "renderer/RenderListBuilder.h"
|
|
#include "renderer/renderListGroup.h"
|
|
#include "renderer/RenderSettings.h"
|
|
#include "renderer/RenderTargetMgr.h"
|
|
#include "renderer/rendertargets.h"
|
|
#include "renderer/renderThread.h"
|
|
#include "renderer/Water.h"
|
|
#include "renderer/TreeImposters.h"
|
|
#include "renderer/SpuPm/SpuPmMgr.h"
|
|
#include "renderer/SSAO.h"
|
|
#include "renderer/Entities/InstancedEntityRenderer.h"
|
|
#include "renderer/ApplyDamage.h"
|
|
#include "renderer/RenderPhases/RenderPhaseDefLight.h"
|
|
#include "renderer/RenderPhases/RenderPhaseCascadeShadows.h"
|
|
#include "renderer/RenderPhases/RenderPhaseDebugOverlay.h"
|
|
#include "renderer/RenderPhases/RenderPhaseEntitySelect.h"
|
|
#include "renderer/RenderPhases/RenderPhaseFX.h"
|
|
#include "renderer/RenderPhases/RenderPhaseHeightMap.h"
|
|
#include "renderer/RenderPhases/RenderPhaseLensDistortion.h"
|
|
#include "renderer/RenderPhases/RenderPhaseMirrorReflection.h"
|
|
#include "renderer/RenderPhases/RenderPhaseParaboloidShadows.h"
|
|
#include "renderer/RenderPhases/RenderPhaseReflection.h"
|
|
#include "renderer/RenderPhases/RenderPhaseStd.h"
|
|
#include "renderer/RenderPhases/RenderPhaseWater.h"
|
|
#include "renderer/RenderPhases/RenderPhaseWaterReflection.h"
|
|
#include "renderer/shadows/shadows.h"
|
|
#include "renderer/UI3DDrawManager.h"
|
|
#include "renderer/Util/ShmooFile.h"
|
|
#include "scene/debug/PostScanDebug.h"
|
|
#include "scene/Entity.h"
|
|
#include "scene/EntityBatch.h"
|
|
#include "scene/portals/FrustumDebug.h"
|
|
#include "scene/portals/portal.h"
|
|
#include "scene/portals/portalDebugHelper.h"
|
|
#include "scene/portals/portalInst.h"
|
|
#include "scene/portals/portalTracker.h"
|
|
#include "scene/streamer/SceneStreamerMgr.h"
|
|
#include "scene/Scene.h"
|
|
#include "scene/worldpoints.h"
|
|
#include "scene/world/GameScan.h"
|
|
#include "scene/world/gameWorld.h"
|
|
#include "scene/world/WorldDebugHelper.h"
|
|
#include "shaders/ShaderLib.h"
|
|
#include "shaders/CustomShaderEffectTint.h"
|
|
#include "shaders/CustomShaderEffectTree.h"
|
|
#include "shaders/CustomShaderEffectAnimUV.h"
|
|
#include "shaders/CustomShaderEffectCable.h"
|
|
#include "shaders/CustomShaderEffectGrass.h"
|
|
#include "shaders/CustomShaderEffectMirror.h"
|
|
#include "Shaders/ShaderEdit.h"
|
|
#include "streaming/streaming.h"
|
|
#include "streaming/streamingengine.h"
|
|
#include "streaming/streamingmodule.h"
|
|
#include "timeCycle/TimeCycle.h"
|
|
#include "timeCycle/TimeCycleAsyncQueryMgr.h"
|
|
#include "vehicles/Automobile.h" //needed so we can tell some SPU code about automobiles
|
|
#include "vehicles/VehicleLightAsyncMgr.h"
|
|
#include "vehicles/vehiclepopulation.h"
|
|
#include "vfx/misc/DistantLights.h"
|
|
#include "vfx/misc/Puddles.h"
|
|
#include "vfx/misc/TerrainGrid.h"
|
|
#include "vfx/VisualEffects.h"
|
|
#include "vfx/misc/LinearPiecewiseFog.h"
|
|
|
|
#if RSG_PC
|
|
#include "renderer/computeshader.h"
|
|
#endif
|
|
|
|
#include "../shader_source/Lighting/Shadows/cascadeshadows_common.fxh"
|
|
#include "../shader_source/Terrain/terrain_cb_switches.fxh"
|
|
|
|
#if __PPU
|
|
#include "cell/atomic.h"
|
|
#include <cell/spurs/task.h>
|
|
#include <cell/spurs/event_flag.h>
|
|
#elif __XENON
|
|
#include "tracerecording.h"
|
|
#endif
|
|
|
|
// make sure these match
|
|
#if __BANK
|
|
CompileTimeAssert(rmDebugMode == _GTA5_rmDebugMode);
|
|
#endif
|
|
|
|
PARAM(lastgen,"render without new nextgen effects");
|
|
PARAM(forcetwopasstrees,"force two pass tree rendering");
|
|
PARAM(modelnamesincapture,"show model names in GPAD/PIX");
|
|
PARAM(dontwaitforbubblefences,"dont wait for bubble fences");
|
|
NOSTRIP_PARAM(setUAVNull,"Set unused UAV slots to NULL");
|
|
|
|
RENDER_OPTIMISATIONS();
|
|
|
|
#define STRIP_ASSERTS 0
|
|
|
|
#if STRIP_ASSERTS
|
|
#undef ASSERT_ONLY
|
|
#undef Assert
|
|
#undef AssertMsgf
|
|
#undef Assertf
|
|
#undef AssertVerify
|
|
#undef DebugAssert
|
|
|
|
|
|
#define ASSERT_ONLY(x)
|
|
#define Assert(x)
|
|
#define AssertMsgf(x,args)
|
|
#define Assertf(x,msg)
|
|
#define AssertVerify(x) (x)
|
|
#define DebugAssert(x)
|
|
|
|
|
|
#undef __DEV
|
|
#define __DEV 0
|
|
#undef __FINAL
|
|
#define __FINAL 1
|
|
#undef __BANK
|
|
#define __BANK 0
|
|
|
|
#endif
|
|
|
|
#if !__FINAL
|
|
#define DEBUG_RENDERER
|
|
#endif
|
|
|
|
RAGE_DEFINE_CHANNEL(render)
|
|
RAGE_DEFINE_SUBCHANNEL(render, drawlist)
|
|
|
|
void DebugEntity(CEntity* UNUSED_PARAM(pEntity),const char* UNUSED_PARAM(fmt), ...) {}
|
|
|
|
#if __BANK
|
|
int g_show_prerendered=false;
|
|
bool gLastGenMode=false;
|
|
bool gLastGenModeState = false;
|
|
|
|
bool CRenderer::ms_isSnowing = false;
|
|
|
|
bool CRenderer::ms_bPlantsAllEnabled = true;
|
|
bool CRenderer::ms_bPlantsDisplayDebugInfo = false;
|
|
bool CRenderer::ms_bPlantsAlphaOverdraw = false;
|
|
#endif //__BANK
|
|
|
|
bool g_multipass_list_gen=true;
|
|
bool g_show_streaming_on_vmap=false;
|
|
bool g_SortRenderLists=true;
|
|
bool g_SortTreeList=true;
|
|
bool g_debug_heightmap=false;
|
|
|
|
int g_alternativeViewport=-1;
|
|
TweakBankBool b_OnlySwapTimedWhenOffscreen=true;
|
|
float g_HighPriorityYaw=10.0f; //in degrees
|
|
TweakBankBool g_HighPrioritySphere=false;
|
|
float g_ScreenYawForPriorityConsideration=5.0f; //in degrees
|
|
bool g_UseTwoPassTreeNormalFlipping = true;
|
|
bool g_DoubleSidedTreesCutoutOptimization = true;
|
|
bool g_UseTwoPassTreeRendering = false;
|
|
bool g_UseTwoPassTreeShadowRendering = false;
|
|
TweakBankBool g_UseDelayedGbuffer2TileResolve = true;
|
|
|
|
#if __BANK
|
|
bool g_HideDebug=false;
|
|
bool g_DrawCloth=true;
|
|
bool g_DrawPeds=true;
|
|
bool g_DrawVehicles=true;
|
|
bool g_EnableSkipRenderingShaders = false;
|
|
bool g_SkipRenderingGrassFur = false;
|
|
bool g_SkipRenderingTrees = false;
|
|
|
|
#if RSG_DURANGO
|
|
bool g_DisplayFrameStatistics = true;
|
|
namespace rage {
|
|
extern DXGIX_FRAME_STATISTICS g_FrameStatistics[16];
|
|
}
|
|
#endif // RSG_DURANGO
|
|
#endif // __BANK
|
|
|
|
#if __PPU
|
|
int dma_planes_mem[MAX_OCCLUSION_PHASES][MAX_SPU_PLANES_MEM] ALIGNED(128);
|
|
short int dma_planes_mem_count[MAX_OCCLUSION_PHASES] ALIGNED(16);
|
|
#endif
|
|
|
|
#if __DEV
|
|
|
|
namespace DebugStreaming
|
|
{
|
|
struct DebugStreamingItem
|
|
{
|
|
CEntity *m_pEntity;
|
|
s16 m_Counter;
|
|
s16 m_Dist;
|
|
char *m_String;
|
|
};
|
|
|
|
static const int MAX_DEBUG_STREAMING_ARRAY=256;
|
|
|
|
static DebugStreamingItem m_Array[MAX_DEBUG_STREAMING_ARRAY];
|
|
static int m_Next=0;
|
|
|
|
void AddEntity(CEntity *pEntity,s16 counter,float dist,char *pstring=NULL)
|
|
{
|
|
if(pstring==NULL)
|
|
{
|
|
for(int i=0;i<MAX_DEBUG_STREAMING_ARRAY;i++)
|
|
{
|
|
if(m_Array[i].m_pEntity==pEntity)
|
|
{
|
|
m_Array[i].m_Counter=counter;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_Array[m_Next].m_pEntity=pEntity;
|
|
m_Array[m_Next].m_Dist=(s16)(dist*10.0f);
|
|
m_Array[m_Next].m_Counter=counter;
|
|
m_Array[m_Next].m_String=pstring;
|
|
m_Next++;
|
|
m_Next%=MAX_DEBUG_STREAMING_ARRAY;
|
|
}
|
|
|
|
void DrawAll(void)
|
|
{
|
|
for(int i=0;i<MAX_DEBUG_STREAMING_ARRAY;i++)
|
|
{
|
|
if(m_Array[i].m_Counter>0)
|
|
{
|
|
--m_Array[i].m_Counter;
|
|
|
|
char str[256];
|
|
Vector3 pos= VEC3V_TO_VECTOR3(m_Array[i].m_pEntity->GetTransform().GetPosition());
|
|
float ldist=((float)m_Array[i].m_Dist)*0.1f;
|
|
float fade=1.0f;//Min(((float)m_Array[i].m_Counter+10.0f)/20.0f,1.0f);
|
|
|
|
Color32 fadecol=Color32(1.0f,1.0f,1.0f,fade);
|
|
if(m_Array[i].m_String)
|
|
{
|
|
grcDebugDraw::Text(pos+Vector3(0.f,0.f,0.6f),fadecol,m_Array[i].m_String);
|
|
grcDebugDraw::AddDebugOutput(fadecol,m_Array[i].m_String);
|
|
|
|
}
|
|
else
|
|
{
|
|
sprintf(str,"%s d %3.1f/%3u",m_Array[i].m_pEntity->GetModelName(),ldist,m_Array[i].m_pEntity->GetLodDistance());
|
|
grcDebugDraw::Text(pos+Vector3(0.f,0.f,0.6f),fadecol,str);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void AddEntity(CEntity *pEntity,s16 counter,float dist,char *pstring)
|
|
{
|
|
DebugStreaming::AddEntity(pEntity,counter,dist,pstring);
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
//
|
|
// 360 GPU GPR allocations
|
|
#if __XENON
|
|
BankInt32 CGPRCounts::ms_DefaultPsRegs = 64;
|
|
BankInt32 CGPRCounts::ms_CascadedGenPsRegs = 32; // Haven't really found a place where it matters what we set this to!
|
|
BankInt32 CGPRCounts::ms_CascadedRevealPsRegs = 96; // Was 64, setting to 112 saves 0.01ms
|
|
BankInt32 CGPRCounts::ms_EnvReflectGenPsRegs = 92; // Was 64, 110 saves ~0.11ms for parab, 92 saves 0.03ms for cubemaps
|
|
BankInt32 CGPRCounts::ms_EnvReflectBlurPsRegs = 96;
|
|
BankInt32 CGPRCounts::ms_GBufferPsRegs = 64;
|
|
BankInt32 CGPRCounts::ms_WaterFogPrepassRegs = 112;
|
|
BankInt32 CGPRCounts::ms_WaterCompositePsRegs = 112;
|
|
BankInt32 CGPRCounts::ms_DefLightingPsRegs = 112; // Was 92, 112 saves 0.192ms in directional+foliage+skin
|
|
BankInt32 CGPRCounts::ms_DepthFXPsRegs = 112;
|
|
BankInt32 CGPRCounts::ms_PostFXPsRegs = 112;
|
|
|
|
#endif // __XENON
|
|
|
|
//
|
|
//
|
|
// CRenderer static variables
|
|
|
|
Vector3 CRenderer::ms_PrevCameraPosition;
|
|
Vector3 CRenderer::ms_ThisCameraPosition;
|
|
float CRenderer::ms_PreStreamDistance=RENDER_PRESTREAMDIST;
|
|
float CRenderer::ms_PrevCameraVelocity=0.0f;
|
|
int CRenderer::m_SceneToGBufferBits=0;
|
|
int CRenderer::m_MirrorBits=0;
|
|
int CRenderer::m_ShadowPhases=0;
|
|
#if __BANK
|
|
int CRenderer::m_DebugPhases=0;
|
|
#endif // __BANK
|
|
u32 CRenderer::ms_canRenderAlpha=0;
|
|
u32 CRenderer::ms_canRenderWater=0;
|
|
u32 CRenderer::ms_canRenderScreenDoor=0;
|
|
u32 CRenderer::ms_canRenderDecal=0;
|
|
u32 CRenderer::ms_canPreRender=0;
|
|
float CRenderer::ms_fCameraHeading;
|
|
float CRenderer::ms_fFarClipPlane;
|
|
bool CRenderer::ms_bInTheSky = false;
|
|
#if !__FINAL
|
|
bool CRenderer::sm_bRenderCollisionGeometry = false;
|
|
#endif
|
|
|
|
#if RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
int CRenderer::ms_WheelTessellationFactor = 1;
|
|
int CRenderer::ms_TreeTessellationFactor = 1;
|
|
float CRenderer::ms_TreeTessellation_PNTriangle_K = 0.0f;
|
|
|
|
float CRenderer::ms_LinearNear = 1.0f;
|
|
float CRenderer::ms_LinearFar = 10.0f;
|
|
// 0.1% of 1280 screen is about 1-2 pixels.
|
|
|
|
float CRenderer::ms_ScreenSpaceErrorInPixels = 1.0f;
|
|
int CRenderer::ms_MaxTessellation = 16;
|
|
float CRenderer::ms_FrustumEpsilon = 0.1f; // Todo - Use height scalar
|
|
float CRenderer::ms_BackFaceEpsilon = 0.725f;
|
|
bool CRenderer::ms_CullEnable = true;
|
|
|
|
|
|
# if !__FINAL
|
|
// Remember to change the default in common.fxh as well
|
|
bool CRenderer::ms_DisablePOM = false;
|
|
bool CRenderer::m_POMDistanceFade = true;
|
|
bool CRenderer::ms_VisPOMDistanceFade = false;
|
|
bool CRenderer::ms_VisPOMVertexHeight= false;
|
|
|
|
float CRenderer::ms_POMNear = 0.0f;
|
|
float CRenderer::ms_POMFar = 20.0f;
|
|
float CRenderer::ms_POMForwardOffset = 8.0f;
|
|
|
|
float CRenderer::ms_POMMinSamp = 3.0f;
|
|
float CRenderer::ms_POMMaxSamp = 27.0f;
|
|
|
|
grcEffectGlobalVar CRenderer::ms_POMValuesVar = grcegvNONE;
|
|
grcEffectGlobalVar CRenderer::ms_POMValues2Var = grcegvNONE;
|
|
# endif // !__FINAL
|
|
//---------------------------------------
|
|
|
|
float CRenderer::ms_GlobalHeightScale = 1.0f;
|
|
|
|
CRenderer::TessellationVars CRenderer::ms_TessellationVars;
|
|
|
|
#if !__FINAL || RSG_PC
|
|
grcEffectGlobalVar CRenderer::ms_POMFlagsVar = grcegvNONE;
|
|
#endif
|
|
|
|
grcEffectGlobalVar CRenderer::ms_GlobalHeightScaleVar;
|
|
#endif //RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
|
|
# if !__FINAL
|
|
// Remember to change the default in common.fxh as well
|
|
float CRenderer::ms_TerrainTintBlendNear = 70.0f;
|
|
float CRenderer::ms_TerrainTintBlendFar = 90.0f;
|
|
|
|
grcEffectGlobalVar CRenderer::ms_TerrainTintBlendValuesVar;
|
|
# endif // !__FINAL
|
|
|
|
// --- Global variables ---------------------------------------------------------------------------------------
|
|
|
|
#if DEBUG_DRAW && __BANK
|
|
static u32 gAddEntityToRenderListDebugModel = 0;
|
|
static u32 gSetupMapEntityVisibilityDebugModel = 0;
|
|
#endif // DEBUG_DRAW && __BANK
|
|
|
|
#if __BANK
|
|
|
|
#ifdef DEBUG_RENDERER
|
|
// model indices to debug
|
|
static char gAddEntityToRenderListDebugModelName[STORE_NAME_LENGTH] = "";
|
|
static char gSetupMapEntityVisibilityDebugModelName[STORE_NAME_LENGTH] = "";
|
|
#endif // DEBUG_RENDERER
|
|
#endif // __BANK
|
|
|
|
#if __BANK
|
|
extern bool g_AddModelGcmMarkers;
|
|
#endif
|
|
|
|
// --- CRenderer --------------------------------------------------------------------------------------------
|
|
|
|
#if __XENON
|
|
int CRenderer::sm_backbufferColorExpBiasHDR=0;
|
|
int CRenderer::sm_backbufferColorExpBiasLDR=0;
|
|
#endif
|
|
|
|
bool CRenderer::sm_disableArtificialLights = false;
|
|
bool CRenderer::sm_disableArtificialVehLights = true; // BS#6497322: if false, then do not disable vehicle lights during the EMP
|
|
|
|
//
|
|
// name: CRenderer::PreLoadingScreensInit
|
|
// description: Yellow logo support ;)
|
|
//
|
|
void CRenderer::PreLoadingScreensInit()
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_RENDER);
|
|
CRenderTargets::PreAllocateRenderTargetMemPool();
|
|
CRenderTargets::AllocateRenderTargets();
|
|
}
|
|
|
|
//
|
|
// name: CRenderer::Init
|
|
// description: Initialise renderer structures
|
|
//
|
|
void CRenderer::Init(unsigned initMode)
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_RENDER);
|
|
|
|
#if __BANK
|
|
g_AddModelGcmMarkers = PARAM_modelnamesincapture.Get();
|
|
#endif
|
|
|
|
#if __BANK
|
|
if ( PARAM_lastgen.Get() )
|
|
{
|
|
gLastGenModeState=true;
|
|
}
|
|
else
|
|
{
|
|
gLastGenModeState=false;
|
|
}
|
|
|
|
#if RSG_PC
|
|
if (PARAM_setUAVNull.Get())
|
|
{
|
|
grcEffect::sm_SetUAVNull = true;
|
|
}
|
|
#endif // RSG_PC
|
|
|
|
if ( PARAM_forcetwopasstrees.Get() )
|
|
{
|
|
g_UseTwoPassTreeRendering=true;
|
|
}
|
|
#endif
|
|
|
|
if(initMode == INIT_CORE)
|
|
{
|
|
InstancedRenderManager::Instantiate();
|
|
|
|
DeferredLighting::Init();
|
|
#if TILED_LIGHTING_ENABLED
|
|
CTiledLighting::Init();
|
|
#endif
|
|
|
|
#if __BANK
|
|
CShaderEdit::Init(initMode);
|
|
CDebugTextureViewerInterface::Init(initMode);
|
|
CRenderPhaseDebugOverlayInterface::InitShaders();
|
|
DebugRenderingMgr::Init();
|
|
#endif // __BANK
|
|
|
|
CRenderPhaseCascadeShadowsInterface::Init_(initMode);
|
|
CRenderPhaseCascadeShadowsInterface::InitShaders();
|
|
CRenderPhaseDrawSceneInterface::Init(initMode);
|
|
|
|
#if __PS3
|
|
// This has to happen after cascaded shadows on the PS3
|
|
CRenderTargets::GetDepthBufferQuarter()->AllocateMemoryFromPool();
|
|
CRenderTargets::SetDepthBufferQuarterAsColor(((grcRenderTargetGCM*)CRenderTargets::GetDepthBufferQuarter())->CreatePrePatchedTarget(false));
|
|
|
|
CRenderTargets::GetOffscreenDepthBuffer()->AllocateMemoryFromPool();
|
|
CRenderTargets::SetOffscreenDepthBufferAsColor(((grcRenderTargetGCM*)CRenderTargets::GetOffscreenDepthBuffer())->CreatePrePatchedTarget(false));
|
|
|
|
#if USE_DEPTHBUFFER_ZCULL_SHARING
|
|
// Force the offscreen depth buffer to share zcull memory with the main back buffer depth. If this fails, performance for volumetric lighting will be very bad (+5ms)
|
|
grcRenderTargetGCM* pOffscreenDepth = static_cast<grcRenderTargetGCM*>( CRenderTargets::GetOffscreenDepthBuffer() );
|
|
if ( !pOffscreenDepth->ForceZCullSharing(static_cast<grcRenderTargetGCM*>(CRenderTargets::GetDepthBuffer())) )
|
|
{
|
|
Assertf(false,"Unable to force zcull sharing for OffscreenDepth, this will destroy volumetric lighting performance!");
|
|
}
|
|
#endif // USE_DEPTHBUFFER_ZCULL_SHARING
|
|
#endif // __PS3
|
|
|
|
CParaboloidShadow::Init();
|
|
CParaboloidShadow::InitShaders("common:/shaders");
|
|
|
|
SSAO::Init(initMode);
|
|
#if LINEAR_PIECEWISE_FOG
|
|
LinearPiecewiseFog::Init();
|
|
#endif // LINEAR_PIECEWISE_FOG
|
|
#if TREES_ENABLE_BRANCH_BEND_AND_TRI_WAVE_MICRO_MOVEMENTS
|
|
CCustomShaderEffectTree::Init();
|
|
#endif // TREES_ENABLE_BRANCH_BEND_AND_TRI_WAVE_MICRO_MOVEMENTS
|
|
|
|
// ENTITYSELECT_ONLY(CRenderPhaseEntitySelect::InitializeRenderingResources());
|
|
|
|
g_RenderPhaseManager::Instantiate(40);
|
|
|
|
CGolfTrailInterface::Init();
|
|
|
|
CRenderPhaseReflection::InitClass();
|
|
CRenderPhaseMirrorReflection::InitClass();
|
|
CRenderPhaseWaterReflection::InitClass();
|
|
RenderPhaseSeeThrough::InitClass();
|
|
|
|
CGtaRenderListGroup::Init(INIT_CORE);
|
|
|
|
CGameScan::Init();
|
|
|
|
gDrawListMgr->SetDefaultSubBucketMask(GenerateSubBucketMask(RB_MODEL_DEFAULT));
|
|
|
|
#if __D3D11
|
|
gCSGameManager.Init();
|
|
#endif
|
|
|
|
InstancedRendererConfig::Init();
|
|
|
|
GPU_VEHICLE_DAMAGE_ONLY(CVehicleDeformation::TexCacheInit(initMode);)
|
|
GPU_VEHICLE_DAMAGE_ONLY(CApplyDamage::Init();)
|
|
}
|
|
else if(initMode == INIT_SESSION)
|
|
{
|
|
RenderPhaseSeeThrough::InitSession();
|
|
}
|
|
|
|
CGrassBatch::Init(initMode);
|
|
}
|
|
|
|
#if __BANK
|
|
void CRenderer::ToggleRenderCollisionGeometry(void)
|
|
{
|
|
if(sm_bRenderCollisionGeometry)
|
|
{
|
|
sm_bRenderCollisionGeometry = false;
|
|
}
|
|
else
|
|
{
|
|
sm_bRenderCollisionGeometry = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// name: ShutdownLevel
|
|
// description: Shutdown renderer module for this level
|
|
void CRenderer::Shutdown(unsigned shutdownMode)
|
|
{
|
|
if(shutdownMode == SHUTDOWN_CORE)
|
|
{
|
|
DeferredLighting::Shutdown();
|
|
#if TILED_LIGHTING_ENABLED
|
|
CTiledLighting::Shutdown();
|
|
#endif
|
|
SSAO::Shutdown(shutdownMode);
|
|
|
|
ENTITYSELECT_ONLY(CRenderPhaseEntitySelect::ReleaseRenderingResources());
|
|
|
|
CGolfTrailInterface::Shutdown();
|
|
#if __BANK
|
|
CShaderEdit::Shutdown(shutdownMode);
|
|
CDebugTextureViewerInterface::Shutdown(shutdownMode);
|
|
DebugRenderingMgr::Shutdown();
|
|
#endif
|
|
PostFX::Shutdown(shutdownMode);
|
|
CRenderPhaseCascadeShadowsInterface::Terminate();
|
|
CParaboloidShadow::Terminate();
|
|
|
|
gRenderListGroup.Shutdown(SHUTDOWN_CORE);
|
|
|
|
#if __XENON || __PPU
|
|
CRenderTargets::FreeRenderTargetMemPool();
|
|
#endif
|
|
|
|
g_RenderPhaseManager::Destroy();
|
|
|
|
#if __D3D11
|
|
gCSGameManager.Shutdown();
|
|
#endif
|
|
OcclusionQueries::Shutdown();
|
|
|
|
InstancedRenderManager::Destroy();
|
|
|
|
CGrassBatch::Shutdown();
|
|
|
|
GPU_VEHICLE_DAMAGE_ONLY(CVehicleDeformation::TexCacheShutdown(shutdownMode);)
|
|
GPU_VEHICLE_DAMAGE_ONLY(CApplyDamage::ShutDown();)
|
|
}
|
|
else if(shutdownMode == SHUTDOWN_SESSION)
|
|
{
|
|
ClearRenderLists();
|
|
|
|
PostFX::Shutdown(shutdownMode);
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
|
|
#define TOO_MANY_SHADERS 20
|
|
|
|
int PrintAndCountShaders(fwRenderListDesc& renderList, RenderPassId id)
|
|
{
|
|
int numAlphaShaders = 0;
|
|
|
|
// Count standard entity shaders
|
|
for(s32 i = 0; i < renderList.GetNumberOfEntities(id); i++)
|
|
{
|
|
rmcDrawable* pDrawable = ((CEntity *) renderList.GetEntity(i, id))->GetDrawable();
|
|
if(pDrawable && pDrawable->GetLodGroup().ContainsLod(LOD_HIGH))
|
|
{
|
|
s32 num = pDrawable->GetLodGroup().GetLodModel0(LOD_HIGH).GetGeometryCount();
|
|
if(num > TOO_MANY_SHADERS)
|
|
{
|
|
grcDebugDraw::AddDebugOutput("%s has %d shaders\n",
|
|
renderList.GetEntity(i, id)->GetModelName(), num);
|
|
}
|
|
numAlphaShaders += num;
|
|
}
|
|
}
|
|
|
|
return numAlphaShaders;
|
|
}
|
|
//
|
|
// name: CRenderer::PrintNumShadersRendered
|
|
// description:
|
|
void CRenderer::PrintNumShadersRendered(s32 list, const char *DEV_ONLY(phaseName))
|
|
{
|
|
#define TOO_MANY_SHADERS 20
|
|
s32 num;
|
|
s32 numShaders = 0;
|
|
s32 numLodShaders = 0;
|
|
s32 numAlphaShaders = 0;
|
|
fwRenderListDesc& renderList = gRenderListGroup.GetRenderListForPhase(list);
|
|
|
|
// Count standard entity shaders
|
|
for(s32 i = 0; i < renderList.GetNumberOfEntities(RPASS_VISIBLE); i++)
|
|
{
|
|
rmcDrawable* pDrawable = ((CEntity *) renderList.GetEntity(i, RPASS_VISIBLE))->GetDrawable();
|
|
if(pDrawable && pDrawable->GetLodGroup().ContainsLod(LOD_HIGH))
|
|
{
|
|
num = pDrawable->GetLodGroup().GetLodModel0(LOD_HIGH).GetGeometryCount();
|
|
if(num > TOO_MANY_SHADERS)
|
|
{
|
|
grcDebugDraw::AddDebugOutput("%s has %d shaders\n",
|
|
renderList.GetEntity(i, RPASS_VISIBLE)->GetModelName(), num);
|
|
}
|
|
numShaders += num;
|
|
}
|
|
}
|
|
// Count lod entity shaders
|
|
for(s32 i = 0; i < renderList.GetNumberOfEntities(RPASS_LOD); i++)
|
|
{
|
|
rmcDrawable* pDrawable = ((CEntity *) renderList.GetEntity(i, RPASS_LOD))->GetDrawable();
|
|
if(pDrawable && pDrawable->GetLodGroup().ContainsLod(LOD_HIGH))
|
|
{
|
|
num = pDrawable->GetLodGroup().GetLodModel0(LOD_HIGH).GetGeometryCount();
|
|
if(num > TOO_MANY_SHADERS)
|
|
{
|
|
grcDebugDraw::AddDebugOutput("%s has %d shaders\n",
|
|
renderList.GetEntity(i, RPASS_LOD)->GetModelName(), num);
|
|
}
|
|
numLodShaders += num;
|
|
}
|
|
}
|
|
|
|
//decal too?
|
|
numAlphaShaders += PrintAndCountShaders(renderList, RPASS_ALPHA);
|
|
numAlphaShaders += PrintAndCountShaders(renderList, RPASS_WATER);
|
|
numAlphaShaders += PrintAndCountShaders(renderList, RPASS_FADING);
|
|
|
|
#if __XENON
|
|
numAlphaShaders += PrintAndCountShaders(renderList, RPASS_TREE);
|
|
#endif //__XENON
|
|
|
|
#if __DEV
|
|
grcDebugDraw::AddDebugOutput("%s %d: shaders %d, lods %d, alpha %d, inst %d, trees %d",
|
|
phaseName, list,
|
|
numShaders, numLodShaders, numAlphaShaders, 0,0);//numInstanceShaders, numTreeShaders);
|
|
#endif //__DEV
|
|
}
|
|
|
|
#if RSG_DURANGO
|
|
|
|
|
|
void CRenderer::PrintFrameStatistic()
|
|
{
|
|
if( g_DisplayFrameStatistics == false )
|
|
return;
|
|
|
|
const int statsStartX = 190;
|
|
const int statsStartY = 20;
|
|
|
|
int y = statsStartY;
|
|
|
|
int queuedFrames = 0;
|
|
u64 presentToQueue = 0;
|
|
u64 queueToGpuDone = 0;
|
|
u64 queueToDisplay = 0;
|
|
u64 GpuDoneToDisplay = 0;
|
|
|
|
for(int i=0;i<16;i++)
|
|
{
|
|
DXGIX_FRAME_STATISTICS *frameStats = &g_FrameStatistics[i];
|
|
if( frameStats->VSyncCount == 0 )
|
|
{
|
|
queuedFrames++;
|
|
}
|
|
else
|
|
{
|
|
presentToQueue += (frameStats->CPUTimeAddedToQueue - frameStats->CPUTimePresentCalled);
|
|
queueToGpuDone += (frameStats->CPUTimeFrameComplete - frameStats->CPUTimeAddedToQueue);
|
|
queueToDisplay += (frameStats->CPUTimeFlip - frameStats->CPUTimeAddedToQueue);
|
|
GpuDoneToDisplay += (frameStats->CPUTimeFlip - frameStats->CPUTimeFrameComplete);
|
|
|
|
}
|
|
}
|
|
|
|
char debugText[512];
|
|
float t2ms = sysTimer::GetTicksToMilliseconds();
|
|
|
|
sprintf(debugText,"Queued Frames : %d",queuedFrames);
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
|
|
sprintf(debugText,"MS P2Q : %f",float(presentToQueue/16)*t2ms);
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
|
|
sprintf(debugText,"MS Q2G : %f",float(queueToGpuDone/16)*t2ms);
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
|
|
sprintf(debugText,"MS Q2D : %f",float(queueToDisplay/16)*t2ms);
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
|
|
sprintf(debugText,"MS G2D %f",float(GpuDoneToDisplay/16)*t2ms);
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
|
|
#if 0 // enable to see the matrix
|
|
for(int i=0;i<16;i++)
|
|
{
|
|
sprintf(debugText,"%u %u %u %u %u %u %u %u %u %u",
|
|
g_FrameStatistics[i].CPUTimePresentCalled,
|
|
g_FrameStatistics[i].CPUTimeAddedToQueue,
|
|
g_FrameStatistics[i].QueueLengthAddedToQueue,
|
|
g_FrameStatistics[i].CPUTimeFrameComplete,
|
|
g_FrameStatistics[i].GPUTimeFrameComplete,
|
|
g_FrameStatistics[i].CPUTimeFlip,
|
|
g_FrameStatistics[i].GPUTimeFlip,
|
|
g_FrameStatistics[i].VSyncCount,
|
|
g_FrameStatistics[i].VSyncCPUTime,
|
|
g_FrameStatistics[i].VSyncGPUTime);
|
|
|
|
grcDebugDraw::PrintToScreenCoors(debugText,statsStartX,y);
|
|
y++;
|
|
}
|
|
y++;
|
|
#endif
|
|
|
|
}
|
|
#endif // RSG_DURANGO
|
|
|
|
#endif // __BANK
|
|
|
|
RAGETRACE_DECL(CRenderer_ConstructRenderList);
|
|
extern bool g_render_lock;
|
|
//
|
|
// name: ConstructRenderList
|
|
// description: construct list of objects to render
|
|
|
|
// TODO: These need to be moved to RenderPhaseDefLight.cpp once the old render phase code disappears
|
|
/*dev_float*/ float MINIMUM_DISTANCE_FOR_PRESTREAM=5.0f;
|
|
/*dev_float*/ float MAX_DISTANCE_FOR_PRESTREAM=(80.0f-MINIMUM_DISTANCE_FOR_PRESTREAM);
|
|
/*dev_float*/ float MAX_SPEED_FOR_PRESTREAM=48.0f; // meters per second
|
|
|
|
|
|
void CRenderer::ConstructRenderListNew(u32 renderFlags, CRenderPhaseScanned *renderPhase)
|
|
{
|
|
Assert(renderPhase->IsScanRenderPhase());
|
|
Assert(renderPhase->HasEntityListIndex() && renderPhase->GetEntityListIndex()<MAX_NUM_RENDER_PHASES);
|
|
|
|
if(g_render_lock)
|
|
return;
|
|
|
|
RAGETRACE_SCOPE(CRenderer_ConstructRenderList);
|
|
|
|
u32 canRenderScreenDoor=0;
|
|
u32 canRenderAlpha=0;
|
|
u32 canRenderWater=0;
|
|
u32 canRenderDecal=0;
|
|
u32 canPreRender=0;
|
|
|
|
s32 list = renderPhase->GetEntityListIndex();
|
|
u32 listBitMask = 1 << list;
|
|
|
|
if(renderFlags & RENDER_SETTING_RENDER_ALPHA_POLYS)
|
|
{
|
|
canRenderAlpha |= listBitMask;
|
|
}
|
|
if(renderFlags & RENDER_SETTING_RENDER_WATER)
|
|
{
|
|
canRenderWater |= listBitMask;
|
|
}
|
|
if(renderFlags & RENDER_SETTING_RENDER_CUTOUT_POLYS)
|
|
{
|
|
canRenderScreenDoor |= listBitMask;
|
|
}
|
|
if(renderFlags & RENDER_SETTING_RENDER_DECAL_POLYS)
|
|
{
|
|
canRenderDecal |= listBitMask;
|
|
}
|
|
if(renderFlags & RENDER_SETTING_ALLOW_PRERENDER)
|
|
{
|
|
canPreRender |= listBitMask;
|
|
}
|
|
|
|
if (CDrawListMgr::IsShadowDrawList(renderPhase->GetDrawListType()))
|
|
{
|
|
CRenderer::OrInShadowPhases(listBitMask);
|
|
}
|
|
else if (CDrawListMgr::IsGBufDrawList(renderPhase->GetDrawListType()))
|
|
{
|
|
CRenderer::SetSceneToGBufferListBits(listBitMask);
|
|
}
|
|
else if (CDrawListMgr::IsMirrorReflectionDrawList(renderPhase->GetDrawListType()))
|
|
{
|
|
CRenderer::SetMirrorListBits(listBitMask);
|
|
}
|
|
#if __BANK
|
|
else if (CDrawListMgr::IsDebugDrawList(renderPhase->GetDrawListType()))
|
|
{
|
|
CRenderer::OrInDebugPhases(listBitMask);
|
|
}
|
|
#endif // __BANK
|
|
|
|
CRenderer::OrCanRenderFlags(canRenderAlpha,canRenderWater,canRenderScreenDoor,canRenderDecal,canPreRender);
|
|
|
|
ms_bInTheSky = false;
|
|
|
|
gRenderListGroup.GetRenderListForPhase(list).InitRenderListBuild();
|
|
|
|
// TODO Assert(pRenderPhase->GetPhaseId()<MAX_PHASE_FLAGS);
|
|
|
|
renderPhase->ConstructRenderList();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// FUNCTION: PreRender
|
|
// PURPOSE: Does the stuff that needs to be done for each visible entity
|
|
// outside of the rendering loop.
|
|
//////////////////////////////////////////////////////////////////////
|
|
void CRenderer::PreRender()
|
|
{
|
|
PF_AUTO_PUSH_DETAIL("PreRender");
|
|
|
|
CParaboloidShadow::PreRender();
|
|
|
|
SSAO::Update();
|
|
|
|
UI3DDRAWMANAGER.Update();
|
|
|
|
#if __BANK
|
|
|
|
#if RSG_DURANGO
|
|
CRenderer::PrintFrameStatistic();
|
|
#endif // RSG_DURANGO
|
|
|
|
CRenderTargets::UpdateBank(false);
|
|
|
|
#if __DEV
|
|
CDebugScene::PreRender();
|
|
#endif // __DEV
|
|
|
|
#endif //__BANK
|
|
|
|
#if defined(GTA_REPLAY) && GTA_REPLAY
|
|
CVideoEditorInterface::UpdatePreRender();
|
|
#endif // defined(GTA_REPLAY) && GTA_REPLAY
|
|
|
|
}
|
|
|
|
void CRenderer::PreRenderEntities()
|
|
{
|
|
PF_AUTO_PUSH_TIMEBAR_BUDGETED("PreRenderEntities",2.0f);
|
|
|
|
PF_PUSH_TIMEBAR("CVehicle : CalcSirenPriorities");
|
|
CVehicle::CalcSirenPriorities();
|
|
PF_POP_TIMEBAR();
|
|
|
|
PF_PUSH_TIMEBAR("CWeaponComponentFlashLight : CalcFlashlightPriorites");
|
|
CWeaponComponentFlashLight::CalcFlashlightPriorities();
|
|
PF_POP_TIMEBAR();
|
|
|
|
PF_PUSH_TIMEBAR("Wait : PreRenderEntities");
|
|
CTaskScheduler::WaitOnResults();
|
|
PF_POP_TIMEBAR();
|
|
|
|
PF_PUSH_TIMEBAR( "PreRender2" );
|
|
|
|
// Kick off the second part of the plant mgr update
|
|
gPlantMgr.AsyncMemcpyBegin();
|
|
|
|
// This needs to be called before PreRender2, which will start kicking off vehicle light async jobs
|
|
CVehicleLightAsyncMgr::SetupDataForAsyncJobs();
|
|
|
|
fwEntityPreRenderList &preRender2List = gRenderListGroup.GetPreRender2List();
|
|
for (int i = 0; i < preRender2List.GetCount(); ++i)
|
|
{
|
|
CDynamicEntity *pEntity = static_cast< CDynamicEntity* >( preRender2List.GetEntity(i) );
|
|
Assert( pEntity && pEntity->GetIsDynamic() );
|
|
|
|
// Visibility scanning is completely done by now, so GetIsVisibleInSomeViewportThisFrame()
|
|
// should return the correct visibility for the main viewport for this dynamic entity this frame.
|
|
const bool bIsEntityVisibleInMainViewport = pEntity->GetIsVisibleInSomeViewportThisFrame();
|
|
pEntity->PreRender2(bIsEntityVisibleInMainViewport);
|
|
|
|
BANK_ONLY( CPostScanDebug::GetNumModelsPreRendered2Ref() += 1; )
|
|
}
|
|
PF_POP_TIMEBAR();
|
|
|
|
// Now that we're done with PreRender2, kick off a final job to handle any remaining vehicles that were queued
|
|
CVehicleLightAsyncMgr::KickJobForRemainingVehicles();
|
|
|
|
// NEED to process 3DUI and headshot peds here so they get registered with the damage system (they don't seem to be in the preRender2List)
|
|
#if __BANK
|
|
UI3DDRAWMANAGER.UpdateDebug();
|
|
#endif
|
|
PedHeadshotManager::GetInstance().PreRender();
|
|
UI3DDrawManager::GetInstance().PreRender();
|
|
|
|
CAsyncLightOcclusionMgr::StartAsyncProcessing();
|
|
|
|
PF_PUSH_TIMEBAR("GameWorld Process After PreRender");
|
|
gVpMan.PushViewport(gVpMan.GetGameViewport());
|
|
{
|
|
// Process post-pre-render activities
|
|
CGameWorld::ProcessAfterPreRender();
|
|
}
|
|
gVpMan.PopViewport();
|
|
PF_POP_TIMEBAR();
|
|
|
|
// NOTE: character cloth should be here because animation expressions are waited on inside pre-render ( i.e. cloth update has to be after expressions have finished )
|
|
if( !fwTimer::IsGamePaused() )
|
|
{
|
|
CPhysics::RopeSimUpdate( fwTimer::GetTimeStep(), ROPE_UPDATE_LATE );
|
|
}
|
|
|
|
CPhysics::GetClothManager()->SwapBuffers();
|
|
CPhysics::VerletSimUpdate( clothManager::Character );
|
|
|
|
// Timecycle async query needs to finish before Visual Effects Update.
|
|
CTimeCycleAsyncQueryMgr::WaitForAsyncProcessingToFinish();
|
|
|
|
PF_PUSH_TIMEBAR("VisualEffects Update After PreRender");
|
|
CVisualEffects::UpdateAfterPreRender();
|
|
PF_POP_TIMEBAR();
|
|
|
|
CAsyncLightOcclusionMgr::ProcessResults();
|
|
|
|
CVehicleLightAsyncMgr::ProcessResults();
|
|
|
|
CParaboloidShadow::UpdateAfterPreRender(); // this needs to be after all moving lights are added.
|
|
|
|
g_SceneStreamerMgr.GetStreamingLists().WaitForSort();
|
|
|
|
//Sorting lights after paraboloid shadows update
|
|
PF_PUSH_TIMEBAR("Process Lights Visibility/Sort");
|
|
Lights::ProcessVisibilitySortAsync();
|
|
PF_POP_TIMEBAR();
|
|
|
|
CLODLights::WaitForProcessVisibilityDependency();
|
|
g_distantLights.WaitForProcessVisibilityDependency();
|
|
gPlantMgr.AsyncMemcpyEnd();
|
|
}
|
|
|
|
RAGETRACE_DECL(CRenderer_PreRender);
|
|
|
|
bool g_debugNonEdgeShadows =true;
|
|
bool g_debugEdgeShadows =true;
|
|
|
|
extern bool g_render_lock;
|
|
//
|
|
// name: CRenderer::ClearRenderLists
|
|
// description: Clear all the render lists
|
|
void CRenderer::ClearRenderLists()
|
|
{
|
|
if(g_render_lock)
|
|
return;
|
|
|
|
gRenderListGroup.Clear();
|
|
CRenderer::SetSceneToGBufferListBits(0);
|
|
CRenderer::SetMirrorListBits(0);
|
|
CRenderer::SetShadowPhases(0);
|
|
#if __BANK
|
|
CRenderer::SetDebugPhases(0);
|
|
#endif // __BANK
|
|
}
|
|
|
|
|
|
int CRenderer::GetRenderListVisibleCount(int list)
|
|
{
|
|
fwRenderListDesc& renderList = gRenderListGroup.GetRenderListForPhase(list);
|
|
return renderList.GetNumberOfEntities(RPASS_VISIBLE)+renderList.GetNumberOfEntities(RPASS_LOD);
|
|
}
|
|
|
|
#if __PS3
|
|
float CRenderer::SetDepthBoundsFromRange(float nearClip, float farClip, float nearZ, float farZ, bool excludeSky/*=true*/)
|
|
{
|
|
Assert(nearZ<=farZ);
|
|
Assert(nearClip<=farClip);
|
|
const float linearMin = Clamp<float>(nearZ, nearClip, farClip);
|
|
const float linearMax = Clamp<float>(farZ, nearClip, farClip);
|
|
|
|
const float Q = farClip/(farClip - nearClip);
|
|
|
|
const float sampleMin = (Q/linearMin)*(linearMin - nearClip);
|
|
const float sampleMax = (Q/linearMax)*(linearMax - nearClip);
|
|
|
|
if (excludeSky && (farClip == farZ))
|
|
{
|
|
// set it to the furthest possible bound before the sky
|
|
|
|
// The furthest depth value that can be represented in fixed
|
|
// point lones is 0xfffff8 (corresponds to znear 0xffff).
|
|
// We want the depth bounds to therefore be the next closest
|
|
// value representable in zcull, 0xfffe, which is depth
|
|
// 0xfffff0.
|
|
//
|
|
// So that sounds great in theory... but that logic leads to
|
|
// the float 0x3f7ffff0, which does not cull the sky. By
|
|
// pure trial and error, the largest float that will cause
|
|
// the sky to get culled is 0x3f7ffeff. Don't know where
|
|
// that values comes from, but it works.
|
|
//
|
|
grcDevice::SetDepthBounds(sampleMin, 0x1.fffdfep-1);
|
|
}
|
|
else
|
|
{
|
|
grcDevice::SetDepthBounds(sampleMin, sampleMax);
|
|
}
|
|
|
|
return sampleMin; // return nearZ in depth sample space
|
|
}
|
|
|
|
#endif
|
|
#if __BANK
|
|
|
|
static void SetAddEntityToRenderListDebugModel()
|
|
{
|
|
fwModelId modelId;
|
|
CModelInfo::GetBaseModelInfoFromName(gAddEntityToRenderListDebugModelName, &modelId);
|
|
gAddEntityToRenderListDebugModel = modelId.GetModelIndex();
|
|
}
|
|
|
|
static void SetSetupMapEntityVisibilityDebugModel()
|
|
{
|
|
fwModelId modelId;
|
|
CModelInfo::GetBaseModelInfoFromName(gSetupMapEntityVisibilityDebugModelName, &modelId);
|
|
gSetupMapEntityVisibilityDebugModel = modelId.GetModelIndex();
|
|
}
|
|
|
|
static grcEffectGlobalVar g_AmbDirBiasVar = (grcEffectGlobalVar)0;
|
|
static Vec4f g_AmbDirBias(0.0f,0.0f,1.0f,0.5f);
|
|
void SetGlobalAmbDirBiasCB()
|
|
{
|
|
grcEffect::SetGlobalVar(g_AmbDirBiasVar, g_AmbDirBias);
|
|
}
|
|
|
|
extern bool PostFX::g_lightRaysAboveWaterLine;
|
|
extern bool g_bRenderExteriorReflection;
|
|
|
|
static bool g_prevDensityMultiplierSaved = false;
|
|
static float g_prevOverrideVehDensityMultiplier;
|
|
static float g_prevOverridePedDensityMultiplier;
|
|
|
|
void SetLastGenMode()
|
|
{
|
|
if ( (gLastGenMode != gLastGenModeState) )
|
|
{
|
|
if (gLastGenModeState == true)
|
|
{
|
|
SSAO::Enable(false);
|
|
PostFX::g_lightRaysAboveWaterLine = false;
|
|
CWorldDebugHelper::SetEarlyRejectExtraDistCull(true);
|
|
CWorldDebugHelper::SetEarlyRejectMaxDist(1000);
|
|
CWorldDebugHelper::SetEarlyRejectMinDist(0);
|
|
|
|
g_bRenderExteriorReflection = false;
|
|
|
|
extern CRenderSettings g_widgetRenderSettings;
|
|
g_widgetRenderSettings.SetLODScale(0.65f);
|
|
g_distantLights.SetRenderingEnabled(false);
|
|
}
|
|
else
|
|
{
|
|
SSAO::Enable(true);
|
|
PostFX::g_lightRaysAboveWaterLine = true;
|
|
CWorldDebugHelper::SetEarlyRejectExtraDistCull(false);
|
|
|
|
g_bRenderExteriorReflection = true;
|
|
|
|
extern CRenderSettings g_widgetRenderSettings;
|
|
g_widgetRenderSettings.SetLODScale(1.0);
|
|
g_distantLights.SetRenderingEnabled(true);
|
|
}
|
|
|
|
if (gLastGenModeState )
|
|
{
|
|
g_prevOverrideVehDensityMultiplier = CVehiclePopulation::GetDebugOverrideMultiplier();
|
|
g_prevOverridePedDensityMultiplier = CPedPopulation::GetDebugOverrideMultiplier();
|
|
g_prevDensityMultiplierSaved = true;
|
|
|
|
PostFX::SetFXAA(false);
|
|
ptfxDebug::SetDisablePtFx(true);
|
|
|
|
CVehiclePopulation::SetDebugOverrideMultiplier( 0.4f );
|
|
CPedPopulation::SetDebugOverrideMultiplier( 0.5f );
|
|
}
|
|
else
|
|
{
|
|
#if !(__D3D11 || RSG_ORBIS) && 0
|
|
PostFX::SetFXAA(!GRCDEVICE.GetMSAA()); // Re-enable only if we're not using MSAA
|
|
#endif // !(__D3D11 || RSG_ORBIS)
|
|
ptfxDebug::SetDisablePtFx(false);
|
|
|
|
if ( g_prevDensityMultiplierSaved )
|
|
{
|
|
CVehiclePopulation::SetDebugOverrideMultiplier( g_prevOverrideVehDensityMultiplier );
|
|
CPedPopulation::SetDebugOverrideMultiplier( g_prevOverridePedDensityMultiplier );
|
|
g_prevDensityMultiplierSaved = false;
|
|
}
|
|
}
|
|
|
|
gLastGenMode = gLastGenModeState;
|
|
}
|
|
}
|
|
|
|
PARAM(rag_renderer,"rag_renderer");
|
|
|
|
#if DEVICE_EQAA
|
|
namespace rage {
|
|
#if RSG_ORBIS
|
|
extern bool s_CopyByCompute;
|
|
extern bool s_AllowGPUClear, s_AllowFastClearStencil;
|
|
extern bool s_UseClearDbControl;
|
|
#endif
|
|
namespace eqaa {
|
|
extern int s_ResolveHighQuality;
|
|
extern bool s_ResolveHighQualityS1;
|
|
}
|
|
}
|
|
#endif //DEVICE_EQAA
|
|
|
|
void CRenderer::InitWidgets()
|
|
{
|
|
// Create the renderer bank
|
|
bkBank* pBank = &BANKMGR.CreateBank("Renderer", 0, 0, false);
|
|
if(renderVerifyf(pBank, "Failed to create renderer bank"))
|
|
{
|
|
if (PARAM_rag_renderer.Get())
|
|
{
|
|
AddWidgets();
|
|
PostFX::AddWidgetsOnDemand();
|
|
}
|
|
else
|
|
{
|
|
pBank->AddButton("Create Renderer widgets", datCallback(CFA1(CRenderer::AddWidgets), pBank));
|
|
}
|
|
}
|
|
|
|
DebugLights::InitWidgets();
|
|
DebugLighting::AddWidgets();
|
|
CPortalDebugHelper::InitInteriorWidgets();
|
|
|
|
ShmooHandling::AddWidgets(*pBank);
|
|
|
|
#if RSG_ORBIS
|
|
{
|
|
bkBank *pDebug = BANKMGR.FindBank("Debug");
|
|
pDebug->PushGroup("Orbis computing");
|
|
pDebug->AddToggle("Use CS RT copy", &rage::s_CopyByCompute,
|
|
NullCallback, "Use compute shaders to copy render targets");
|
|
pDebug->AddToggle("Allow GPU clear", &rage::s_AllowGPUClear,
|
|
NullCallback, "Use compute shaders to clear buffers");
|
|
pDebug->AddToggle("Use CS clear (stencil)", &rage::s_AllowFastClearStencil,
|
|
NullCallback, "Use compute shaders to clear raw stencil data");
|
|
pDebug->AddToggle("Use DbRenderControl", &rage::s_UseClearDbControl,
|
|
NullCallback, "Use another fast-clear path for depth & stencil");
|
|
pDebug->PopGroup();
|
|
}
|
|
#endif //RSG_ORBIS
|
|
#if DEVICE_EQAA
|
|
{
|
|
bkBank *pDebug = BANKMGR.FindBank("Debug");
|
|
pDebug->PushGroup("EQAA");
|
|
pDebug->AddSlider("HQ resolve Mode", &rage::eqaa::s_ResolveHighQuality, -1, 1, 1);
|
|
pDebug->AddToggle("Force HQ resolve for S/1", &rage::eqaa::s_ResolveHighQualityS1);
|
|
#if AA_SAMPLE_DEBUG
|
|
eqaa::Debug &ed = eqaa::GetDebug();
|
|
pDebug->PushGroup("Custom Pattern");
|
|
pDebug->AddToggle("Use Deprecated Mode", &ed.useDeprecatedPattern,
|
|
NullCallback, "Use the previously written hand-made pattern for comparison.");
|
|
pDebug->AddSlider("Radius", &ed.patternRadius, 0.f, 1.f, 0.1f);
|
|
pDebug->AddSlider("Angle Offset", &ed.patternOffset, 0.f, 360.f, 1.f);
|
|
pDebug->PopGroup();
|
|
pDebug->PushGroup("Resolve Params");
|
|
pDebug->AddSlider("Side Weight", &ed.resolveSideWeight, 0.f, 0.5f, 0.01f);
|
|
pDebug->AddSlider("Depth Threshold", &ed.resolveDepthThreshold, 0.f, 1.f, 0.001f);
|
|
pDebug->AddToggle("Skip Blending Edges", &ed.resolveSkipEdges);
|
|
pDebug->PopGroup();
|
|
#endif //AA_SAMPLE_DEBUG
|
|
#if RSG_ORBIS
|
|
eqaa::Control &ct = eqaa::GetControl();
|
|
pDebug->PushGroup("Depth Control");
|
|
pDebug->AddToggle("Incoherent Eqaa Reads", &ct.incoherentEqaaReads,
|
|
NullCallback, "Enables the coherency check for abutting triangles that share anchor samples, but not detail samples.");
|
|
pDebug->AddToggle("Static Anchor Associations", &ct.staticAnchorAssociations,
|
|
NullCallback, "Forces replicated destination data to always come from the statically associated anchor sample.");
|
|
pDebug->AddToggle("Interpolate Compressed Z", &ct.interpolateCompressedZ,
|
|
NullCallback, "Allows unanchored samples to interpolate a unique Z from compressed Z Planes.");
|
|
pDebug->AddToggle("High Quality Tile Intersections", &ct.highQualityTileIntersections,
|
|
NullCallback, "Enables high-quality tile intersections.");
|
|
pDebug->PopGroup();
|
|
#endif //RSG_ORBIS
|
|
pDebug->PopGroup();
|
|
}
|
|
#endif //DEVICE_EQAA
|
|
|
|
bkBank* pOptBank = BANKMGR.FindBank("Optimization");
|
|
pOptBank->AddToggle("Draw Cloth", &g_DrawCloth );
|
|
pOptBank->AddToggle("Draw Peds", &g_DrawPeds );
|
|
pOptBank->AddToggle("Draw Vehicles", &g_DrawVehicles );
|
|
pOptBank->PushGroup("Skip Rendering Shaders");
|
|
pOptBank->AddToggle("Enable", &g_EnableSkipRenderingShaders);
|
|
pOptBank->AddToggle("Disable fur grass shaders",&g_SkipRenderingGrassFur);
|
|
pOptBank->AddToggle("Disable tree shaders", &g_SkipRenderingTrees);
|
|
pOptBank->PopGroup();
|
|
|
|
CCustomShaderEffectCable::InitOptimisationWidgets(*pOptBank);
|
|
}
|
|
|
|
//
|
|
// name: CRenderer::AddWidgets
|
|
// description: Add bank widgets for renderer class
|
|
extern bank_bool g_show_water_clip;
|
|
extern bank_bool g_cache_entities;
|
|
extern bool g_prototype_batch;
|
|
namespace FPSPedDraw {
|
|
extern BankBool sEnable3rdPersonSkel;
|
|
}
|
|
|
|
void CRenderer::AddWidgets()
|
|
{
|
|
// destroy first widget which is the create button
|
|
bkWidget* pWidget = BANKMGR.FindWidget("Renderer/Create Renderer widgets");
|
|
if(pWidget)
|
|
{
|
|
pWidget->Destroy();
|
|
}
|
|
|
|
bkBank* pRendererBank = BANKMGR.FindBank("Renderer");
|
|
Assert(pRendererBank);
|
|
bkBank& bank = *pRendererBank;
|
|
|
|
bank.AddToggle("LASTGEN", &gLastGenModeState);
|
|
bank.AddToggle("Enable Snow", &ms_isSnowing);
|
|
bank.PushGroup("Plants");
|
|
bank.AddToggle("All Plants Enabled", &ms_bPlantsAllEnabled, PlantsToggleCB);
|
|
bank.AddToggle("Display Debug Info", &ms_bPlantsDisplayDebugInfo, PlantsDisplayDebugInfoCB);
|
|
bank.AddToggle("Alpha Overdraw", &ms_bPlantsAlphaOverdraw, PlantsAlphaOverDrawCB);
|
|
bank.PopGroup();
|
|
bank.AddToggle("Show clip water quads against frustum", &g_show_water_clip);
|
|
bank.AddToggle("Cache entity draw data", &g_cache_entities);
|
|
bank.AddToggle("Batch entity draw", &g_prototype_batch);
|
|
bank.AddToggle("Add model names to GPAD/PIX captures", &g_AddModelGcmMarkers);
|
|
|
|
CCustomShaderEffectAnimUV::InitWidgets(bank);
|
|
CCustomShaderEffectCable::InitWidgets(bank);
|
|
CCustomShaderEffectMirror::InitWidgets(bank);
|
|
#if __DEV
|
|
extern void InitBypassWidgets(bkBank& bk);
|
|
InitBypassWidgets(bank);
|
|
#endif // __DEV
|
|
#if __BANK
|
|
extern void InitRenderWidgets(bkBank& bk);
|
|
InitRenderWidgets(bank);
|
|
#endif
|
|
|
|
#if RSG_DURANGO
|
|
bank.AddToggle("Display Frame Statistics", &g_DisplayFrameStatistics);
|
|
#endif // RSG_DURANGO
|
|
bank.AddToggle("Disable Artificial Lights",&sm_disableArtificialLights);
|
|
bank.AddSlider("DAL Emissive Scale",&CShaderLib::ms_overridesEmissiveScale,0.0f,1.0f,0.1f);
|
|
bank.AddSlider("DAL Emissive Mult",&CShaderLib::ms_overridesEmissiveMult,0.0f,1.0f,0.1f);
|
|
bank.AddSlider("DAL Art Int Amb Down",&CShaderLib::ms_overridesArtIntAmbDown,0.0f,255.0f,0.1f);
|
|
bank.AddSlider("DAL Art Int Amb Base",&CShaderLib::ms_overridesArtIntAmbBase,0.0f,255.0f,0.1f);
|
|
bank.AddSlider("DAL Art Ext Amb Down",&CShaderLib::ms_overridesArtExtAmbDown,0.0f,255.0f,0.1f);
|
|
bank.AddSlider("DAL Art Ext Amb Base",&CShaderLib::ms_overridesArtExtAmbBase,0.0f,255.0f,0.1f);
|
|
bank.AddSlider("DAL Art Amb Scale",&CShaderLib::ms_overridesArtAmbScale,0.0f,1.0f,0.1f);
|
|
|
|
#if GCM_HUD
|
|
bank.PushGroup("Gcm Hud", false);
|
|
{
|
|
s_bGcmHudEnabled = grcCellGcmHudIsEnabled;
|
|
bank.AddToggle("Enable Gcm Hud *BUGGED*", &s_bGcmHudEnabled, datCallback(CFA(ToggleGcmHud)), "Enable/Disable Gcm Hud");
|
|
bank.AddToggle("Enable render phase tags", &g_bGcmHudRenderPhaseTags, NullCB, "Enable/Disable RenderPhase tagging");
|
|
}
|
|
bank.PopGroup();
|
|
#endif
|
|
|
|
bank.PushGroup("Streaming High Priority settings", false);
|
|
{
|
|
bank.AddToggle("Show streaming on Vmap", &g_show_streaming_on_vmap,NullCB);
|
|
bank.AddSlider("High Priority angle degrees", &g_HighPriorityYaw, 0.0f, 90.f, 1.0f ,NullCB,"Inner Cone around camera view vector considered to be high priority for streaming if an entities bounding sphere overlaps it");
|
|
bank.AddToggle("Show High Priority Spheres", &g_HighPrioritySphere,NullCB," Show the bounding sphere for high priority objects");
|
|
bank.AddSlider("Subtended Angle For High Priority Consideration", &g_ScreenYawForPriorityConsideration,0.0f,90.0f,0.5f,NullCB," Angle subtended by object (ie decreases with distance) required to be considered for HP");
|
|
}
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Optimisations WIP", false);
|
|
{
|
|
bank.AddSlider("Show pre rendered", &g_show_prerendered,0,3,1,NullCB,"");
|
|
bank.AddToggle("Hide Debug Objects", &g_HideDebug);
|
|
bank.AddToggle("Use multipass List Processing", &g_multipass_list_gen);
|
|
bank.AddToggle("Only Swap Timed objects When Offscreen", &b_OnlySwapTimedWhenOffscreen);
|
|
bank.AddToggle("Lock Render List and Pause Game", &g_render_lock);
|
|
bank.AddSlider("renderPhase to use for main render", &g_alternativeViewport, -1, (int)40, 1 );
|
|
|
|
bank.AddToggle("Sort Lod and Visible Lists", &g_SortRenderLists);
|
|
bank.AddToggle("Sort Tree List", &g_SortTreeList);
|
|
bank.AddToggle("Use GTAIV two pass tree rendering ", &g_UseTwoPassTreeRendering );
|
|
bank.AddToggle("Use GTAIV two pass tree normal flipping ", &g_UseTwoPassTreeNormalFlipping );
|
|
bank.AddToggle("Use Single SetDoubleSided Call for trees cutout", &g_DoubleSidedTreesCutoutOptimization);
|
|
|
|
bank.AddToggle("Use two pass shadow tree rendering ", &g_UseTwoPassTreeShadowRendering );
|
|
bank.AddToggle("Use delayed Gbuffer2 tile resolve ", &g_UseDelayedGbuffer2TileResolve );
|
|
}
|
|
bank.PopGroup();
|
|
|
|
InstancedRendererConfig::AddWidgets(bank);
|
|
CEntityBatch::AddWidgets(bank);
|
|
|
|
#if __XENON
|
|
bank.PushGroup("GPR Allocations", false);
|
|
{
|
|
bank.AddSlider("DefaultPsRegs", &CGPRCounts::ms_DefaultPsRegs, 16, 112, 1);
|
|
bank.AddSlider("CascadedGenPsRegs", &CGPRCounts::ms_CascadedGenPsRegs, 16, 112, 1);
|
|
bank.AddSlider("CascadedRevealPsRegs", &CGPRCounts::ms_CascadedRevealPsRegs, 16, 112, 1);
|
|
bank.AddSlider("EnvReflectGenPsRegs", &CGPRCounts::ms_EnvReflectGenPsRegs, 16, 112, 1);
|
|
bank.AddSlider("EnvReflectBlurPsRegs", &CGPRCounts::ms_EnvReflectBlurPsRegs, 16, 112, 1);
|
|
bank.AddSlider("GBufferPsRegs", &CGPRCounts::ms_GBufferPsRegs, 16, 112, 1);
|
|
bank.AddSlider("DefLightingPsRegs", &CGPRCounts::ms_DefLightingPsRegs, 16, 112, 1);
|
|
bank.AddSlider("WaterCompositePsRegs", &CGPRCounts::ms_WaterCompositePsRegs, 16, 112, 1);
|
|
bank.AddSlider("DepthFXPsRegs", &CGPRCounts::ms_DepthFXPsRegs, 16, 112, 1);
|
|
bank.AddSlider("PostFXPsRegs", &CGPRCounts::ms_PostFXPsRegs, 16, 112, 1);
|
|
}
|
|
bank.PopGroup();
|
|
#endif // __XENON
|
|
|
|
gVpMan.SetupRenderPhaseWidgets(bank);
|
|
|
|
bank.PushGroup("Debug Info", false);
|
|
{
|
|
bank.AddButton("Collision geometry", datCallback(CFA(ToggleRenderCollisionGeometry)));
|
|
}
|
|
bank.PopGroup();
|
|
#ifdef DEBUG_RENDERER
|
|
const u32 maxModelInfos = CModelInfo::GetMaxModelInfos();
|
|
|
|
bank.PushGroup("Debug RenderList", false);
|
|
{
|
|
bank.AddText("AddEntityToRenderList", &gAddEntityToRenderListDebugModelName[0],
|
|
sizeof(gAddEntityToRenderListDebugModelName), false, &SetAddEntityToRenderListDebugModel);
|
|
bank.AddSlider("AddEntityToRenderList", &gAddEntityToRenderListDebugModel, 0, maxModelInfos, 1);
|
|
bank.AddText("SetupMapEntityVisibility", &gSetupMapEntityVisibilityDebugModelName[0],
|
|
sizeof(gSetupMapEntityVisibilityDebugModelName), false, &SetSetupMapEntityVisibilityDebugModel);
|
|
bank.AddSlider("SetupMapEntityVisibility", &gSetupMapEntityVisibilityDebugModel, 0, maxModelInfos, 1);
|
|
|
|
bank.AddToggle("Count models rendered", &CPostScanDebug::GetCountModelsRenderedRef() );
|
|
bank.AddToggle("Count shaders rendered", &CPostScanDebug::GetCountShadersRenderedRef() );
|
|
}
|
|
bank.PopGroup();
|
|
#endif // DEBUG_RENDERER
|
|
|
|
CFrustumDebug::AddWidgets(bank);
|
|
|
|
CPlantMgr::InitWidgets(bank);
|
|
|
|
#if SPUPMMGR_ENABLED
|
|
CSpuPmMgr::InitWidgets(bank);
|
|
#endif // SPUPMMGR_ENABLED
|
|
|
|
DebugRenderingMgr::AddWidgets(&bank);
|
|
SSAO::AddWidgets(bank);
|
|
Lights::AddWidgets(bank);
|
|
|
|
gDebugVolumeGlobals.AddWidgets(bank);
|
|
gShadows.AddWidgets(bank);
|
|
|
|
GOLFGREENGRID.AddWidgets(&bank);
|
|
UI3DDRAWMANAGER.AddWidgets(&bank);
|
|
|
|
PostFX::AddWidgets(bank);
|
|
|
|
OcclusionQueries::AddWidgets(bank);
|
|
|
|
gDrawListMgr->SetupWidgets(bank);
|
|
#if __XENON
|
|
bank.AddSlider("HDR Color Exp Bias", &CRenderer::sm_backbufferColorExpBiasHDR, -4, 4, 1 );
|
|
bank.AddSlider("LDR Color Exp Bias", &CRenderer::sm_backbufferColorExpBiasLDR, -4, 4, 1 );
|
|
#endif
|
|
|
|
#if __DEV
|
|
CDebugScene::AddModelViewerBankWidgets(bank);
|
|
#endif // __DEV
|
|
|
|
CRenderListBuilder::AddWidgets(bank);
|
|
|
|
bkBank *pBank = BANKMGR.FindBank("Optimization");
|
|
pBank->AddToggle("count models rendered", &CPostScanDebug::GetCountModelsRenderedRef() );
|
|
pBank->AddToggle("count shaders rendered", &CPostScanDebug::GetCountShadersRenderedRef() );
|
|
pBank->AddButton("collision geometry", datCallback(CFA(ToggleRenderCollisionGeometry)));
|
|
|
|
CRenderTargets::AddWidgets(bank);
|
|
|
|
COcclusion::InitWidgets();
|
|
CPortalDebugHelper::InitWidgets();
|
|
Water::InitWidgets();
|
|
PuddlePassSingleton::InstanceRef().InitWidgets();
|
|
#if USE_TREE_IMPOSTERS
|
|
CTreeImposters::InitWidgets();
|
|
#endif // USE_TREE_IMPOSTERS
|
|
#if CSE_TREE_EDITABLEVALUES
|
|
CCustomShaderEffectTree::InitWidgets(bank);
|
|
#endif
|
|
|
|
#if CSE_TINT_EDITABLEVALUES
|
|
CCustomShaderEffectTint::InitWidgets(bank);
|
|
#endif
|
|
|
|
g_ShaderEdit::InstanceRef().AddRendererWidgets();
|
|
CRenderPhaseDebugOverlayInterface::AddWidgets();
|
|
|
|
CRenderPhaseLensDistortion::InitWidgets();
|
|
|
|
MESHBLENDMANAGER.AddWidgets(bank);
|
|
|
|
#if __D3D11 || RSG_ORBIS
|
|
bank.PushGroup("Shader Model 5");
|
|
# if RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
bank.PushGroup("POM / Displacement", false);
|
|
|
|
bank.AddToggle("Disable POM", &ms_DisablePOM);
|
|
bank.AddToggle("POM Distance Fade", &m_POMDistanceFade);
|
|
bank.AddToggle("Visualise POM Distance Fade Settings", &ms_VisPOMDistanceFade);
|
|
bank.AddToggle("Visualise POM Vertex Weights", &ms_VisPOMVertexHeight);
|
|
bank.AddSlider("Near Fade", &ms_POMNear, 0.0f, 60.0f, 0.5f);
|
|
bank.AddSlider("Far Fade", &ms_POMFar, 0.0f, 100.0f, 0.5f);
|
|
bank.AddSlider("Forward Fade Offset", &ms_POMForwardOffset, 0.0f, 20.0f, 0.5f);
|
|
bank.AddSlider("Min Sample", &ms_POMMinSamp, 0.0f, 20.0f, 1.0f);
|
|
bank.AddSlider("Max Sample", &ms_POMMaxSamp, 0.0f, 50.0f, 1.0f);
|
|
bank.AddSlider("Global Height Scale", &ms_GlobalHeightScale, 0.0f, 2.0f, 0.01f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Terrain Tint Blend", false);
|
|
bank.AddSlider("Blend Start", &ms_TerrainTintBlendNear, 0.0f, 100.0f, 1.0f);
|
|
bank.AddSlider("Blend finish", &ms_TerrainTintBlendFar, 10.0f, 200.0f, 1.0f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Tessellation", false);
|
|
bank.AddSlider("Wheel Tessellation", &ms_WheelTessellationFactor, 1, 10, 1 );
|
|
bank.AddSlider("Tree Tessellation", &ms_TreeTessellationFactor, 1, 10, 1 );
|
|
bank.AddSlider("Tree K Factor", &ms_TreeTessellation_PNTriangle_K, 0.0f, 1.0f, 0.05f );
|
|
|
|
bank.AddSlider("Tessellation - Near", &ms_LinearNear, 0.01f, 200.0f, 0.25f );
|
|
bank.AddSlider("Tessellation - Far", &ms_LinearFar, 0.01f, 200.0f, 0.25f );
|
|
bank.AddSlider("Tessellation - Allowed error in pixels", &ms_ScreenSpaceErrorInPixels, 0.001f, 100.0f, 0.001f );
|
|
bank.AddSlider("Tessellation - Max", &ms_MaxTessellation, 1, 16, 1);
|
|
|
|
bank.AddSlider("Tessellation - Frustum Epsilon", &ms_FrustumEpsilon, -1000.00f, 1000.0f, 0.001f );
|
|
bank.AddSlider("Tessellation - BackFace Cull Epsilon", &ms_BackFaceEpsilon, -1.00f, 1.0f, 0.001f );
|
|
bank.AddToggle("Tessellation - Cull", &ms_CullEnable);
|
|
bank.PopGroup();
|
|
# endif // RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
|
|
# if TRACK_CONSTANT_BUFFER_CHANGES
|
|
bank.AddToggle("Track ConstantBuffer Usage", &grcEffect::sm_TrackConstantBufferUsage);
|
|
bank.AddToggle("Reset counters after each frame", &grcEffect::sm_TrackConstantBufferResetFrame);
|
|
bank.AddToggle("Print ConstantBuffer Usage (requires track on)", &grcEffect::sm_PrintConstantBufferUsage);
|
|
bank.AddToggle("Only print changed constant buffers", &grcEffect::sm_PrintConstantBufferUsageOnlyChanged);
|
|
# endif // TRACK_CONSTANT_BUFFER_CHANGES
|
|
|
|
#if RSG_PC
|
|
bank.AddToggle("SetUAV to NULL rather than NULL Buffer", &grcEffect::sm_SetUAVNull);
|
|
#endif // RSG_PC
|
|
|
|
bank.PopGroup();
|
|
#endif //__D3D11 || RSG_ORBIS
|
|
|
|
#if TERRAIN_TESSELLATION_SUPPORT
|
|
CRenderPhaseDeferredLighting_SceneToGBuffer::AddTerrainWidgets(bank);
|
|
#endif //TERRAIN_TESSELLATION_SUPPORT
|
|
|
|
#if CASCADE_SHADOWS_DO_SOFT_FILTERING
|
|
CRenderPhaseCascadeShadowsInterface::InitWidgets_SoftShadows(bank);
|
|
#endif
|
|
|
|
#if LINEAR_PIECEWISE_FOG
|
|
LinearPiecewiseFog::AddWidgets(bank);
|
|
#endif // LINEAR_PIECEWISE_FOG
|
|
|
|
bank.AddToggle("Render FPS Ped with 3rd person IK in non-gbuffer phases", &FPSPedDraw::sEnable3rdPersonSkel);
|
|
}
|
|
#endif //__BANK
|
|
|
|
|
|
RAGETRACE_DECL(CRenderer_WaitForSPU);
|
|
|
|
int g_stream_model=-100;
|
|
|
|
bool dump_stats=false;
|
|
void CRenderer::IssueAllScanTasksNew()
|
|
{
|
|
if(g_render_lock)
|
|
return;
|
|
|
|
if (!g_SceneToGBufferPhaseNew)
|
|
return;
|
|
|
|
PF_START_TIMEBAR_BUDGETED("Issued scan tasks",1.0f);
|
|
|
|
Assert(g_SceneToGBufferPhaseNew);
|
|
CRenderer::SetSceneToGBufferListBits(1<<g_SceneToGBufferPhaseNew->GetEntityListIndex());
|
|
CRenderer::SetMirrorListBits(1<<CRenderPhaseMirrorReflectionInterface::GetRenderPhase()->GetEntityListIndex());
|
|
CRenderer::SetShadowPhases(0);
|
|
#if __BANK
|
|
CRenderer::SetDebugPhases(0);
|
|
#endif // __BANK
|
|
|
|
int phaseCount = RENDERPHASEMGR.GetRenderPhaseCount();
|
|
|
|
for(int x=0; x<phaseCount; x++)
|
|
{
|
|
fwRenderPhase &pRenderPhase = RENDERPHASEMGR.GetRenderPhase(x);
|
|
|
|
if (CDrawListMgr::IsShadowDrawList(pRenderPhase.GetDrawListType()))
|
|
{
|
|
Assert(pRenderPhase.HasEntityListIndex());
|
|
CRenderer::OrInShadowPhases(1<<pRenderPhase.GetEntityListIndex());
|
|
}
|
|
#if __BANK
|
|
else if (CDrawListMgr::IsDebugDrawList(pRenderPhase.GetDrawListType()))
|
|
{
|
|
if (pRenderPhase.HasEntityListIndex())
|
|
{
|
|
CRenderer::OrInDebugPhases(1<<pRenderPhase.GetEntityListIndex());
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
|
|
CGameScan::PerformScan();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
float CRenderer::ms_bestScannedVisiblePortalArea=0.0f;
|
|
grcViewport CRenderer::ms_bestScannedVisiblePortalViewport;
|
|
s32 CRenderer::ms_bestScannedVisiblePortalIntProxyID=-1;
|
|
s32 CRenderer::ms_bestScannedVisiblePortalMainTCModifier=-1;
|
|
s32 CRenderer::ms_bestScannedVisiblePortalSecondaryTCModifier=-1;
|
|
|
|
bank_float ScannedVisibilePortalNearClip = 0.01f;
|
|
bank_float ScannedVisibilePortalFarClip = 500.0f;
|
|
|
|
const grcViewport& CRenderer::FixupScannedVisiblePortalViewport(const grcViewport& viewport)
|
|
{
|
|
ms_bestScannedVisiblePortalViewport=viewport;
|
|
|
|
// use fixed parameters, it's save us from the tc use far clip to modify far clip to use far clip to modify far clip to use far clip to modify far clip to use far clip to...
|
|
ms_bestScannedVisiblePortalViewport.SetNearFarClip(ScannedVisibilePortalNearClip,ScannedVisibilePortalFarClip); // Bank this, bitch
|
|
|
|
return ms_bestScannedVisiblePortalViewport;
|
|
}
|
|
|
|
void CRenderer::ResetScannedVisiblePortal()
|
|
{
|
|
ms_bestScannedVisiblePortalArea=0.0f;
|
|
ms_bestScannedVisiblePortalIntProxyID=-1;
|
|
}
|
|
|
|
|
|
void CRenderer::UpdateScannedVisiblePortal(CPortalInst* portalInst)
|
|
{
|
|
Assert(CSystem::IsThisThreadId(SYS_THREAD_UPDATE));
|
|
|
|
CInteriorInst* pIntInst;
|
|
s32 portalIdx0;
|
|
portalInst->GetOwnerData(pIntInst, portalIdx0);
|
|
|
|
Assert(pIntInst);
|
|
|
|
u32 portalIdx = pIntInst->GetPortalIdxInRoom(0, portalIdx0);
|
|
const fwPortalCorners& portalCorners=pIntInst->GetPortal(portalIdx);
|
|
spdAABB boundBox;
|
|
portalCorners.CalcBoundingBox(boundBox);
|
|
|
|
bool visible = COcclusion::IsBoxVisibleFast(boundBox);
|
|
|
|
if( visible )
|
|
{
|
|
float area = portalCorners.CalcScreenSurface(ms_bestScannedVisiblePortalViewport);
|
|
|
|
if (area>ms_bestScannedVisiblePortalArea)
|
|
{
|
|
ms_bestScannedVisiblePortalArea=area;
|
|
ms_bestScannedVisiblePortalIntProxyID = CInteriorProxy::GetPool()->GetJustIndex(pIntInst->GetProxy());
|
|
|
|
CMloModelInfo* modelInfo = pIntInst->GetMloModelInfo();
|
|
unsigned int roomId1,roomId2;
|
|
CPortalFlags flags;
|
|
|
|
modelInfo->GetPortalData(portalIdx,roomId1,roomId2,flags);
|
|
int roomId = Max(roomId1,roomId2);
|
|
|
|
pIntInst->GetTimeCycleIndicesForRoom(roomId, ms_bestScannedVisiblePortalMainTCModifier, ms_bestScannedVisiblePortalSecondaryTCModifier);
|
|
}
|
|
|
|
if( portalInst->GetUseLightBleed() )
|
|
{
|
|
const Vec3V camPos = VECTOR3_TO_VEC3V(camInterface::GetPos());
|
|
const ScalarV portalDist = portalCorners.CalcSimpleDistanceToPointSquared(camPos);
|
|
|
|
const Vec3V extent = (portalCorners.GetCornerV(0) - portalCorners.GetCornerV(2))*ScalarV(V_HALF);
|
|
const ScalarV extentMagSquared = Max(ScalarV(V_FIFTEEN)*ScalarV(V_FIFTEEN), MagSquared(extent));
|
|
|
|
if(IsLessThanAll(portalDist, extentMagSquared))
|
|
{
|
|
CMloModelInfo* modelInfo = pIntInst->GetMloModelInfo();
|
|
unsigned int roomId1,roomId2;
|
|
int timeCycleIndex, secondaryTimeCycleIndex;
|
|
CPortalFlags flags;
|
|
|
|
modelInfo->GetPortalData(portalIdx,roomId1,roomId2,flags);
|
|
int roomId = Max(roomId1,roomId2);
|
|
|
|
pIntInst->GetTimeCycleIndicesForRoom(roomId, timeCycleIndex, secondaryTimeCycleIndex);
|
|
if( timeCycleIndex != -1 )
|
|
{
|
|
float doorOcclusion = flags.GetAllowClosing() ? CPortal::GetDoorOcclusion(pIntInst, portalIdx) : 1.0f;
|
|
g_timeCycle.AddLocalPortal(portalCorners,area,doorOcclusion,timeCycleIndex,secondaryTimeCycleIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CRenderer::TwoPassTreeRenderingEnabled()
|
|
{
|
|
return g_UseTwoPassTreeRendering;
|
|
}
|
|
|
|
bool CRenderer::TwoPassTreeNormalFlipping()
|
|
{
|
|
return g_UseTwoPassTreeNormalFlipping;
|
|
}
|
|
|
|
bool CRenderer::DoubleSidedTreesCutoutOptimization()
|
|
{
|
|
return g_DoubleSidedTreesCutoutOptimization;
|
|
}
|
|
bool CRenderer::TwoPassTreeShadowRenderingEnabled()
|
|
{
|
|
return g_UseTwoPassTreeShadowRendering;
|
|
}
|
|
|
|
bool CRenderer::UseDelayedGbuffer2TileResolve()
|
|
{
|
|
//Only supported in 720p scene buffers
|
|
bool allow = VideoResManager::GetSceneWidth() == 1280 && VideoResManager::GetSceneHeight() == 720;
|
|
return g_UseDelayedGbuffer2TileResolve && allow;
|
|
}
|
|
|
|
#if RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
void CRenderer::SetTessellationQuality(int quality)
|
|
{
|
|
ms_ScreenSpaceErrorInPixels = quality==0 ? 0.f : quality==1? 2.f : 1.f;
|
|
ms_MaxTessellation = 2<<quality;
|
|
}
|
|
|
|
bool CRenderer::IsTessellationEnabled()
|
|
{
|
|
return ms_ScreenSpaceErrorInPixels != 0;
|
|
}
|
|
|
|
void CRenderer::SetTessellationVars(const grcViewport &viewport, const float aspect)
|
|
{
|
|
//Vec4V TessellationGlobal1((float)ms_WheelTessellationFactor, (float)ms_TreeTessellationFactor, (float)ms_TreeTessellation_PNTriangle_K, 0.0f);
|
|
//DLC_SET_GLOBAL_VAR(m_TessellationVar, TessellationGlobal1);
|
|
ms_TessellationVars.Set(&viewport, ms_LinearNear, ms_LinearFar, ms_MaxTessellation, ms_ScreenSpaceErrorInPixels, aspect, ms_FrustumEpsilon, ms_BackFaceEpsilon, ms_CullEnable);
|
|
|
|
# if !__FINAL
|
|
SetDisplacementGlobals();
|
|
# endif // !__FINAL
|
|
|
|
#if !__FINAL || RSG_PC
|
|
// Setup POM Flags
|
|
if(ms_POMFlagsVar == grcegvNONE)
|
|
{
|
|
ms_POMFlagsVar = grcEffect::LookupGlobalVar("POMFlags", !RSG_PC);
|
|
}
|
|
|
|
if(ms_POMFlagsVar != grcegvNONE)
|
|
{
|
|
const bool pomDisabled = CSettingsManager::GetInstance().GetSettings().m_graphics.m_ShaderQuality >= CSettings::High ? false : true;
|
|
|
|
#if !__FINAL
|
|
// if rag, force using its settings
|
|
DLC_SET_GLOBAL_VAR(ms_POMFlagsVar, Vec4V(ms_DisablePOM ? 1.0f : pomDisabled ? 1.0f : 0.0f,
|
|
ms_VisPOMVertexHeight ? 1.0f : 0.0f,
|
|
m_POMDistanceFade ? 1.0f : 0.0f,
|
|
ms_VisPOMDistanceFade ? 1.0f : 0.0f));
|
|
#else
|
|
DLC_SET_GLOBAL_VAR(ms_POMFlagsVar, Vec4V(pomDisabled ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f));
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
# if !__FINAL
|
|
void CRenderer::SetDisplacementGlobals()
|
|
{
|
|
//POM vars
|
|
if(ms_POMValuesVar == grcegvNONE)
|
|
{
|
|
ms_POMValuesVar = grcEffect::LookupGlobalVar("POMValues", !RSG_PC);
|
|
}
|
|
|
|
if(ms_POMValuesVar != grcegvNONE)
|
|
{
|
|
DLC_SET_GLOBAL_VAR(ms_POMValuesVar, Vec4V(ms_POMNear, ms_POMFar, ms_POMMinSamp, ms_POMMaxSamp>=ms_POMMinSamp ? ms_POMMaxSamp : ms_POMMinSamp));
|
|
}
|
|
|
|
if(ms_POMValues2Var == grcegvNONE)
|
|
{
|
|
ms_POMValues2Var = grcEffect::LookupGlobalVar("POMValues2", !RSG_PC);
|
|
}
|
|
|
|
if(ms_POMValues2Var != grcegvNONE)
|
|
{
|
|
DLC_SET_GLOBAL_VAR(ms_POMValues2Var, Vec4V(ms_POMForwardOffset, 0.0f, 0.0f, 0.0f));
|
|
}
|
|
|
|
//general displacement vars
|
|
if(ms_GlobalHeightScaleVar == grcegvNONE)
|
|
{
|
|
ms_GlobalHeightScaleVar = grcEffect::LookupGlobalVar("globalHeightScale", !RSG_PC);
|
|
}
|
|
|
|
if(ms_GlobalHeightScaleVar != grcegvNONE)
|
|
{
|
|
DLC_SET_GLOBAL_VAR(ms_GlobalHeightScaleVar, ms_GlobalHeightScale);
|
|
}
|
|
}
|
|
# endif // !__FINAL
|
|
#endif //RAGE_SUPPORT_TESSELLATION_TECHNIQUES
|
|
|
|
# if !__FINAL
|
|
void CRenderer::SetTerrainTintGlobals()
|
|
{
|
|
if(ms_TerrainTintBlendValuesVar == grcegvNONE)
|
|
{
|
|
ms_TerrainTintBlendValuesVar = grcEffect::LookupGlobalVar("TerrainTintBlendValues");
|
|
}
|
|
|
|
if(ms_TerrainTintBlendValuesVar != grcegvNONE)
|
|
{
|
|
DLC_SET_GLOBAL_VAR(ms_TerrainTintBlendValuesVar, Vec4V(ms_TerrainTintBlendNear, ms_TerrainTintBlendFar, 0.0f, 0.0f));
|
|
}
|
|
}
|
|
# endif // !__FINAL
|
|
|
|
#if __BANK
|
|
void CRenderer::PlantsToggleCB()
|
|
{
|
|
// Proc grass:
|
|
gbPlantMgrActive = ms_bPlantsAllEnabled;
|
|
|
|
// IP grass:
|
|
CEntityBatchDrawHandler::SetGrassBatchEnabled(ms_bPlantsAllEnabled);
|
|
}
|
|
|
|
namespace EBStatic
|
|
{
|
|
extern BankBool sPerfDisplayUsageInfo;
|
|
}
|
|
|
|
void CRenderer::PlantsDisplayDebugInfoCB()
|
|
{
|
|
// Proc grass:
|
|
extern bool gbDisplayCPlantMgrInfo;
|
|
gbDisplayCPlantMgrInfo = ms_bPlantsDisplayDebugInfo;
|
|
|
|
// IP grass:
|
|
grcDebugDraw::SetDisplayDebugText(true);
|
|
EBStatic::sPerfDisplayUsageInfo = ms_bPlantsDisplayDebugInfo;
|
|
}
|
|
|
|
void CRenderer::PlantsAlphaOverDrawCB()
|
|
{
|
|
// Proc grass:
|
|
extern bool gbShowAlphaOverdraw;
|
|
gbShowAlphaOverdraw = ms_bPlantsAlphaOverdraw;
|
|
|
|
// IP grass:
|
|
CCustomShaderEffectGrass::SetDbgAlphaOverdraw(ms_bPlantsAlphaOverdraw);
|
|
}
|
|
#endif //__BANK...
|
|
|
|
|