// 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 #include #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;i0) { --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( CRenderTargets::GetOffscreenDepthBuffer() ); if ( !pOffscreenDepth->ForceZCullSharing(static_cast(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()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()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(nearZ, nearClip, farClip); const float linearMax = Clamp(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<GetEntityListIndex()); CRenderer::SetMirrorListBits(1<GetEntityListIndex()); CRenderer::SetShadowPhases(0); #if __BANK CRenderer::SetDebugPhases(0); #endif // __BANK int phaseCount = RENDERPHASEMGR.GetRenderPhaseCount(); for(int x=0; xGetOwnerData(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<= 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...