Merge from main
This commit is contained in:
@@ -1,402 +0,0 @@
|
||||
<!--
|
||||
= Platform names =
|
||||
(case insensitive)
|
||||
"ANDROID"
|
||||
"PROVO"
|
||||
"PC"
|
||||
"LINUX"
|
||||
"MAC"
|
||||
|
||||
= Basic Layout =
|
||||
<ThreadConfig>
|
||||
<Platform name="XXX">
|
||||
<ThreadDefault Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="A" Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="B" Affinity="XX" >
|
||||
...
|
||||
</Platform>
|
||||
|
||||
<Platform name="YYY">
|
||||
...
|
||||
</Platform>
|
||||
</ThreadConfig>
|
||||
|
||||
= Parser Order for Platform =
|
||||
1. PlatformName_Common (valid for all potential platform configurations. Can be overridden by concert platform configuration)
|
||||
2. PlatformName or PlatformName_X (for platforms with unknown CPU count where X is the number of potential cores. The equal or next lower matching configuration for the identified core count at runtime will be taken)
|
||||
|
||||
Note: Overriding of thread configuration by later parsed configuration allowed.
|
||||
|
||||
= <ThreadDefault> and <Thread> XML attributes =
|
||||
|
||||
!!!
|
||||
Note: Use "ignore" as value if you do not want the thread system to set the value specifically!
|
||||
If a value is not defines the <ThreadDefault> value of the parameter will be used.
|
||||
This is useful when dealing with 3rdParty threads where you are not in control of the parameter setup.
|
||||
!!!
|
||||
|
||||
Name:
|
||||
"x" (string) : Name of thread
|
||||
"x*y" (string) : Name of thread with wildcard character
|
||||
|
||||
Affinity:
|
||||
"-1" : Put SW thread affinity in the hands of the scheduler - (default) -
|
||||
"x" : Run thread on specified core
|
||||
"x, y, ..." : Run thread on specified cores
|
||||
|
||||
Priority:
|
||||
"idle" : Hint to CryEngine to run thread with pre-set priority
|
||||
"below_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"normal" : Hint to CryEngine to run thread with pre-set priority - (default) -
|
||||
"above_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"highest" : Hint to CryEngine to run thread with pre-set priority
|
||||
"time_critical" : Hint to CryEngine to run thread with pre-set priority
|
||||
|
||||
"x" (number) : User defined thread priority number
|
||||
|
||||
StackSizeKB:
|
||||
"0" : Let platform decide on the stack size - (default) -
|
||||
"x" : Create thread with "x" KB of stack size
|
||||
|
||||
DisablePriorityBoost:
|
||||
"true" : Disable priority boosting - (default) -
|
||||
"false" : Enable priority boosting
|
||||
-->
|
||||
|
||||
|
||||
<ThreadConfig>
|
||||
<!-- ============= -->
|
||||
<!-- === PROVO === -->
|
||||
<!-- ============= -->
|
||||
<Platform name="Provo">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="64"/>
|
||||
|
||||
<!-- [PROCESS] -->
|
||||
<Thread name ="Main" Affinity="0" Priority="Above_Normal"/>
|
||||
|
||||
<!-- [RenderDLL] -->
|
||||
<Thread name ="RenderThread" Affinity="2" Priority="Highest" StackSizeKB="128"/>
|
||||
<Thread name ="RenderLoadingThread" Affinity="1" Priority="Above_Normal" StackSizeKB="72"/>
|
||||
<Thread name ="ShaderCompile"/>
|
||||
|
||||
<!-- [SYSTEM] -->
|
||||
<Thread name ="GFxMeshCacheReset"/>
|
||||
<Thread name ="MTrace NetPump" Priority="25"/>
|
||||
<Thread name ="NotificationNetwork"/>
|
||||
<Thread name ="ReplayRecord"/>
|
||||
<Thread name ="ResourceActivator"/>
|
||||
<Thread name ="StatoscopeDataWriter"/>
|
||||
<Thread name ="RemoteCommandClient"/>
|
||||
<Thread name ="RemoteCommandServer"/>
|
||||
<Thread name ="ServiceNetwork"/>
|
||||
<Thread name ="SysCrashTestOnThread"/>
|
||||
|
||||
<!-- [SYSTEM] - JobSystem -->
|
||||
<Thread name ="JobSystem_Worker_0(Blocking)" Affinity="1"/>
|
||||
|
||||
<Thread name ="JobSystem_Worker_0(Regular)" Affinity="1" StackSizeKB="256"/>
|
||||
<Thread name ="JobSystem_Worker_1(Regular)" Affinity="3" StackSizeKB="256"/>
|
||||
<Thread name ="JobSystem_Worker_2(Regular)" Affinity="4" StackSizeKB="256"/>
|
||||
<Thread name ="JobSystem_Worker_3(Regular)" Affinity="5" StackSizeKB="256"/>
|
||||
|
||||
<!-- [SYSTEM] - Physics -->
|
||||
<Thread name ="Physics" StackSizeKB="128"/>
|
||||
<Thread name ="PhysicsWorkerThread_*" StackSizeKB="128"/>
|
||||
|
||||
<!-- [SYSTEM] - Streaming -->
|
||||
<Thread name ="Streaming File IO HDD" Priority="Above_Normal" Affinity="1"/>
|
||||
<Thread name ="Streaming File IO Optical" Priority="Above_Normal" Affinity="1"/>
|
||||
<Thread name ="Streaming File IO InMemory" Priority="Above_Normal" Affinity="1"/>
|
||||
|
||||
<Thread name ="Streaming AsyncCallback" Affinity="5"/>
|
||||
<Thread name ="Streaming AsyncCallback Pak 0" Affinity="5"/>
|
||||
|
||||
<!-- [SYSTEM] - Console -->
|
||||
<Thread name ="RemoteConsoleServer"/>
|
||||
<Thread name ="RemoteConsoleClient"/>
|
||||
|
||||
<!-- [NETWORK] -->
|
||||
<Thread name ="Network"/>
|
||||
<Thread name ="ServerProbe"/>
|
||||
<Thread name ="NetworkDebugKit"/>
|
||||
<Thread name ="NetFileDownload"/>
|
||||
<Thread name ="NetworkWatchdog"/>
|
||||
<Thread name ="NetAddressSolver"/>
|
||||
|
||||
<!-- [AI] -->
|
||||
<Thread name ="NavigationSystemBackgroundUpdate"/>
|
||||
|
||||
<!-- [AUDIO] -->
|
||||
<Thread name ="MainAudioThread" Affinity="1,3,4,5" Priority="below_normal" StackSize="ignore"/>
|
||||
|
||||
<Thread name ="Wwise_Device" Affinity="5" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_BankManager" Affinity="5" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_LEngine" Affinity="5" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_Monitor" Affinity="5" Priority="ignore" StackSize="ignore"/>
|
||||
|
||||
<!-- [ACTION] -->
|
||||
<Thread name ="NetworkStallTicker"/>
|
||||
<Thread name ="ZLibCompressor" Priority="Normal"/>
|
||||
|
||||
<!-- [INPUT] -->
|
||||
<Thread name ="InputWorker"/>
|
||||
<Thread name ="Synergy"/>
|
||||
|
||||
<!-- [LIVE_CREATE]-->
|
||||
<Thread name ="LiveCreate_Server"/>
|
||||
<Thread name ="LiveCreate_FileSync"/>
|
||||
<Thread name ="LiveCreatePlatformService"/>
|
||||
<Thread name ="LiveCreateUtilityService"/>
|
||||
|
||||
<!-- [SCALEFORM][3rd Party] -->
|
||||
<Thread name ="GFxVideo_SoundUpdate" Affinity="5" Priority="time_critical" DisablePriorityBoost="ignore" StackSizeKB="ignore"/>
|
||||
<Thread name ="GFxVideo_Decoder" Affinity="4" Priority="highest" DisablePriorityBoost="ignore" StackSizeKB="ignore"/>
|
||||
<Thread name ="GFxVideo_Reader" Affinity="5" Priority="highest" DisablePriorityBoost="ignore" StackSizeKB="ignore"/>
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === PC_Common === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="PC_Common">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="32"/>
|
||||
|
||||
<!-- [PROCESS] -->
|
||||
<Thread name ="Main" Affinity="-1" Priority="Normal"/>
|
||||
|
||||
<!-- [SYSTEM] - JobSystem -->
|
||||
<Thread name ="JobSystem_Worker_*(Blocking)" StackSizeKB="32"/>
|
||||
<Thread name ="JobSystem_Worker_*(Regular)" StackSizeKB="256"/>
|
||||
|
||||
<!-- [SYSTEM] - Physics -->
|
||||
<Thread name ="Physics" StackSizeKB="128"/>
|
||||
<Thread name ="PhysicsWorkerThread_*" StackSizeKB="128"/>
|
||||
|
||||
<!-- [RenderDLL] -->
|
||||
<Thread name ="RenderThread" StackSizeKB="128"/>
|
||||
<Thread name ="RenderLoadingThread" Priority="Above_Normal" StackSizeKB="72"/>
|
||||
<Thread name ="ShaderCompile"/>
|
||||
|
||||
<!-- [SYSTEM] -->
|
||||
<Thread name ="GFxMeshCacheReset"/>
|
||||
<Thread name ="MTrace NetPump" Priority="25" StackSizeKB="64"/>
|
||||
<Thread name ="NotificationNetwork"/>
|
||||
<Thread name ="ReplayRecord"/>
|
||||
<Thread name ="ResourceActivator"/>
|
||||
<Thread name ="StatoscopeDataWriter"/>
|
||||
<Thread name ="RemoteCommandClient"/>
|
||||
<Thread name ="RemoteCommandServer"/>
|
||||
<Thread name ="ServiceNetwork"/>
|
||||
<Thread name ="SysCrashTestOnThread"/>
|
||||
|
||||
<!-- [SYSTEM] - Streaming -->
|
||||
<Thread name ="Streaming File IO HDD" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO Optical" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO InMemory" Priority="Above_Normal"/>
|
||||
|
||||
<Thread name ="Streaming AsyncCallback"/>
|
||||
<Thread name ="Streaming AsyncCallback Pak 0"/>
|
||||
|
||||
<!-- [SYSTEM] - Console -->
|
||||
<Thread name ="RemoteConsoleServer"/>
|
||||
<Thread name ="RemoteConsoleClient"/>
|
||||
<Thread name ="WindowsConsoleInput"/>
|
||||
<Thread name ="UNIXConsoleInput"/>
|
||||
|
||||
<!-- [NETWORK] -->
|
||||
<Thread name ="Network"/>
|
||||
<Thread name ="ServerProbe"/>
|
||||
<Thread name ="NetworkDebugKit"/>
|
||||
<Thread name ="NetFileDownload"/>
|
||||
<Thread name ="NetworkWatchdog" StackSizeKB="8"/>
|
||||
<Thread name ="NetAddressSolver" StackSizeKB="16"/>
|
||||
|
||||
<!-- [AUDIO] -->
|
||||
<Thread name ="MainAudioThread" Affinity="ignore" Priority="below_normal" StackSize="ignore"/>
|
||||
|
||||
<Thread name ="Wwise_Device" Affinity="ignore" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_BankManager" Affinity="ignore" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_LEngine" Affinity="ignore" Priority="ignore" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_Monitor" Affinity="ignore" Priority="ignore" StackSize="ignore"/>
|
||||
|
||||
<!-- [AI] -->
|
||||
<Thread name ="NavigationSystemBackgroundUpdate"/>
|
||||
|
||||
<!-- [ACTION] -->
|
||||
<Thread name ="NetworkStallTicker"/>
|
||||
<Thread name ="ZLibCompressor" Priority="Normal" StackSizeKB="32"/>
|
||||
|
||||
<!-- [INPUT] -->
|
||||
<Thread name ="InputWorker"/>
|
||||
<Thread name ="Synergy"/>
|
||||
|
||||
<!-- [LIVE_CREATE]-->
|
||||
<Thread name ="LiveCreate_Server"/>
|
||||
<Thread name ="LiveCreate_FileSync"/>
|
||||
<Thread name ="LiveCreatePlatformService"/>
|
||||
<Thread name ="LiveCreateUtilityService"/>
|
||||
|
||||
<!-- [SCALEFORM][3rd Party] -->
|
||||
<Thread name ="GFxVideo_SoundUpdate" Affinity="ignore" Priority="highest" DisablePriorityBoost="ignore" StackSizeKB="16"/>
|
||||
|
||||
<!-- Special case, to add additional decoder threads add a threads with an increase incremental number. "GFxVideo_Decoder_0" sets thread priority for all other decoder threads-->
|
||||
<Thread name ="GFxVideo_Decoder_0" Affinity="ignore" Priority="normal" DisablePriorityBoost="ignore" StackSizeKB="ignore"/>
|
||||
<Thread name ="GFxVideo_Decoder_1" Affinity="ignore" Priority="normal" DisablePriorityBoost="ignore" StackSizeKB="ignore"/>
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === PC_8 === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="PC_8">
|
||||
<!-- Empty Example - Extend for 8 core specific machines. May override Common settings -->
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === MAC_Common === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="MAC_Common">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="32"/>
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === LINUX_Common === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="LINUX_Common">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="64"/>
|
||||
|
||||
<!-- [PROCESS] -->
|
||||
<Thread name ="Main" Affinity="-1" Priority="Above_Normal"/>
|
||||
|
||||
<!-- [SYSTEM] - JobSystem -->
|
||||
<Thread name ="JobSystem_Worker_*(Blocking)" StackSizeKB="32"/>
|
||||
<Thread name ="JobSystem_Worker_*(Regular)" StackSizeKB="256"/>
|
||||
|
||||
<!-- [SYSTEM] - Physics -->
|
||||
<Thread name ="Physics" StackSizeKB="128"/>
|
||||
<Thread name ="PhysicsWorkerThread_*" StackSizeKB="128"/>
|
||||
|
||||
<!-- [RenderDLL] -->
|
||||
<Thread name ="RenderThread" Priority="Above_Normal" StackSizeKB="128"/>
|
||||
<Thread name ="RenderLoadingThread" Priority="Above_Normal" StackSizeKB="72"/>
|
||||
<Thread name ="ShaderCompile"/>
|
||||
|
||||
<!-- [SYSTEM] -->
|
||||
<Thread name ="GFxMeshCacheReset"/>
|
||||
<Thread name ="MTrace NetPump" Priority="25" StackSizeKB="64"/>
|
||||
<Thread name ="NotificationNetwork"/>
|
||||
<Thread name ="ReplayRecord"/>
|
||||
<Thread name ="ResourceActivator"/>
|
||||
<Thread name ="StatoscopeDataWriter"/>
|
||||
<Thread name ="RemoteCommandClient"/>
|
||||
<Thread name ="RemoteCommandServer"/>
|
||||
<Thread name ="ServiceNetwork"/>
|
||||
<Thread name ="SysCrashTestOnThread"/>
|
||||
|
||||
<!-- [SYSTEM] - Streaming -->
|
||||
<Thread name ="Streaming File IO HDD" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO Optical" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO InMemory" Priority="Above_Normal"/>
|
||||
|
||||
<Thread name ="Streaming AsyncCallback"/>
|
||||
<Thread name ="Streaming AsyncCallback Pak 0"/>
|
||||
|
||||
<!-- [SYSTEM] - Console -->
|
||||
<Thread name ="RemoteConsoleServer"/>
|
||||
<Thread name ="RemoteConsoleClient"/>
|
||||
<Thread name ="UNIXConsoleInput"/>
|
||||
|
||||
<!-- [NETWORK] -->
|
||||
<Thread name ="Network"/>
|
||||
<Thread name ="ServerProbe"/>
|
||||
<Thread name ="NetworkDebugKit"/>
|
||||
<Thread name ="NetFileDownload"/>
|
||||
<Thread name ="NetworkWatchdog" StackSizeKB="8"/>
|
||||
<Thread name ="NetAddressSolver"/>
|
||||
|
||||
<!-- [AUDIO] -->
|
||||
<Thread name ="MainAudioThread" Affinity="ignore" Priority="below_normal" StackSize="ignore"/>
|
||||
|
||||
<Thread name ="Wwise_Device" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_BankManager" Affinity="ignore" Priority="50" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_LEngine" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_Monitor" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
|
||||
<!-- [AI] -->
|
||||
<Thread name ="NavigationSystemBackgroundUpdate"/>
|
||||
|
||||
<!-- [ACTION] -->
|
||||
<Thread name ="NetworkStallTicker"/>
|
||||
<Thread name ="ZLibCompressor" Priority="Normal" StackSizeKB="32"/>
|
||||
|
||||
<!-- [INPUT] -->
|
||||
<Thread name ="InputWorker"/>
|
||||
<Thread name ="Synergy"/>
|
||||
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === ANDROID_Common === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="ANDROID_Common">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="32"/>
|
||||
|
||||
<!-- [PROCESS] -->
|
||||
<Thread name ="Main" Priority="Above_Normal"/>
|
||||
|
||||
<!-- [SYSTEM] - JobSystem -->
|
||||
<Thread name ="JobSystem_Worker_*(Blocking)" StackSizeKB="32"/>
|
||||
<Thread name ="JobSystem_Worker_*(Regular)" StackSizeKB="256"/>
|
||||
|
||||
<!-- [SYSTEM] - Physics -->
|
||||
<Thread name ="Physics" StackSizeKB="128"/>
|
||||
<Thread name ="PhysicsWorkerThread_*" StackSizeKB="128"/>
|
||||
|
||||
<!-- [RenderDLL] -->
|
||||
<Thread name ="RenderThread" Affinity="ignore" Priority="Above_Normal" StackSizeKB="128"/>
|
||||
<Thread name ="RenderLoadingThread" Affinity="ignore" Priority="Above_Normal" StackSizeKB="72"/>
|
||||
<Thread name ="ShaderCompile"/>
|
||||
|
||||
<!-- [SYSTEM] -->
|
||||
<Thread name ="GFxMeshCacheReset"/>
|
||||
<Thread name ="MTrace NetPump" Priority="25" StackSizeKB="64"/>
|
||||
<Thread name ="NotificationNetwork"/>
|
||||
<Thread name ="ReplayRecord"/>
|
||||
<Thread name ="ResourceActivator"/>
|
||||
<Thread name ="StatoscopeDataWriter"/>
|
||||
<Thread name ="RemoteCommandClient"/>
|
||||
<Thread name ="RemoteCommandServer"/>
|
||||
<Thread name ="ServiceNetwork"/>
|
||||
<Thread name ="SysCrashTestOnThread"/>
|
||||
|
||||
<!-- [AUDIO] -->
|
||||
<Thread name ="MainAudioThread" Affinity="ignore" Priority="below_normal" StackSize="ignore"/>
|
||||
|
||||
<Thread name ="Wwise_Device" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_BankManager" Affinity="ignore" Priority="50" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_LEngine" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
<Thread name ="Wwise_Monitor" Affinity="ignore" Priority="99" StackSize="ignore"/>
|
||||
|
||||
<!-- [SYSTEM] - Streaming -->
|
||||
<Thread name ="Streaming File IO HDD" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO Optical" Priority="Above_Normal"/>
|
||||
<Thread name ="Streaming File IO InMemory" Priority="Above_Normal"/>
|
||||
|
||||
<Thread name ="Streaming AsyncCallback"/>
|
||||
<Thread name ="Streaming AsyncCallback Pak 0"/>
|
||||
|
||||
<!-- [SYSTEM] - Console -->
|
||||
<Thread name ="RemoteConsoleServer"/>
|
||||
|
||||
<!-- [NETWORK] -->
|
||||
<Thread name ="Network"/>
|
||||
<Thread name ="ServerProbe"/>
|
||||
<Thread name ="NetworkDebugKit"/>
|
||||
<Thread name ="NetFileDownload"/>
|
||||
<Thread name ="NetworkWatchdog" StackSizeKB="8"/>
|
||||
<Thread name ="NetAddressSolver" StackSizeKB="16"/>
|
||||
|
||||
<!-- [ACTION] -->
|
||||
<Thread name ="NetworkStallTicker"/>
|
||||
<Thread name ="ZLibCompressor" Affinity="ignore" Priority="Above_Normal" StackSizeKB="32"/>
|
||||
</Platform>
|
||||
|
||||
</ThreadConfig>
|
||||
@@ -1,128 +0,0 @@
|
||||
<!--
|
||||
= Platform names =
|
||||
(case insensitive)
|
||||
"ANDROID"
|
||||
"PROVO"
|
||||
"PC"
|
||||
"MAC"
|
||||
|
||||
= Basic Layout =
|
||||
<ThreadConfig>
|
||||
<Platform name="XXX">
|
||||
<ThreadDefault Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="A" Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="B" Affinity="XX" >
|
||||
...
|
||||
</Platform>
|
||||
|
||||
<Platform name="YYY">
|
||||
...
|
||||
</Platform>
|
||||
</ThreadConfig>
|
||||
|
||||
= Parser Order for Platform =
|
||||
1. PlatformName_Common (valid for all potential platform configurations. Can be overridden by concert platform configuration)
|
||||
2. PlatformName or PlatformName_X (for platforms with unknown CPU count where X is the number of potential cores. The equal or next lower matching configuration for the identified core count at runtime will be taken)
|
||||
|
||||
Note: Overriding of thread configuration by later parsed configuration allowed.
|
||||
|
||||
= <ThreadDefault> and <Thread> XML attributes =
|
||||
|
||||
!!!
|
||||
Note: Use "ignore" as value if you do not want the thread system to set the value specifically!
|
||||
If a value is not defines the <ThreadDefault> value of the parameter will be used.
|
||||
This is useful when dealing with 3rdParty threads where you are not in control of the parameter setup.
|
||||
!!!
|
||||
|
||||
Name:
|
||||
"x" (string) : Name of thread
|
||||
"x*y" (string) : Name of thread with wildcard character
|
||||
|
||||
Affinity:
|
||||
"-1" : Put SW thread affinity in the hands of the scheduler - (default) -
|
||||
"x" : Run thread on specified core
|
||||
"x, y, ..." : Run thread on specified cores
|
||||
|
||||
Priority:
|
||||
"idle" : Hint to CryEngine to run thread with pre-set priority
|
||||
"below_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"normal" : Hint to CryEngine to run thread with pre-set priority - (default) -
|
||||
"above_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"highest" : Hint to CryEngine to run thread with pre-set priority
|
||||
"time_critical" : Hint to CryEngine to run thread with pre-set priority
|
||||
|
||||
"x" (number) : User defined thread priority number
|
||||
|
||||
StackSizeKB:
|
||||
"0" : Let platform decide on the stack size - (default) -
|
||||
"x" : Create thread with "x" KB of stack size
|
||||
|
||||
DisablePriorityBoost:
|
||||
"true" : Disable priority boosting - (default) -
|
||||
"false" : Enable priority boosting
|
||||
-->
|
||||
|
||||
|
||||
<ThreadConfig>
|
||||
<!-- ============ -->
|
||||
<!-- === PC_Common === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="PC_Common">
|
||||
<ThreadDefault Affinity="-1" Priority="Normal" StackSizeKB="32"/>
|
||||
|
||||
<!-- [SANDBOX] -->
|
||||
<Thread name ="TextureViewer"/>
|
||||
<Thread name ="TextureDatabaseCreator"/>
|
||||
|
||||
<Thread name ="MaterialFilesScanning"/>
|
||||
<Thread name ="FileChangeMonitor"/>
|
||||
|
||||
<Thread name ="FileSystemSearcher"/>
|
||||
<Thread name ="BackgroundTask_IO"/>
|
||||
<Thread name ="BackgroundTask_*"/>
|
||||
|
||||
<!-- [SANDBOX] - Dialogues -->
|
||||
<Thread name ="ResourceCompilerDialog"/>
|
||||
|
||||
<!-- [SANDBOX] - Telemetry -->
|
||||
<Thread name ="TelemetryPipeThread"/>
|
||||
|
||||
<!-- [SANDBOX] - Asset Browser -->
|
||||
<Thread name ="AssetMetaDataFileDB_CachingInfo"/>
|
||||
<Thread name ="AssetMetaDataFileDB_LoadAndUpdate"/>
|
||||
|
||||
<!-- [SANDBOX] - Console -->
|
||||
<Thread name ="ConsoleHotUpdate"/>
|
||||
<Thread name ="Console Synchronization"/>
|
||||
|
||||
<!-- [SANDBOX] - LiveCreate -->
|
||||
<Thread name ="LiveCreate_PeerComm"/>
|
||||
<Thread name ="LiveCreate_SyncFiles"/>
|
||||
<Thread name ="LiveCreate_CheckPowerOn"/>
|
||||
|
||||
<!-- [SANDBOX] - Plug-ins -->
|
||||
<Thread name ="PerforcePlugin"/>
|
||||
|
||||
<!-- [SANDBOX] - Utility -->
|
||||
<Thread name ="FileIndexing"/>
|
||||
<Thread name ="LODChainGenerateThread"/>
|
||||
<Thread name ="VisualChangeCalculatorView"/>
|
||||
|
||||
<!-- [SANDBOX] - Segmented World -->
|
||||
<Thread name ="SegWorld_MapUpdater"/>
|
||||
<Thread name ="SegWorld_WorldUpdater"/>
|
||||
<Thread name ="SegWorld_ExportSurfaceTexture_*"/>
|
||||
|
||||
<!-- [SANDBOX] - Indirect Lighting -->
|
||||
<Thread name ="SHLighting_*" StackSizeKB="1024"/>
|
||||
<Thread name ="SHLighting_TriRaster" StackSizeKB="1024"/>
|
||||
|
||||
</Platform>
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- === PC_8 === -->
|
||||
<!-- ============ -->
|
||||
<Platform name="PC_8">
|
||||
<!-- Empty Example - Extend for 8 core specific machines. May override Common settings -->
|
||||
</Platform>
|
||||
</ThreadConfig>
|
||||
@@ -0,0 +1,117 @@
|
||||
"""
|
||||
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
its licensors.
|
||||
|
||||
For complete copyright and license terms please see the LICENSE at the root of this
|
||||
distribution (the "License"). All use of this software is governed by the License,
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
|
||||
# fmt: off
|
||||
class Tests():
|
||||
node_duplicated = ("Successfully duplicated node", "Failed to duplicate the node")
|
||||
# fmt: on
|
||||
|
||||
|
||||
def Node_HappyPath_DuplicateNode():
|
||||
"""
|
||||
Summary:
|
||||
Duplicating node in graph
|
||||
|
||||
Expected Behavior:
|
||||
Upon selecting a node and pressing Ctrl+D, the node will be duplicated
|
||||
|
||||
Test Steps:
|
||||
1) Open Script Canvas window (Tools > Script Canvas)
|
||||
2) Open a new graph
|
||||
3) Add node to graph
|
||||
4) Duplicate node
|
||||
5) Verify the node was duplicated6) Verify the node was duplicated
|
||||
|
||||
Note:
|
||||
- This test file must be called from the Open 3D Engine Editor command terminal
|
||||
- Any passed and failed tests are written to the Editor.log file.
|
||||
Parsing the file or running a log_monitor are required to observe the test results.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
from PySide2 import QtWidgets, QtTest
|
||||
from PySide2.QtCore import Qt
|
||||
|
||||
from editor_python_test_tools.utils import Report
|
||||
from editor_python_test_tools.utils import TestHelper as helper
|
||||
import editor_python_test_tools.pyside_utils as pyside_utils
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
WAIT_FRAMES = 200
|
||||
|
||||
NODE_NAME = "Print"
|
||||
NODE_CATEGORY = "Debug"
|
||||
EXPECTED_STRING = f"{NODE_NAME} - {NODE_CATEGORY} (2 Selected)"
|
||||
|
||||
def command_line_input(command_str):
|
||||
cmd_action = pyside_utils.find_child_by_pattern(
|
||||
sc_main, {"objectName": "action_ViewCommandLine", "type": QtWidgets.QAction}
|
||||
)
|
||||
cmd_action.trigger()
|
||||
textbox = sc.findChild(QtWidgets.QLineEdit, "commandText")
|
||||
QtTest.QTest.keyClicks(textbox, command_str)
|
||||
QtTest.QTest.keyClick(textbox, Qt.Key_Enter, Qt.NoModifier)
|
||||
|
||||
def grab_title_text():
|
||||
scroll_area = node_inspector.findChild(QtWidgets.QScrollArea, "")
|
||||
QtTest.QTest.keyClick(graph, "a", Qt.ControlModifier, WAIT_FRAMES)
|
||||
background = scroll_area.findChild(QtWidgets.QFrame, "Background")
|
||||
title = background.findChild(QtWidgets.QLabel, "Title")
|
||||
text = title.findChild(QtWidgets.QLabel, "Title")
|
||||
return text.text()
|
||||
|
||||
# 1) Open Script Canvas window (Tools > Script Canvas)
|
||||
general.idle_enable(True)
|
||||
general.open_pane("Script Canvas")
|
||||
helper.wait_for_condition(lambda: general.is_pane_visible("Script Canvas"), 5.0)
|
||||
|
||||
# 2) Open a new graph
|
||||
editor_window = pyside_utils.get_editor_main_window()
|
||||
sc = editor_window.findChild(QtWidgets.QDockWidget, "Script Canvas")
|
||||
sc_main = sc.findChild(QtWidgets.QMainWindow)
|
||||
create_new_graph = pyside_utils.find_child_by_pattern(
|
||||
sc_main, {"objectName": "action_New_Script", "type": QtWidgets.QAction}
|
||||
)
|
||||
if sc.findChild(QtWidgets.QDockWidget, "NodeInspector") is None:
|
||||
action = pyside_utils.find_child_by_pattern(sc, {"text": "Node Inspector", "type": QtWidgets.QAction})
|
||||
action.trigger()
|
||||
node_inspector = sc.findChild(QtWidgets.QDockWidget, "NodeInspector")
|
||||
create_new_graph.trigger()
|
||||
|
||||
# 3) Add node
|
||||
command_line_input("add_node Print")
|
||||
|
||||
# 4) Duplicate node
|
||||
graph_view = sc.findChild(QtWidgets.QFrame, "graphicsViewFrame")
|
||||
graph = graph_view.findChild(QtWidgets.QWidget, "")
|
||||
# There are currently no utilities available to directly duplicate the node,
|
||||
# therefore the node is selected using CTRL+A on the graph to select
|
||||
# it and then CTRL+D to duplicate
|
||||
sc_main.activateWindow()
|
||||
QtTest.QTest.keyClick(graph, "a", Qt.ControlModifier, WAIT_FRAMES)
|
||||
QtTest.QTest.keyClick(graph, "d", Qt.ControlModifier, WAIT_FRAMES)
|
||||
|
||||
# 5) Verify the node was duplicated
|
||||
# As direct interaction with node is not available the text on the label
|
||||
# inside the Node Inspector is validated showing two nodes exist
|
||||
after_dup = grab_title_text()
|
||||
Report.result(Tests.node_duplicated, after_dup == EXPECTED_STRING)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import ImportPathHelper as imports
|
||||
|
||||
imports.init()
|
||||
from editor_python_test_tools.utils import Report
|
||||
|
||||
Report.start_test(Node_HappyPath_DuplicateNode)
|
||||
@@ -84,7 +84,7 @@ class TestAutomation(TestAutomationBase):
|
||||
file_system.delete([os.path.join(workspace.paths.project(), "Levels", level)], True, True)
|
||||
from . import OnEntityActivatedDeactivated_PrintMessage as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
|
||||
@pytest.mark.test_case_id("T92562993")
|
||||
def test_NodePalette_ClearSelection(self, request, workspace, editor, launcher_platform, project):
|
||||
from . import NodePalette_ClearSelection as test_module
|
||||
@@ -122,7 +122,7 @@ class TestAutomation(TestAutomationBase):
|
||||
def test_NodeInspector_RenameVariable(self, request, workspace, editor, launcher_platform, project):
|
||||
from . import NodeInspector_RenameVariable as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
|
||||
@pytest.mark.test_case_id("T92569137")
|
||||
def test_Debugging_TargetMultipleGraphs(self, request, workspace, editor, launcher_platform, project):
|
||||
from . import Debugging_TargetMultipleGraphs as test_module
|
||||
@@ -195,7 +195,7 @@ class TestAutomation(TestAutomationBase):
|
||||
def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform):
|
||||
from . import NodeCategory_ExpandOnClick as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
|
||||
def test_NodePalette_SearchText_Deletion(self, request, workspace, editor, launcher_platform):
|
||||
from . import NodePalette_SearchText_Deletion as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -204,6 +204,10 @@ class TestAutomation(TestAutomationBase):
|
||||
from . import VariableManager_UnpinVariableType_Works as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
def test_Node_HappyPath_DuplicateNode(self, request, workspace, editor, launcher_platform):
|
||||
from . import Node_HappyPath_DuplicateNode as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
# NOTE: We had to use hydra_test_utils.py, as TestAutomationBase run_test method
|
||||
# fails because of pyside_utils import
|
||||
@pytest.mark.SUITE_periodic
|
||||
|
||||
@@ -32,41 +32,6 @@ ly_add_target(
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME CryCommon.EngineSettings.Static STATIC
|
||||
NAMESPACE Legacy
|
||||
FILES_CMAKE
|
||||
crycommon_enginesettings_files.cmake
|
||||
${pal_dir}/crycommon_enginesettings_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
${pal_dir}
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME CryCommon.EngineSettings.RC.Static STATIC
|
||||
NAMESPACE Legacy
|
||||
FILES_CMAKE
|
||||
crycommon_enginesettings_files.cmake
|
||||
${pal_dir}/crycommon_enginesettings_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PUBLIC
|
||||
.
|
||||
${pal_dir}
|
||||
COMPILE_DEFINITIONS
|
||||
PRIVATE
|
||||
RESOURCE_COMPILER
|
||||
BUILD_DEPENDENCIES
|
||||
PUBLIC
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
|
||||
ly_add_target(
|
||||
|
||||
@@ -31,7 +31,7 @@ void CryAssertTrace(const char* szFormat, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
|
||||
if (!gEnv->bIgnoreAllAsserts)
|
||||
{
|
||||
if (szFormat == NULL)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ void CryAssertTrace(const char* szFormat, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
|
||||
if (!gEnv->bIgnoreAllAsserts)
|
||||
{
|
||||
if (szFormat == NULL)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ void CryAssertTrace(const char* szFormat, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
|
||||
if (!gEnv->bIgnoreAllAsserts)
|
||||
{
|
||||
if (szFormat == NULL)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ void CryAssertTrace(const char* szFormat, ...)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
|
||||
if (!gEnv->bIgnoreAllAsserts)
|
||||
{
|
||||
if (szFormat == NULL)
|
||||
{
|
||||
|
||||
@@ -305,7 +305,7 @@ void CryAssertTrace(const char* _pszFormat, ...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
|
||||
if (!gEnv->bIgnoreAllAsserts)
|
||||
{
|
||||
if (NULL == _pszFormat)
|
||||
{
|
||||
|
||||
@@ -49,12 +49,6 @@ public:
|
||||
//! ISystem has shut down.
|
||||
virtual void OnCrySystemPostShutdown() {}
|
||||
|
||||
//! Engine pre physics update.
|
||||
virtual void OnCrySystemPrePhysicsUpdate() {}
|
||||
|
||||
//! Engine post physics update.
|
||||
virtual void OnCrySystemPostPhysicsUpdate() {}
|
||||
|
||||
//! Sent when a new level is being created.
|
||||
virtual void OnCryEditorBeginCreate() {}
|
||||
|
||||
|
||||
@@ -37,9 +37,6 @@ enum CryLockType
|
||||
|
||||
#define CRYLOCK_HAVE_FASTLOCK 1
|
||||
|
||||
void CryThreadSetName(threadID nThreadId, const char* sThreadName);
|
||||
const char* CryThreadGetName(threadID nThreadId);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Primitive locks and conditions.
|
||||
|
||||
@@ -31,22 +31,3 @@
|
||||
#else
|
||||
// Put other platform specific includes here!
|
||||
#endif
|
||||
|
||||
#include <IThreadTask.h>
|
||||
|
||||
void CryThreadSetName(threadID dwThreadId, const char* sThreadName)
|
||||
{
|
||||
if (gEnv && gEnv->pSystem && gEnv->pSystem->GetIThreadTaskManager())
|
||||
{
|
||||
gEnv->pSystem->GetIThreadTaskManager()->SetThreadName(dwThreadId, sThreadName);
|
||||
}
|
||||
}
|
||||
|
||||
const char* CryThreadGetName(threadID dwThreadId)
|
||||
{
|
||||
if (gEnv && gEnv->pSystem && gEnv->pSystem->GetIThreadTaskManager())
|
||||
{
|
||||
return gEnv->pSystem->GetIThreadTaskManager()->GetThreadName(dwThreadId);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include <IThreadTask.h>
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
@@ -249,10 +249,6 @@ public:
|
||||
void SetName(const char* Name)
|
||||
{
|
||||
m_name = Name;
|
||||
if (m_threadId)
|
||||
{
|
||||
CryThreadSetName(m_threadId, m_name);
|
||||
}
|
||||
}
|
||||
const char* GetName() { return m_name; }
|
||||
|
||||
@@ -289,11 +285,6 @@ private:
|
||||
self->m_bIsStarted = true;
|
||||
self->m_bIsRunning = true;
|
||||
|
||||
if (!self->m_name.empty())
|
||||
{
|
||||
CryThreadSetName(-1, self->m_name);
|
||||
}
|
||||
|
||||
self->m_Runnable->Run();
|
||||
self->m_bIsRunning = false;
|
||||
self->m_bCreatedThread = false;
|
||||
@@ -311,11 +302,6 @@ private:
|
||||
self->m_bIsStarted = true;
|
||||
self->m_bIsRunning = true;
|
||||
|
||||
if (!self->m_name.empty())
|
||||
{
|
||||
CryThreadSetName(-1, self->m_name);
|
||||
}
|
||||
|
||||
self->Run();
|
||||
self->m_bIsRunning = false;
|
||||
self->m_bCreatedThread = false;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EngineSettingsBackend.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
CEngineSettingsBackend::CEngineSettingsBackend(CEngineSettingsManager* parent, const wchar_t* moduleName)
|
||||
: m_parent(parent)
|
||||
, m_moduleName()
|
||||
{
|
||||
if (moduleName != nullptr)
|
||||
{
|
||||
m_moduleName = moduleName;
|
||||
}
|
||||
}
|
||||
|
||||
CEngineSettingsBackend::~CEngineSettingsBackend()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKEND_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKEND_H
|
||||
#pragma once
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
#include "SettingsManagerHelpers.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class CEngineSettingsManager;
|
||||
|
||||
class CEngineSettingsBackend
|
||||
{
|
||||
public:
|
||||
CEngineSettingsBackend(CEngineSettingsManager* parent, const wchar_t* moduleName = NULL);
|
||||
virtual ~CEngineSettingsBackend();
|
||||
|
||||
virtual std::wstring GetModuleFilePath() const = 0;
|
||||
|
||||
virtual bool GetModuleSpecificStringEntryUtf16(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer) = 0;
|
||||
virtual bool GetModuleSpecificIntEntry(const char* key, int& value) = 0;
|
||||
virtual bool GetModuleSpecificBoolEntry(const char* key, bool& value) = 0;
|
||||
|
||||
virtual bool SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str) = 0;
|
||||
virtual bool SetModuleSpecificIntEntry(const char* key, const int& value) = 0;
|
||||
virtual bool SetModuleSpecificBoolEntry(const char* key, const bool& value) = 0;
|
||||
|
||||
virtual bool GetInstalledBuildRootPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path) = 0;
|
||||
|
||||
virtual void LoadEngineSettingsFromRegistry() = 0;
|
||||
virtual bool StoreEngineSettingsToRegistry() = 0;
|
||||
|
||||
protected:
|
||||
CEngineSettingsManager* parent() const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
const std::wstring& moduleName() const
|
||||
{
|
||||
return m_moduleName;
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring m_moduleName;
|
||||
CEngineSettingsManager* m_parent;
|
||||
};
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKEND_H
|
||||
@@ -1,486 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EngineSettingsBackendApple.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
#include "AzCore/PlatformDef.h"
|
||||
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
|
||||
#include "EngineSettingsManager.h"
|
||||
#include "SettingsManagerHelpers.h"
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/nlist.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <codecvt>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
using namespace SettingsManagerHelpers;
|
||||
|
||||
static const char gDefaultRegistryLocation[] = "/EngineSettings.reg";
|
||||
|
||||
#define REG_SOFTWARE L"Software\\"
|
||||
#define REG_COMPANY_NAME L"Amazon\\"
|
||||
#define REG_PRODUCT_NAME L"Lumberyard\\"
|
||||
#define REG_SETTING L"Settings\\"
|
||||
#define REG_BASE_SETTING_KEY REG_SOFTWARE REG_COMPANY_NAME REG_PRODUCT_NAME REG_SETTING
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class SimpleRegistry
|
||||
{
|
||||
typedef std::map< std::wstring, std::wstring > WStringMap;
|
||||
std::map< std::wstring, WStringMap * > m_modules;
|
||||
|
||||
public:
|
||||
SimpleRegistry();
|
||||
~SimpleRegistry();
|
||||
|
||||
void setBoolValue(const std::wstring& module, const std::wstring& key, bool value);
|
||||
void setIntValue(const std::wstring& module, const std::wstring& key, int value);
|
||||
void setStrValue(const std::wstring& module, const std::wstring& key, const std::wstring& value);
|
||||
|
||||
bool getBoolValue(const std::wstring& module, const std::wstring& key, bool& value);
|
||||
bool getIntValue(const std::wstring& module, const std::wstring& key, int& value);
|
||||
bool getStrValue(const std::wstring& module, const std::wstring& key, std::wstring& value);
|
||||
|
||||
bool loadFromFile(const char* fileName);
|
||||
bool saveToFile(const char* fileName);
|
||||
|
||||
protected:
|
||||
void clear();
|
||||
|
||||
private:
|
||||
static const wchar_t gSimpleMagic[];
|
||||
static const size_t gMetaCharCount;
|
||||
};
|
||||
|
||||
const wchar_t SimpleRegistry::gSimpleMagic[] = L"FR0";
|
||||
const size_t SimpleRegistry::gMetaCharCount = sizeof(size_t) / sizeof(wchar_t);
|
||||
|
||||
SimpleRegistry::SimpleRegistry()
|
||||
{
|
||||
}
|
||||
|
||||
SimpleRegistry::~SimpleRegistry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void SimpleRegistry::setBoolValue(const std::wstring& module, const std::wstring& key, bool value)
|
||||
{
|
||||
return setStrValue(module, key, value ? L"true" : L"false");
|
||||
}
|
||||
|
||||
void SimpleRegistry::setIntValue(const std::wstring& module, const std::wstring& key, int value)
|
||||
{
|
||||
return setStrValue(module, key, std::to_wstring(value));
|
||||
}
|
||||
|
||||
void SimpleRegistry::setStrValue(const std::wstring& module, const std::wstring& key, const std::wstring& value)
|
||||
{
|
||||
WStringMap *map = nullptr;
|
||||
|
||||
auto i = m_modules.find(module);
|
||||
|
||||
if (i == m_modules.end())
|
||||
{
|
||||
map = new WStringMap;
|
||||
m_modules.emplace(module, map);
|
||||
}
|
||||
else
|
||||
{
|
||||
map = i->second;
|
||||
}
|
||||
|
||||
assert(map);
|
||||
|
||||
(*map)[key] = value;
|
||||
}
|
||||
|
||||
bool SimpleRegistry::getBoolValue(const std::wstring& module, const std::wstring& key, bool& value)
|
||||
{
|
||||
std::wstring str;
|
||||
|
||||
if (!getStrValue(module, key, str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = (0 == str.compare(L"true"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleRegistry::getIntValue(const std::wstring& module, const std::wstring& key, int& value)
|
||||
{
|
||||
std::wstring str;
|
||||
|
||||
if (!getStrValue(module, key, str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = std::stoi(str);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleRegistry::getStrValue(const std::wstring& module, const std::wstring& key, std::wstring& value)
|
||||
{
|
||||
WStringMap *map = nullptr;
|
||||
|
||||
auto mi = m_modules.find(module);
|
||||
if (mi == m_modules.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
map = mi->second;
|
||||
assert(map);
|
||||
|
||||
auto ki = map->find(key);
|
||||
if (ki == map->end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = ki->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleRegistry::loadFromFile(const char* fileName)
|
||||
{
|
||||
clear();
|
||||
|
||||
std::wifstream file(fileName, std::ios_base::in|std::ios_base::binary);
|
||||
file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t>));
|
||||
if (!file.is_open())
|
||||
{
|
||||
AZ_Warning("EngineSettings", false, "Failed to open registry settings file: %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring module;
|
||||
std::wstring key;
|
||||
std::wstring value;
|
||||
|
||||
wchar_t buffer[512];
|
||||
size_t size;
|
||||
wchar_t meta[gMetaCharCount];
|
||||
|
||||
/* magic number */
|
||||
if(!file.read(buffer, sizeof(gSimpleMagic) / sizeof(wchar_t)) ||
|
||||
wcsncmp(gSimpleMagic, buffer, sizeof(gSimpleMagic) / sizeof(wchar_t)) != 0)
|
||||
{
|
||||
file.close();
|
||||
AZ_Warning("EngineSettings", false, "Failed to load registry settings from file: %s", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (file.good())
|
||||
{
|
||||
file.read(meta, gMetaCharCount);
|
||||
if (!file.good())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&size, meta, sizeof(size));
|
||||
file.read(buffer, size);
|
||||
buffer[file.gcount()] = L'\0';
|
||||
module = buffer;
|
||||
|
||||
file.read(meta, gMetaCharCount);
|
||||
memcpy(&size, meta, sizeof(size));
|
||||
file.read(buffer, size);
|
||||
buffer[file.gcount()] = L'\0';
|
||||
key = buffer;
|
||||
|
||||
file.read(meta, gMetaCharCount);
|
||||
memcpy(&size, meta, sizeof(size));
|
||||
file.read(buffer, size);
|
||||
buffer[file.gcount()] = L'\0';
|
||||
value = buffer;
|
||||
|
||||
setStrValue(module, key, value);
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleRegistry::saveToFile(const char* fileName)
|
||||
{
|
||||
std::wofstream file(fileName, std::ios_base::out|std::ios_base::trunc|std::ios_base::binary);
|
||||
file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t>));
|
||||
if (!file.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring module;
|
||||
|
||||
size_t size;
|
||||
wchar_t meta[gMetaCharCount];
|
||||
|
||||
/* magic number */
|
||||
file.write(gSimpleMagic, sizeof(gSimpleMagic) / sizeof(wchar_t));
|
||||
|
||||
for (auto j : m_modules)
|
||||
{
|
||||
module = j.first;
|
||||
|
||||
for (auto i : *j.second)
|
||||
{
|
||||
size = module.size();
|
||||
memcpy(meta, &size, sizeof(meta));
|
||||
file.write(meta, gMetaCharCount);
|
||||
file.write(module.c_str(), size);
|
||||
|
||||
size = i.first.size();
|
||||
memcpy(meta, &size, sizeof(meta));
|
||||
file.write(meta, gMetaCharCount);
|
||||
file.write(i.first.c_str(), size);
|
||||
|
||||
size = i.second.size();
|
||||
memcpy(meta, &size, sizeof(meta));
|
||||
file.write(meta, gMetaCharCount);
|
||||
file.write(i.second.c_str(), size);
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SimpleRegistry::clear()
|
||||
{
|
||||
for (auto pair : m_modules)
|
||||
{
|
||||
delete pair.second;
|
||||
}
|
||||
|
||||
m_modules.clear();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CEngineSettingsBackendApple::CEngineSettingsBackendApple(CEngineSettingsManager* parent, const wchar_t* moduleName)
|
||||
: CEngineSettingsBackend(parent, moduleName)
|
||||
, m_registry(new SimpleRegistry)
|
||||
, m_registryFilePath()
|
||||
{
|
||||
std::string rootValue = gEnv->pFileIO->GetAlias("@root@");
|
||||
if (rootValue.empty())
|
||||
{
|
||||
AZ_Warning("EngineSettings", false, "Could not get engine root.");
|
||||
return;
|
||||
}
|
||||
|
||||
rootValue.append(gDefaultRegistryLocation);
|
||||
m_registryFilePath = rootValue;
|
||||
}
|
||||
|
||||
CEngineSettingsBackendApple::~CEngineSettingsBackendApple()
|
||||
{
|
||||
delete m_registry, m_registry = nullptr;
|
||||
}
|
||||
|
||||
std::wstring CEngineSettingsBackendApple::GetModuleFilePath() const
|
||||
{
|
||||
std::string path;
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::string module = converter.to_bytes(moduleName());
|
||||
|
||||
void* handle = ::dlopen(module.c_str(), RTLD_LAZY);
|
||||
if (handle)
|
||||
{
|
||||
const int c = _dyld_image_count();
|
||||
for (int i = 0; i < c; ++i)
|
||||
{
|
||||
const char* image = _dyld_get_image_name(i);
|
||||
const void* altHandle = dlopen(image, RTLD_LAZY);
|
||||
if (handle == altHandle)
|
||||
{
|
||||
char absImage[PATH_MAX];
|
||||
realpath(image, absImage);
|
||||
char *ext = rindex(absImage, '.');
|
||||
if (ext)
|
||||
{
|
||||
*ext = '\0';
|
||||
}
|
||||
path.append(absImage);
|
||||
path.append(".ini");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return converter.from_bytes(path);
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::GetModuleSpecificStringEntryUtf16(const char* key, CWCharBuffer wbuffer)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
std::wstring str;
|
||||
if (!m_registry->getStrValue(moduleName(), wkey, str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wcscpy(wbuffer.getPtr(), str.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::GetModuleSpecificIntEntry(const char* key, int& value)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
return m_registry->getIntValue(moduleName(), wkey, value);
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::GetModuleSpecificBoolEntry(const char* key, bool& value)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
return m_registry->getBoolValue(moduleName(), wkey, value);
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
m_registry->setStrValue(moduleName(), wkey, str);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::SetModuleSpecificIntEntry(const char* key, const int& value)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
m_registry->setIntValue(moduleName(), wkey, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::SetModuleSpecificBoolEntry(const char* key, const bool& value)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
|
||||
std::wstring wkey = converter.from_bytes(key);
|
||||
|
||||
m_registry->setBoolValue(moduleName(), wkey, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::GetInstalledBuildRootPathUtf16(const int index, CWCharBuffer name, CWCharBuffer path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendApple::StoreEngineSettingsToRegistry()
|
||||
{
|
||||
bool bRet = true;
|
||||
wchar_t buffer[1024];
|
||||
|
||||
// ResourceCompiler Specific
|
||||
if (parent()->GetValueByRef("RC_ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
m_registry->setBoolValue(REG_BASE_SETTING_KEY, L"RC_ShowWindow", b);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_HideCustom", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
m_registry->setBoolValue(REG_BASE_SETTING_KEY, L"RC_HideCustom", b);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_Parameters", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
m_registry->setStrValue(REG_BASE_SETTING_KEY, L"RC_Parameters", buffer);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_EnableSourceControl", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
m_registry->setBoolValue(REG_BASE_SETTING_KEY, L"RC_EnableSourceControl", b);
|
||||
}
|
||||
|
||||
bRet &= m_registry->saveToFile(m_registryFilePath.c_str());
|
||||
return bRet;
|
||||
}
|
||||
|
||||
void CEngineSettingsBackendApple::LoadEngineSettingsFromRegistry()
|
||||
{
|
||||
if (!m_registry->loadFromFile(m_registryFilePath.c_str()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring wStrResult;
|
||||
bool bResult;
|
||||
|
||||
if (m_registry->getStrValue(REG_BASE_SETTING_KEY, L"RootPath", wStrResult))
|
||||
{
|
||||
parent()->SetKey("ENG_RootPath", wStrResult.c_str());
|
||||
}
|
||||
|
||||
// Engine Specific
|
||||
if (m_registry->getStrValue(REG_BASE_SETTING_KEY, L"ENG_RootPath", wStrResult))
|
||||
{
|
||||
parent()->SetKey("ENG_RootPath", wStrResult.c_str());
|
||||
}
|
||||
|
||||
// ResourceCompiler Specific
|
||||
if (m_registry->getBoolValue(REG_BASE_SETTING_KEY, L"RC_ShowWindow", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_ShowWindow", bResult);
|
||||
}
|
||||
if (m_registry->getBoolValue(REG_BASE_SETTING_KEY, L"RC_HideCustom", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_HideCustom", bResult);
|
||||
}
|
||||
if (m_registry->getStrValue(REG_BASE_SETTING_KEY, L"RC_Parameters", wStrResult))
|
||||
{
|
||||
parent()->SetKey("RC_Parameters", wStrResult.c_str());
|
||||
}
|
||||
if (m_registry->getBoolValue(REG_BASE_SETTING_KEY, L"RC_EnableSourceControl", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_EnableSourceControl", bResult);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDAPPLE_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDAPPLE_H
|
||||
#pragma once
|
||||
|
||||
#include "EngineSettingsBackend.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
class CEngineSettingsManager;
|
||||
class SimpleRegistry;
|
||||
|
||||
class CEngineSettingsBackendApple : public CEngineSettingsBackend
|
||||
{
|
||||
public:
|
||||
CEngineSettingsBackendApple(CEngineSettingsManager* parent, const wchar_t* moduleName = NULL);
|
||||
~CEngineSettingsBackendApple();
|
||||
|
||||
std::wstring GetModuleFilePath() const override;
|
||||
|
||||
bool GetModuleSpecificStringEntryUtf16(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer) override;
|
||||
bool GetModuleSpecificIntEntry(const char* key, int& value) override;
|
||||
bool GetModuleSpecificBoolEntry(const char* key, bool& value) override;
|
||||
|
||||
bool SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str) override;
|
||||
bool SetModuleSpecificIntEntry(const char* key, const int& value) override;
|
||||
bool SetModuleSpecificBoolEntry(const char* key, const bool& value) override;
|
||||
|
||||
bool GetInstalledBuildRootPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path) override;
|
||||
|
||||
void LoadEngineSettingsFromRegistry() override;
|
||||
bool StoreEngineSettingsToRegistry() override;
|
||||
|
||||
private:
|
||||
SimpleRegistry *m_registry;
|
||||
std::string m_registryFilePath;
|
||||
};
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDAPPLE_H
|
||||
@@ -1,431 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EngineSettingsBackendWin32.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
#include "AzCore/PlatformDef.h"
|
||||
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
|
||||
#include "EngineSettingsManager.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include <windows.h>
|
||||
|
||||
#define REG_SOFTWARE L"Software\\"
|
||||
#define REG_COMPANY_NAME L"Amazon\\"
|
||||
#define REG_PRODUCT_NAME L"Open 3D Engine\\"
|
||||
#define REG_SETTING L"Settings\\"
|
||||
#define REG_BASE_SETTING_KEY REG_SOFTWARE REG_COMPANY_NAME REG_PRODUCT_NAME REG_SETTING
|
||||
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
using namespace SettingsManagerHelpers;
|
||||
|
||||
static bool g_bWindowQuit;
|
||||
static CEngineSettingsManager* g_pThis = 0;
|
||||
static const unsigned int IDC_hEditRootPath = 100;
|
||||
static const unsigned int IDC_hBtnBrowse = 101;
|
||||
|
||||
namespace
|
||||
{
|
||||
class RegKey
|
||||
{
|
||||
public:
|
||||
RegKey(const wchar_t* key, bool writeable);
|
||||
~RegKey();
|
||||
void* pKey;
|
||||
};
|
||||
|
||||
RegKey::RegKey(const wchar_t* key, bool writeable)
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG result;
|
||||
if (writeable)
|
||||
{
|
||||
result = RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, 0, 0, KEY_WRITE, 0, &hKey, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ, &hKey);
|
||||
}
|
||||
pKey = hKey;
|
||||
}
|
||||
|
||||
RegKey::~RegKey()
|
||||
{
|
||||
RegCloseKey((HKEY)pKey);
|
||||
}
|
||||
}
|
||||
|
||||
CEngineSettingsBackendWin32::CEngineSettingsBackendWin32(CEngineSettingsManager* parent, const wchar_t* moduleName)
|
||||
: CEngineSettingsBackend(parent, moduleName)
|
||||
{
|
||||
}
|
||||
|
||||
std::wstring CEngineSettingsBackendWin32::GetModuleFilePath() const
|
||||
{
|
||||
wchar_t szFilename[_MAX_PATH];
|
||||
GetModuleFileNameW((HINSTANCE)&__ImageBase, szFilename, _MAX_PATH);
|
||||
wchar_t drive[_MAX_DRIVE];
|
||||
wchar_t dir[_MAX_DIR];
|
||||
wchar_t fname[_MAX_FNAME];
|
||||
wchar_t ext[1] = L"";
|
||||
_wsplitpath_s(szFilename, drive, dir, fname, ext);
|
||||
_wmakepath_s(szFilename, drive, dir, fname, L"ini");
|
||||
return szFilename;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetModuleSpecificStringEntryUtf16(const char* key, CWCharBuffer wbuffer)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), false);
|
||||
if (!superKey.pKey)
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
if (!GetRegValue(superKey.pKey, key, wbuffer))
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetModuleSpecificIntEntry(const char* key, int& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), false);
|
||||
if (!superKey.pKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GetRegValue(superKey.pKey, key, value))
|
||||
{
|
||||
value = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetModuleSpecificBoolEntry(const char* key, bool& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), false);
|
||||
if (!superKey.pKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GetRegValue(superKey.pKey, key, value))
|
||||
{
|
||||
value = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), true);
|
||||
if (superKey.pKey)
|
||||
{
|
||||
return SetRegValue(superKey.pKey, key, str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetModuleSpecificIntEntry(const char* key, const int& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), true);
|
||||
if (superKey.pKey)
|
||||
{
|
||||
return SetRegValue(superKey.pKey, key, value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetModuleSpecificBoolEntry(const char* key, const bool& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> s = REG_BASE_SETTING_KEY;
|
||||
s.append(moduleName().c_str());
|
||||
RegKey superKey(s.c_str(), true);
|
||||
if (superKey.pKey)
|
||||
{
|
||||
return SetRegValue(superKey.pKey, key, value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetInstalledBuildRootPathUtf16(const int index, CWCharBuffer name, CWCharBuffer path)
|
||||
{
|
||||
RegKey key(REG_BASE_SETTING_KEY L"O3DEExport\\ProjectBuilds", false);
|
||||
if (key.pKey)
|
||||
{
|
||||
DWORD type;
|
||||
DWORD nameSizeInBytes = DWORD(name.getSizeInBytes());
|
||||
DWORD pathSizeInBytes = DWORD(path.getSizeInBytes());
|
||||
LONG result = RegEnumValueW((HKEY)key.pKey, index, name.getPtr(), &nameSizeInBytes, NULL, &type, (BYTE*)path.getPtr(), &pathSizeInBytes);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::StoreEngineSettingsToRegistry()
|
||||
{
|
||||
// make sure the path in registry exists
|
||||
{
|
||||
RegKey key0(REG_SOFTWARE REG_COMPANY_NAME, true);
|
||||
if (!key0.pKey)
|
||||
{
|
||||
RegKey software(REG_SOFTWARE, true);
|
||||
HKEY hKey;
|
||||
RegCreateKeyW((HKEY)software.pKey, REG_COMPANY_NAME, &hKey);
|
||||
if (!hKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RegKey key1(REG_SOFTWARE REG_COMPANY_NAME REG_PRODUCT_NAME, true);
|
||||
if (!key1.pKey)
|
||||
{
|
||||
RegKey softwareCompany(REG_SOFTWARE REG_COMPANY_NAME, true);
|
||||
HKEY hKey;
|
||||
RegCreateKeyW((HKEY)softwareCompany.pKey, REG_COMPANY_NAME, &hKey);
|
||||
if (!hKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RegKey key2(REG_BASE_SETTING_KEY, true);
|
||||
if (!key2.pKey)
|
||||
{
|
||||
RegKey softwareCompanyProduct(REG_SOFTWARE REG_COMPANY_NAME REG_PRODUCT_NAME, true);
|
||||
HKEY hKey;
|
||||
RegCreateKeyW((HKEY)key2.pKey, REG_SETTING, &hKey);
|
||||
if (!hKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bRet = true;
|
||||
|
||||
RegKey key(REG_BASE_SETTING_KEY, true);
|
||||
if (!key.pKey)
|
||||
{
|
||||
bRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t buffer[1024];
|
||||
|
||||
// ResourceCompiler Specific
|
||||
|
||||
if (parent()->GetValueByRef("RC_ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
SetRegValue(key.pKey, "RC_ShowWindow", b);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_HideCustom", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
SetRegValue(key.pKey, "RC_HideCustom", b);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_Parameters", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
SetRegValue(key.pKey, "RC_Parameters", buffer);
|
||||
}
|
||||
|
||||
if (parent()->GetValueByRef("RC_EnableSourceControl", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
const bool b = wcscmp(buffer, L"true") == 0;
|
||||
SetRegValue(key.pKey, "RC_EnableSourceControl", b);
|
||||
}
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
void CEngineSettingsBackendWin32::LoadEngineSettingsFromRegistry()
|
||||
{
|
||||
wchar_t buffer[1024];
|
||||
|
||||
bool bResult;
|
||||
|
||||
// Engine Specific (Deprecated value)
|
||||
RegKey key(REG_BASE_SETTING_KEY, false);
|
||||
if (key.pKey)
|
||||
{
|
||||
if (GetRegValue(key.pKey, "RootPath", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
parent()->SetKey("ENG_RootPath", buffer);
|
||||
}
|
||||
|
||||
// Engine Specific
|
||||
if (GetRegValue(key.pKey, "ENG_RootPath", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
parent()->SetKey("ENG_RootPath", buffer);
|
||||
}
|
||||
|
||||
// ResourceCompiler Specific
|
||||
if (GetRegValue(key.pKey, "RC_ShowWindow", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_ShowWindow", bResult);
|
||||
}
|
||||
if (GetRegValue(key.pKey, "RC_HideCustom", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_HideCustom", bResult);
|
||||
}
|
||||
if (GetRegValue(key.pKey, "RC_Parameters", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
parent()->SetKey("RC_Parameters", buffer);
|
||||
}
|
||||
if (GetRegValue(key.pKey, "RC_EnableSourceControl", bResult))
|
||||
{
|
||||
parent()->SetKey("RC_EnableSourceControl", bResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetRegValue(void* key, const char* valueName, const wchar_t* value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
size_t const sizeInBytes = (wcslen(value) + 1) * sizeof(value[0]);
|
||||
return (ERROR_SUCCESS == RegSetValueExW((HKEY)key, name.c_str(), 0, REG_SZ, (BYTE*)value, DWORD(sizeInBytes)));
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetRegValue(void* key, const char* valueName, bool value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
DWORD dwVal = value;
|
||||
return (ERROR_SUCCESS == RegSetValueExW((HKEY)key, name.c_str(), 0, REG_DWORD, (BYTE*)&dwVal, sizeof(dwVal)));
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::SetRegValue(void* key, const char* valueName, int value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
DWORD dwVal = value;
|
||||
return (ERROR_SUCCESS == RegSetValueExW((HKEY)key, name.c_str(), 0, REG_DWORD, (BYTE*)&dwVal, sizeof(dwVal)));
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetRegValue(void* key, const char* valueName, CWCharBuffer wbuffer)
|
||||
{
|
||||
if (wbuffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
DWORD type;
|
||||
DWORD sizeInBytes = DWORD(wbuffer.getSizeInBytes());
|
||||
if (ERROR_SUCCESS != RegQueryValueExW((HKEY)key, name.c_str(), NULL, &type, (BYTE*)wbuffer.getPtr(), &sizeInBytes))
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t sizeInElements = sizeInBytes / sizeof(wbuffer[0]);
|
||||
if (sizeInElements > wbuffer.getSizeInElements()) // paranoid check
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// According to MSDN documentation for RegQueryValueEx(), strings returned by the function
|
||||
// are not zero-terminated sometimes, so we need to terminate them by ourselves.
|
||||
if (wbuffer[sizeInElements - 1] != 0)
|
||||
{
|
||||
if (sizeInElements >= wbuffer.getSizeInElements())
|
||||
{
|
||||
// No space left to put terminating zero character
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
wbuffer[sizeInElements] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetRegValue(void* key, const char* valueName, bool& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
// Open the appropriate registry key
|
||||
DWORD type, dwVal = 0, size = sizeof(dwVal);
|
||||
bool res = (ERROR_SUCCESS == RegQueryValueExW((HKEY)key, name.c_str(), NULL, &type, (BYTE*)&dwVal, &size));
|
||||
if (res)
|
||||
{
|
||||
value = (dwVal != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t buffer[100];
|
||||
res = GetRegValue(key, valueName, CWCharBuffer(buffer, sizeof(buffer)));
|
||||
if (res)
|
||||
{
|
||||
value = (wcscmp(buffer, L"true") == 0);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CEngineSettingsBackendWin32::GetRegValue(void* key, const char* valueName, int& value)
|
||||
{
|
||||
CFixedString<wchar_t, 256> name;
|
||||
name.appendAscii(valueName);
|
||||
|
||||
// Open the appropriate registry key
|
||||
DWORD type, dwVal = 0, size = sizeof(dwVal);
|
||||
|
||||
bool res = (ERROR_SUCCESS == RegQueryValueExW((HKEY)key, name.c_str(), NULL, &type, (BYTE*)&dwVal, &size));
|
||||
if (res)
|
||||
{
|
||||
value = dwVal;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // AZ_PLATFORM_WINDOWS
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDWIN32_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDWIN32_H
|
||||
#pragma once
|
||||
|
||||
#include "EngineSettingsBackend.h"
|
||||
|
||||
#ifdef CRY_ENABLE_RC_HELPER
|
||||
|
||||
class CEngineSettingsManager;
|
||||
|
||||
class CEngineSettingsBackendWin32 : public CEngineSettingsBackend
|
||||
{
|
||||
public:
|
||||
CEngineSettingsBackendWin32(CEngineSettingsManager* parent, const wchar_t* moduleName = NULL);
|
||||
|
||||
std::wstring GetModuleFilePath() const override;
|
||||
|
||||
bool GetModuleSpecificStringEntryUtf16(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer) override;
|
||||
bool GetModuleSpecificIntEntry(const char* key, int& value) override;
|
||||
bool GetModuleSpecificBoolEntry(const char* key, bool& value) override;
|
||||
|
||||
bool SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str) override;
|
||||
bool SetModuleSpecificIntEntry(const char* key, const int& value) override;
|
||||
bool SetModuleSpecificBoolEntry(const char* key, const bool& value) override;
|
||||
|
||||
bool GetInstalledBuildRootPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path) override;
|
||||
|
||||
void LoadEngineSettingsFromRegistry() override;
|
||||
bool StoreEngineSettingsToRegistry() override;
|
||||
|
||||
protected:
|
||||
bool SetRegValue(void* key, const char* valueName, const wchar_t* value);
|
||||
bool SetRegValue(void* key, const char* valueName, bool value);
|
||||
bool SetRegValue(void* key, const char* valueName, int value);
|
||||
bool GetRegValue(void* key, const char* valueName, SettingsManagerHelpers::CWCharBuffer wbuffer);
|
||||
bool GetRegValue(void* key, const char* valueName, bool& value);
|
||||
bool GetRegValue(void* key, const char* valueName, int& value);
|
||||
};
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ENGINESETTINGSBACKENDWIN32_H
|
||||
@@ -1,479 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
#include "EngineSettingsManager.h"
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#include <assert.h> // assert()
|
||||
#include "EngineSettingsBackend.h"
|
||||
|
||||
#include "AzCore/PlatformDef.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#include "EngineSettingsBackendWin32.h"
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#elif AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
#include "EngineSettingsBackendApple.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
|
||||
#define INFOTEXT L"Please specify the directory of your CryENGINE installation (RootPath):"
|
||||
|
||||
|
||||
using namespace SettingsManagerHelpers;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEngineSettingsManager::CEngineSettingsManager(const wchar_t* moduleName, const wchar_t* iniFileName)
|
||||
: m_hWndParent(0)
|
||||
, m_backend(NULL)
|
||||
{
|
||||
m_sModuleName.clear();
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
m_backend = new CEngineSettingsBackendWin32(this, moduleName);
|
||||
#elif AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
m_backend = new CEngineSettingsBackendApple(this, moduleName);
|
||||
#endif
|
||||
assert(m_backend);
|
||||
|
||||
// std initialization
|
||||
RestoreDefaults();
|
||||
|
||||
// try to load content from INI file
|
||||
if (moduleName != NULL)
|
||||
{
|
||||
m_sModuleName = moduleName;
|
||||
|
||||
if (iniFileName == NULL)
|
||||
{
|
||||
// find INI filename located in module path
|
||||
m_sModuleFileName = m_backend->GetModuleFilePath().c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sModuleFileName = iniFileName;
|
||||
}
|
||||
|
||||
if (LoadValuesFromConfigFile(m_sModuleFileName.c_str()))
|
||||
{
|
||||
m_bGetDataFromBackend = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_bGetDataFromBackend = true;
|
||||
|
||||
// load basic content from registry
|
||||
LoadEngineSettingsFromRegistry();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEngineSettingsManager::~CEngineSettingsManager()
|
||||
{
|
||||
delete m_backend, m_backend = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::RestoreDefaults()
|
||||
{
|
||||
// Engine
|
||||
SetKey("ENG_RootPath", L"");
|
||||
|
||||
// RC
|
||||
SetKey("RC_ShowWindow", false);
|
||||
SetKey("RC_HideCustom", false);
|
||||
SetKey("RC_Parameters", L"");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetModuleSpecificStringEntryUtf16(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer)
|
||||
{
|
||||
if (wbuffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
if (!HasKey(key))
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
if (!GetValueByRef(key, wbuffer))
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_backend);
|
||||
return m_backend->GetModuleSpecificStringEntryUtf16(key, wbuffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetModuleSpecificStringEntryUtf8(const char* key, SettingsManagerHelpers::CCharBuffer buffer)
|
||||
{
|
||||
if (buffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wchar_t wBuffer[1024];
|
||||
|
||||
if (!GetModuleSpecificStringEntryUtf16(key, SettingsManagerHelpers::CWCharBuffer(wBuffer, sizeof(wBuffer))))
|
||||
{
|
||||
buffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
SettingsManagerHelpers::ConvertUtf16ToUtf8(wBuffer, buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetModuleSpecificIntEntry(const char* key, int& value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
if (!HasKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GetValueByRef(key, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_backend);
|
||||
return m_backend->GetModuleSpecificIntEntry(key, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetModuleSpecificBoolEntry(const char* key, bool& value)
|
||||
{
|
||||
value = false;
|
||||
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
if (!HasKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GetValueByRef(key, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_backend);
|
||||
return m_backend->GetModuleSpecificBoolEntry(key, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str)
|
||||
{
|
||||
SetKey(key, str);
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
return StoreData();
|
||||
}
|
||||
|
||||
assert(m_backend);
|
||||
return m_backend->SetModuleSpecificStringEntryUtf16(key, str);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::SetModuleSpecificIntEntry(const char* key, const int& value)
|
||||
{
|
||||
SetKey(key, value);
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
return StoreData();
|
||||
}
|
||||
|
||||
assert(m_backend);
|
||||
return m_backend->SetModuleSpecificIntEntry(key, value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::SetModuleSpecificBoolEntry(const char* key, const bool& value)
|
||||
{
|
||||
SetKey(key, value);
|
||||
if (!m_bGetDataFromBackend)
|
||||
{
|
||||
return StoreData();
|
||||
}
|
||||
|
||||
assert(m_backend);
|
||||
return m_backend->SetModuleSpecificBoolEntry(key, value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::SetModuleSpecificStringEntryUtf8(const char* key, const char* str)
|
||||
{
|
||||
wchar_t wbuffer[512];
|
||||
SettingsManagerHelpers::ConvertUtf8ToUtf16(str, SettingsManagerHelpers::CWCharBuffer(wbuffer, sizeof(wbuffer)));
|
||||
|
||||
return SetModuleSpecificStringEntryUtf16(key, wbuffer);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::HasKey(const char* key)
|
||||
{
|
||||
return m_keyValueArray.find(key) != 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::SetKey(const char* key, const wchar_t* value)
|
||||
{
|
||||
m_keyValueArray.set(key, value);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::SetKey(const char* key, bool value)
|
||||
{
|
||||
m_keyValueArray.set(key, (value ? L"true" : L"false"));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::SetKey(const char* key, int value)
|
||||
{
|
||||
m_keyValueArray.set(key, std::to_wstring(value).c_str());
|
||||
}
|
||||
|
||||
bool CEngineSettingsManager::GetInstalledBuildRootPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path)
|
||||
{
|
||||
assert(m_backend);
|
||||
return m_backend->GetInstalledBuildRootPathUtf16(index, name, path);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::SetParentDialog(size_t window)
|
||||
{
|
||||
m_hWndParent = window;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::StoreData()
|
||||
{
|
||||
if (m_bGetDataFromBackend)
|
||||
{
|
||||
bool res = StoreEngineSettingsToRegistry();
|
||||
|
||||
if (!res)
|
||||
{
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
MessageBoxA(reinterpret_cast<HWND>(m_hWndParent), "Could not store data to registry.", "Error", MB_OK | MB_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// store data to INI file
|
||||
|
||||
FILE* file;
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
_wfopen_s(&file, m_sModuleFileName.c_str(), L"wb");
|
||||
#else
|
||||
char fname[MAX_PATH];
|
||||
memset(fname, 0, MAX_PATH);
|
||||
wcstombs(fname, m_sModuleFileName.c_str(), MAX_PATH);
|
||||
file = fopen(fname, "wb");
|
||||
#endif
|
||||
if (file == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
for (size_t i = 0; i < m_keyValueArray.size(); ++i)
|
||||
{
|
||||
const SKeyValue& kv = m_keyValueArray[i];
|
||||
|
||||
fprintf_s(file, kv.key.c_str());
|
||||
fprintf_s(file, " = ");
|
||||
|
||||
if (kv.value.length() > 0)
|
||||
{
|
||||
SettingsManagerHelpers::ConvertUtf16ToUtf8(kv.value.c_str(), SettingsManagerHelpers::CCharBuffer(buffer, sizeof(buffer)));
|
||||
fprintf_s(file, "%s", buffer);
|
||||
}
|
||||
|
||||
fprintf_s(file, "\r\n");
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::LoadValuesFromConfigFile(const wchar_t* szFileName)
|
||||
{
|
||||
m_keyValueArray.clear();
|
||||
|
||||
// read file to memory
|
||||
|
||||
FILE* file;
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
_wfopen_s(&file, szFileName, L"rb");
|
||||
#else
|
||||
char fname[MAX_PATH];
|
||||
memset(fname, 0, MAX_PATH);
|
||||
wcstombs(fname, szFileName, MAX_PATH);
|
||||
file = fopen(fname, "rb");
|
||||
#endif
|
||||
if (file == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
char* data = new char[size + 1];
|
||||
fread_s(data, size, 1, size, file);
|
||||
fclose(file);
|
||||
|
||||
wchar_t wBuffer[1024];
|
||||
|
||||
// parse file for root path
|
||||
|
||||
int start = 0, end = 0;
|
||||
while (end < size)
|
||||
{
|
||||
while (end < size && data[end] != '\n')
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
memcpy(data, &data[start], end - start);
|
||||
data[end - start] = 0;
|
||||
start = end = end + 1;
|
||||
|
||||
CFixedString<char, 2048> line(data);
|
||||
size_t equalsOfs;
|
||||
for (equalsOfs = 0; equalsOfs < line.length(); ++equalsOfs)
|
||||
{
|
||||
if (line[equalsOfs] == '=')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (equalsOfs < line.length())
|
||||
{
|
||||
CFixedString<char, 256> key;
|
||||
CFixedString<wchar_t, 1024> value;
|
||||
|
||||
key.appendAscii(line.c_str(), equalsOfs);
|
||||
key.trim();
|
||||
|
||||
SettingsManagerHelpers::ConvertUtf8ToUtf16(line.c_str() + equalsOfs + 1, SettingsManagerHelpers::CWCharBuffer(wBuffer, sizeof(wBuffer)));
|
||||
value.append(wBuffer);
|
||||
value.trim();
|
||||
|
||||
m_keyValueArray.set(key.c_str(), value.c_str());
|
||||
}
|
||||
}
|
||||
delete[] data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::StoreEngineSettingsToRegistry()
|
||||
{
|
||||
assert(m_backend);
|
||||
return m_backend->StoreEngineSettingsToRegistry();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CEngineSettingsManager::LoadEngineSettingsFromRegistry()
|
||||
{
|
||||
assert(m_backend);
|
||||
m_backend->LoadEngineSettingsFromRegistry();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetValueByRef(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer) const
|
||||
{
|
||||
if (wbuffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const SKeyValue* p = m_keyValueArray.find(key);
|
||||
if (!p || (p->value.length() + 1) > wbuffer.getSizeInElements())
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return false;
|
||||
}
|
||||
azwcscpy(wbuffer.getPtr(), wbuffer.getSizeInElements(), p->value.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetValueByRef(const char* key, bool& value) const
|
||||
{
|
||||
wchar_t buffer[100];
|
||||
if (!GetValueByRef(key, SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value = (wcscmp(buffer, L"true") == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CEngineSettingsManager::GetValueByRef(const char* key, int& value) const
|
||||
{
|
||||
wchar_t buffer[100];
|
||||
if (!GetValueByRef(key, SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value = wcstol(buffer, 0, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //(CRY_ENABLE_RC_HELPER)
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ENGINESETTINGSMANAGER_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ENGINESETTINGSMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#include "SettingsManagerHelpers.h"
|
||||
|
||||
class CEngineSettingsBackend;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Manages storage and loading of all information for tools and CryENGINE, by either registry or an INI file.
|
||||
// Information can be read and set by key-to-value functions.
|
||||
// Specific information can be set by a dialog application called by this class.
|
||||
// If the engine root path is not found, a fall-back dialog is opened.
|
||||
class CEngineSettingsManager
|
||||
{
|
||||
public:
|
||||
// prepares CEngineSettingsManager to get requested information either from registry or an INI file,
|
||||
// if existent as a file with name an directory equal to the module, or from registry.
|
||||
CEngineSettingsManager(const wchar_t* moduleName = NULL, const wchar_t* iniFileName = NULL);
|
||||
~CEngineSettingsManager();
|
||||
|
||||
void RestoreDefaults();
|
||||
|
||||
// stores/loads user specific information for modules to/from registry or INI file
|
||||
bool GetModuleSpecificStringEntryUtf16(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer);
|
||||
bool GetModuleSpecificStringEntryUtf8(const char* key, SettingsManagerHelpers::CCharBuffer buffer);
|
||||
bool GetModuleSpecificIntEntry(const char* key, int& value);
|
||||
bool GetModuleSpecificBoolEntry(const char* key, bool& value);
|
||||
|
||||
bool SetModuleSpecificStringEntryUtf16(const char* key, const wchar_t* str);
|
||||
bool SetModuleSpecificStringEntryUtf8(const char* key, const char* str);
|
||||
bool SetModuleSpecificIntEntry(const char* key, const int& value);
|
||||
bool SetModuleSpecificBoolEntry(const char* key, const bool& value);
|
||||
|
||||
bool GetValueByRef(const char* key, SettingsManagerHelpers::CWCharBuffer wbuffer) const;
|
||||
bool GetValueByRef(const char* key, bool& value) const;
|
||||
bool GetValueByRef(const char* key, int& value) const;
|
||||
|
||||
void SetKey(const char* key, const wchar_t* value);
|
||||
void SetKey(const char* key, bool value);
|
||||
void SetKey(const char* key, int value);
|
||||
|
||||
bool StoreData();
|
||||
|
||||
bool GetInstalledBuildRootPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path);
|
||||
|
||||
void SetParentDialog(size_t window);
|
||||
|
||||
private:
|
||||
bool HasKey(const char* key);
|
||||
|
||||
void LoadEngineSettingsFromRegistry();
|
||||
bool StoreEngineSettingsToRegistry();
|
||||
|
||||
// parses a file and stores all flags in a private key-value-map
|
||||
bool LoadValuesFromConfigFile(const wchar_t* szFileName);
|
||||
|
||||
private:
|
||||
CEngineSettingsBackend *m_backend;
|
||||
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, 256> m_sModuleName; // name to store key-value pairs of modules in (registry) or to identify INI file
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, 256> m_sModuleFileName; // used in case of data being loaded from INI file
|
||||
bool m_bGetDataFromBackend;
|
||||
SettingsManagerHelpers::CKeyValueArray<30> m_keyValueArray;
|
||||
|
||||
void* m_hBtnBrowse;
|
||||
size_t m_hWndParent;
|
||||
};
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ENGINESETTINGSMANAGER_H
|
||||
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_IFLARES_H
|
||||
#define CRYINCLUDE_CRYCOMMON_IFLARES_H
|
||||
#pragma once
|
||||
|
||||
#include <IFuncVariable.h> // <> required for Interfuscator
|
||||
#include <IXml.h> // <> required for Interfuscator
|
||||
#include "smartptr.h"
|
||||
|
||||
struct IShader;
|
||||
class CCamera;
|
||||
|
||||
class __MFPA
|
||||
{
|
||||
};
|
||||
class __MFPB
|
||||
{
|
||||
};
|
||||
#define MFP_SIZE_ENFORCE : public __MFPA, public __MFPB
|
||||
|
||||
enum EFlareType
|
||||
{
|
||||
eFT__Base__,
|
||||
eFT_Root,
|
||||
eFT_Group,
|
||||
eFT_Ghost,
|
||||
eFT_MultiGhosts,
|
||||
eFT_Glow,
|
||||
eFT_ChromaticRing,
|
||||
eFT_IrisShafts,
|
||||
eFT_CameraOrbs,
|
||||
eFT_ImageSpaceShafts,
|
||||
eFT_Streaks,
|
||||
eFT_Reference,
|
||||
eFT_Proxy,
|
||||
eFT_Max
|
||||
};
|
||||
|
||||
#define FLARE_LIBS_PATH "libs/flares/"
|
||||
#define FLARE_EXPORT_FILE "LensFlareList.xml"
|
||||
#define FLARE_EXPORT_FILE_VERSION "1"
|
||||
|
||||
struct FlareInfo
|
||||
{
|
||||
EFlareType type;
|
||||
const char* name;
|
||||
#if defined(FLARES_SUPPORT_EDITING)
|
||||
const char* imagename;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(FLARES_SUPPORT_EDITING)
|
||||
# define ADD_FLARE_INFO(type, name, imagename) {type, name, imagename}
|
||||
#else
|
||||
# define ADD_FLARE_INFO(type, name, imagename) {type, name}
|
||||
#endif
|
||||
|
||||
class FlareInfoArray
|
||||
{
|
||||
public:
|
||||
struct Props
|
||||
{
|
||||
const FlareInfo* p;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static const Props Get()
|
||||
{
|
||||
static const FlareInfo flareInfoArray[] =
|
||||
{
|
||||
ADD_FLARE_INFO(eFT__Base__, "__Base__", NULL),
|
||||
ADD_FLARE_INFO(eFT_Root, "Root", NULL),
|
||||
ADD_FLARE_INFO(eFT_Group, "Group", NULL),
|
||||
ADD_FLARE_INFO(eFT_Ghost, "Ghost", "EngineAssets/Textures/flares/icons/ghost.dds"),
|
||||
ADD_FLARE_INFO(eFT_MultiGhosts, "Multi Ghost", "EngineAssets/Textures/flares/icons/multi_ghost.dds"),
|
||||
ADD_FLARE_INFO(eFT_Glow, "Glow", "EngineAssets/Textures/flares/icons/glow.dds"),
|
||||
ADD_FLARE_INFO(eFT_ChromaticRing, "ChromaticRing", "EngineAssets/Textures/flares/icons/ring.dds"),
|
||||
ADD_FLARE_INFO(eFT_IrisShafts, "IrisShafts", "EngineAssets/Textures/flares/icons/iris_shafts.dds"),
|
||||
ADD_FLARE_INFO(eFT_CameraOrbs, "CameraOrbs", "EngineAssets/Textures/flares/icons/orbs.dds"),
|
||||
ADD_FLARE_INFO(eFT_ImageSpaceShafts, "Vol Shafts", "EngineAssets/Textures/flares/icons/vol_shafts.dds"),
|
||||
ADD_FLARE_INFO(eFT_Streaks, "Streaks", "EngineAssets/Textures/flares/icons/iris_shafts.dds")
|
||||
};
|
||||
|
||||
Props ret;
|
||||
ret.p = flareInfoArray;
|
||||
ret.size = sizeof(flareInfoArray) / sizeof(flareInfoArray[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
FlareInfoArray();
|
||||
~FlareInfoArray();
|
||||
};
|
||||
|
||||
struct SLensFlareRenderParam
|
||||
{
|
||||
SLensFlareRenderParam()
|
||||
: pCamera(NULL)
|
||||
, pShader(NULL)
|
||||
{
|
||||
}
|
||||
~SLensFlareRenderParam(){}
|
||||
bool IsValid() const
|
||||
{
|
||||
return pCamera && pShader;
|
||||
}
|
||||
CCamera* pCamera;
|
||||
IShader* pShader;
|
||||
};
|
||||
|
||||
class ISoftOcclusionQuery
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ISoftOcclusionQuery() {}
|
||||
|
||||
virtual void AddRef() = 0;
|
||||
virtual void Release() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
class IOpticsElementBase MFP_SIZE_ENFORCE
|
||||
{
|
||||
public:
|
||||
|
||||
IOpticsElementBase()
|
||||
: m_nRefCount(0)
|
||||
{
|
||||
}
|
||||
void AddRef()
|
||||
{
|
||||
CryInterlockedIncrement(&m_nRefCount);
|
||||
}
|
||||
void Release()
|
||||
{
|
||||
if (CryInterlockedDecrement(&m_nRefCount) <= 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
// <interfuscator:shuffle>
|
||||
virtual EFlareType GetType() = 0;
|
||||
virtual bool IsGroup() const = 0;
|
||||
virtual string GetName() const = 0;
|
||||
virtual void SetName(const char* ch_name) = 0;
|
||||
virtual void Load(IXmlNode* pNode) = 0;
|
||||
|
||||
virtual IOpticsElementBase* GetParent() const = 0;
|
||||
virtual ~IOpticsElementBase() {
|
||||
}
|
||||
|
||||
virtual bool IsEnabled() const = 0;
|
||||
|
||||
virtual void AddElement(IOpticsElementBase* pElement) = 0;
|
||||
virtual void InsertElement(int nPos, IOpticsElementBase* pElement) = 0;
|
||||
virtual void Remove(int i) = 0;
|
||||
virtual void RemoveAll() = 0;
|
||||
virtual int GetElementCount() const = 0;
|
||||
virtual IOpticsElementBase* GetElementAt(int i) const = 0;
|
||||
|
||||
virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0;
|
||||
virtual void Invalidate() = 0;
|
||||
|
||||
virtual void Render(SLensFlareRenderParam* pParam, const Vec3& vPos) = 0;
|
||||
|
||||
virtual void SetOpticsReference([[maybe_unused]] IOpticsElementBase* pReference) {}
|
||||
virtual IOpticsElementBase* GetOpticsReference() const { return NULL; }
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
#if defined(FLARES_SUPPORT_EDITING)
|
||||
virtual AZStd::vector<FuncVariableGroup> GetEditorParamGroups() = 0;
|
||||
#endif
|
||||
|
||||
///Basic Setters///////////////////////////////////////////////////////////////
|
||||
virtual void SetEnabled(bool enabled) { (void)enabled; }
|
||||
virtual void SetSize(float size) { (void)size; }
|
||||
virtual void SetPerspectiveFactor(float perspectiveFactor) { (void)perspectiveFactor; }
|
||||
virtual void SetDistanceFadingFactor(float distanceFadingFactor) { (void)distanceFadingFactor; }
|
||||
virtual void SetBrightness(float brightness) { (void)brightness; }
|
||||
virtual void SetColor(ColorF color) { (void)color; }
|
||||
virtual void SetMovement(Vec2 movement) { (void)movement; }
|
||||
virtual void SetTransform(const Matrix33& xform) { (void)xform; }
|
||||
virtual void SetOccBokehEnabled(bool occBokehEnabled) { (void)occBokehEnabled; }
|
||||
virtual void SetOrbitAngle(float orbitAngle) { (void)orbitAngle; }
|
||||
virtual void SetSensorSizeFactor(float sizeFactor) { (void)sizeFactor; }
|
||||
virtual void SetSensorBrightnessFactor(float brightnessFactor) { (void)brightnessFactor; }
|
||||
virtual void SetAutoRotation(bool autoRotation) { (void)autoRotation; }
|
||||
virtual void SetAspectRatioCorrection(bool aspectRatioCorrection) { (void)aspectRatioCorrection; }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
volatile int m_nRefCount;
|
||||
};
|
||||
|
||||
class IOpticsManager
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IOpticsManager(){}
|
||||
virtual void Reset() = 0;
|
||||
virtual IOpticsElementBase* Create(EFlareType type) const = 0;
|
||||
virtual bool Load(const char* fullFlareName, int& nOutIndex, bool forceReload = false) = 0;
|
||||
virtual bool Load(XmlNodeRef& rootNode, int& nOutIndex) = 0;
|
||||
virtual IOpticsElementBase* GetOptics(int nIndex) = 0;
|
||||
virtual bool AddOptics(IOpticsElementBase* pOptics, const char* name, int& nOutNewIndex, bool allowReplace = false) = 0;
|
||||
virtual bool Rename(const char* fullFlareName, const char* newFullFlareName) = 0;
|
||||
virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0;
|
||||
virtual void Invalidate() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
typedef _smart_ptr<IOpticsElementBase> IOpticsElementBasePtr;
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_IFLARES_H
|
||||
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Interface to the Material Effects System
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_IMATERIALEFFECTS_H
|
||||
#define CRYINCLUDE_CRYCOMMON_IMATERIALEFFECTS_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
#define MATERIAL_EFFECTS_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
#include "CryFixedArray.h"
|
||||
|
||||
struct IRenderNode;
|
||||
struct ISurfaceType;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum EMFXPlayFlags
|
||||
{
|
||||
eMFXPF_Disable_Delay = BIT(0),
|
||||
eMFXPF_Audio = BIT(1),
|
||||
eMFXPF_Decal = BIT(2),
|
||||
eMFXPF_Particles = BIT(3),
|
||||
eMFXPF_Deprecated0 = BIT(4), // formerly eMFXPF_Flowgraph
|
||||
eMFXPF_ForceFeedback = BIT(5),
|
||||
eMFXPF_All = (eMFXPF_Audio | eMFXPF_Decal | eMFXPF_Particles | eMFXPF_Deprecated0 | eMFXPF_ForceFeedback),
|
||||
};
|
||||
|
||||
#define MFX_INVALID_ANGLE (gf_PI2 + 1)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SMFXAudioEffectRtpc
|
||||
{
|
||||
SMFXAudioEffectRtpc()
|
||||
{
|
||||
rtpcName = "";
|
||||
rtpcValue = 0.0f;
|
||||
}
|
||||
const char* rtpcName;
|
||||
float rtpcValue;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SMFXRunTimeEffectParams
|
||||
{
|
||||
static const int MAX_AUDIO_RTPCS = 4;
|
||||
|
||||
SMFXRunTimeEffectParams()
|
||||
: playSoundFP(false)
|
||||
, playflags(eMFXPF_All)
|
||||
, fLastTime(0.0f)
|
||||
, srcSurfaceId(0)
|
||||
, trgSurfaceId(0)
|
||||
, srcRenderNode(0)
|
||||
, trgRenderNode(0)
|
||||
, partID(0)
|
||||
, pos(ZERO)
|
||||
, decalPos(ZERO)
|
||||
, normal(0.0f, 0.0f, 1.0f)
|
||||
, angle(MFX_INVALID_ANGLE)
|
||||
, scale(1.0f)
|
||||
, audioComponentOffset(ZERO)
|
||||
, numAudioRtpcs(0)
|
||||
, fDecalPlacementTestMaxSize(1000.f)
|
||||
{
|
||||
dir[0].Set(0.0f, 0.0f, -1.0f);
|
||||
dir[1].Set(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
bool AddAudioRtpc(const char* name, float val)
|
||||
{
|
||||
if (numAudioRtpcs < MAX_AUDIO_RTPCS)
|
||||
{
|
||||
audioRtpcs[numAudioRtpcs].rtpcName = name;
|
||||
audioRtpcs[numAudioRtpcs].rtpcValue = val;
|
||||
++numAudioRtpcs;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResetAudioRtpcs()
|
||||
{
|
||||
numAudioRtpcs = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
uint16 playSoundFP; // Sets 1p/3p audio switch
|
||||
uint16 playflags; // See EMFXPlayFlags
|
||||
float fLastTime; // Last time this effect was played
|
||||
float fDecalPlacementTestMaxSize;
|
||||
|
||||
int srcSurfaceId;
|
||||
int trgSurfaceId;
|
||||
IRenderNode* srcRenderNode;
|
||||
IRenderNode* trgRenderNode;
|
||||
int partID;
|
||||
|
||||
Vec3 pos;
|
||||
Vec3 decalPos;
|
||||
Vec3 dir[2];
|
||||
Vec3 normal;
|
||||
float angle;
|
||||
float scale;
|
||||
|
||||
// audio related
|
||||
Vec3 audioComponentOffset; // in case of audio component, uses this offset
|
||||
|
||||
SMFXAudioEffectRtpc audioRtpcs[MAX_AUDIO_RTPCS];
|
||||
uint32 numAudioRtpcs;
|
||||
};
|
||||
|
||||
struct SMFXBreakageParams
|
||||
{
|
||||
enum EBreakageRequestFlags
|
||||
{
|
||||
eBRF_Matrix = BIT(0),
|
||||
eBRF_HitPos = BIT(1),
|
||||
eBRF_HitImpulse = BIT(2),
|
||||
eBRF_Velocity = BIT(3),
|
||||
eBRF_ExplosionImpulse = BIT(4),
|
||||
eBRF_Mass = BIT(5),
|
||||
eBFR_Entity = BIT(6),
|
||||
};
|
||||
|
||||
SMFXBreakageParams()
|
||||
: m_flags(0)
|
||||
, m_worldTM(IDENTITY)
|
||||
, m_vHitPos(ZERO)
|
||||
, m_vHitImpulse(IDENTITY)
|
||||
, m_vVelocity(ZERO)
|
||||
, m_fExplosionImpulse(1.0f)
|
||||
, m_fMass(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Matrix
|
||||
void SetMatrix(const Matrix34& worldTM)
|
||||
{
|
||||
m_worldTM = worldTM;
|
||||
SetFlag(eBRF_Matrix);
|
||||
}
|
||||
|
||||
const Matrix34& GetMatrix() const
|
||||
{
|
||||
return m_worldTM;
|
||||
}
|
||||
|
||||
// HitPos
|
||||
void SetHitPos(const Vec3& vHitPos)
|
||||
{
|
||||
m_vHitPos = vHitPos;
|
||||
SetFlag(eBRF_HitPos);
|
||||
}
|
||||
|
||||
const Vec3& GetHitPos() const
|
||||
{
|
||||
return m_vHitPos;
|
||||
}
|
||||
|
||||
// HitImpulse
|
||||
void SetHitImpulse(const Vec3& vHitImpulse)
|
||||
{
|
||||
m_vHitImpulse = vHitImpulse;
|
||||
SetFlag(eBRF_HitImpulse);
|
||||
}
|
||||
|
||||
const Vec3& GetHitImpulse() const
|
||||
{
|
||||
return m_vHitImpulse;
|
||||
}
|
||||
|
||||
// Velocity
|
||||
void SetVelocity(const Vec3& vVelocity)
|
||||
{
|
||||
m_vVelocity = vVelocity;
|
||||
SetFlag(eBRF_Velocity);
|
||||
}
|
||||
|
||||
const Vec3& GetVelocity() const
|
||||
{
|
||||
return m_vVelocity;
|
||||
}
|
||||
|
||||
// Explosion Impulse
|
||||
void SetExplosionImpulse(float fExplosionImpulse)
|
||||
{
|
||||
m_fExplosionImpulse = fExplosionImpulse;
|
||||
SetFlag(eBRF_ExplosionImpulse);
|
||||
}
|
||||
|
||||
float GetExplosionImpulse() const
|
||||
{
|
||||
return m_fExplosionImpulse;
|
||||
}
|
||||
|
||||
// Mass
|
||||
void SetMass(float fMass)
|
||||
{
|
||||
m_fMass = fMass;
|
||||
SetFlag(eBRF_Mass);
|
||||
}
|
||||
|
||||
float GetMass() const
|
||||
{
|
||||
return m_fMass;
|
||||
}
|
||||
|
||||
// Checking for flags
|
||||
bool CheckFlag(EBreakageRequestFlags flag) const
|
||||
{
|
||||
return (m_flags & flag) != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetFlag(EBreakageRequestFlags flag)
|
||||
{
|
||||
m_flags |= flag;
|
||||
}
|
||||
|
||||
void ClearFlag(EBreakageRequestFlags flag)
|
||||
{
|
||||
m_flags &= ~flag;
|
||||
}
|
||||
|
||||
uint32 m_flags;
|
||||
Matrix34 m_worldTM;
|
||||
Vec3 m_vHitPos;
|
||||
Vec3 m_vHitImpulse;
|
||||
Vec3 m_vVelocity;
|
||||
float m_fExplosionImpulse;
|
||||
float m_fMass;
|
||||
};
|
||||
|
||||
class IMFXParticleParams
|
||||
{
|
||||
public:
|
||||
IMFXParticleParams()
|
||||
: name(NULL)
|
||||
, userdata(NULL)
|
||||
, scale(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
const char* name;
|
||||
const char* userdata;
|
||||
float scale;
|
||||
};
|
||||
|
||||
class SMFXParticleListNode
|
||||
{
|
||||
public:
|
||||
static SMFXParticleListNode* Create();
|
||||
void Destroy();
|
||||
static void FreePool();
|
||||
|
||||
IMFXParticleParams m_particleParams;
|
||||
SMFXParticleListNode* pNext;
|
||||
|
||||
private:
|
||||
SMFXParticleListNode()
|
||||
{
|
||||
pNext = NULL;
|
||||
}
|
||||
~SMFXParticleListNode() {}
|
||||
};
|
||||
|
||||
class IMFXAudioParams
|
||||
{
|
||||
const static uint MAX_SWITCH_DATA_ELEMENTS = 4;
|
||||
|
||||
public:
|
||||
|
||||
struct SSwitchData
|
||||
{
|
||||
SSwitchData()
|
||||
: switchName(NULL)
|
||||
, switchStateName(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
const char* switchName;
|
||||
const char* switchStateName;
|
||||
};
|
||||
|
||||
IMFXAudioParams()
|
||||
: triggerName(NULL)
|
||||
{
|
||||
}
|
||||
const char* triggerName;
|
||||
|
||||
CryFixedArray<SSwitchData, MAX_SWITCH_DATA_ELEMENTS> triggerSwitches;
|
||||
};
|
||||
|
||||
class SMFXAudioListNode
|
||||
{
|
||||
public:
|
||||
static SMFXAudioListNode* Create();
|
||||
void Destroy();
|
||||
static void FreePool();
|
||||
|
||||
IMFXAudioParams m_audioParams;
|
||||
SMFXAudioListNode* pNext;
|
||||
|
||||
private:
|
||||
SMFXAudioListNode()
|
||||
: pNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~SMFXAudioListNode()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class IMFXDecalParams
|
||||
{
|
||||
public:
|
||||
IMFXDecalParams()
|
||||
{
|
||||
filename = 0;
|
||||
material = 0;
|
||||
minscale = 1.f;
|
||||
maxscale = 1.f;
|
||||
rotation = -1.f;
|
||||
lifetime = 10.0f;
|
||||
assemble = false;
|
||||
forceedge = false;
|
||||
}
|
||||
const char* filename;
|
||||
const char* material;
|
||||
float minscale;
|
||||
float maxscale;
|
||||
float rotation;
|
||||
float lifetime;
|
||||
bool assemble;
|
||||
bool forceedge;
|
||||
};
|
||||
|
||||
class SMFXDecalListNode
|
||||
{
|
||||
public:
|
||||
static SMFXDecalListNode* Create();
|
||||
void Destroy();
|
||||
static void FreePool();
|
||||
|
||||
IMFXDecalParams m_decalParams;
|
||||
SMFXDecalListNode* pNext;
|
||||
|
||||
private:
|
||||
SMFXDecalListNode()
|
||||
{
|
||||
pNext = 0;
|
||||
}
|
||||
~SMFXDecalListNode() {}
|
||||
};
|
||||
|
||||
class IMFXForceFeedbackParams
|
||||
{
|
||||
public:
|
||||
IMFXForceFeedbackParams()
|
||||
: forceFeedbackEventName (NULL)
|
||||
, intensityFallOffMinDistanceSqr(0.0f)
|
||||
, intensityFallOffMaxDistanceSqr(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
const char* forceFeedbackEventName;
|
||||
float intensityFallOffMinDistanceSqr;
|
||||
float intensityFallOffMaxDistanceSqr;
|
||||
};
|
||||
|
||||
class SMFXForceFeedbackListNode
|
||||
{
|
||||
public:
|
||||
static SMFXForceFeedbackListNode* Create();
|
||||
void Destroy();
|
||||
static void FreePool();
|
||||
|
||||
IMFXForceFeedbackParams m_forceFeedbackParams;
|
||||
SMFXForceFeedbackListNode* pNext;
|
||||
|
||||
private:
|
||||
SMFXForceFeedbackListNode()
|
||||
: pNext(NULL)
|
||||
{
|
||||
}
|
||||
~SMFXForceFeedbackListNode() {}
|
||||
};
|
||||
|
||||
struct SMFXResourceList;
|
||||
typedef _smart_ptr<SMFXResourceList> SMFXResourceListPtr;
|
||||
|
||||
struct SMFXResourceList
|
||||
{
|
||||
public:
|
||||
SMFXParticleListNode* m_particleList;
|
||||
SMFXAudioListNode* m_audioList;
|
||||
SMFXDecalListNode* m_decalList;
|
||||
SMFXForceFeedbackListNode* m_forceFeedbackList;
|
||||
|
||||
void AddRef() { ++m_refs; }
|
||||
void Release()
|
||||
{
|
||||
if (--m_refs <= 0)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
static SMFXResourceListPtr Create();
|
||||
static void FreePool();
|
||||
|
||||
private:
|
||||
int m_refs;
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
SMFXResourceList()
|
||||
: m_refs(0)
|
||||
{
|
||||
m_particleList = 0;
|
||||
m_audioList = 0;
|
||||
m_decalList = 0;
|
||||
m_forceFeedbackList = 0;
|
||||
}
|
||||
virtual ~SMFXResourceList()
|
||||
{
|
||||
while (m_particleList != 0)
|
||||
{
|
||||
SMFXParticleListNode* next = m_particleList->pNext;
|
||||
m_particleList->Destroy();
|
||||
m_particleList = next;
|
||||
}
|
||||
while (m_audioList != 0)
|
||||
{
|
||||
SMFXAudioListNode* next = m_audioList->pNext;
|
||||
m_audioList->Destroy();
|
||||
m_audioList = next;
|
||||
}
|
||||
while (m_decalList != 0)
|
||||
{
|
||||
SMFXDecalListNode* next = m_decalList->pNext;
|
||||
m_decalList->Destroy();
|
||||
m_decalList = next;
|
||||
}
|
||||
while (m_forceFeedbackList != 0)
|
||||
{
|
||||
SMFXForceFeedbackListNode* next = m_forceFeedbackList->pNext;
|
||||
m_forceFeedbackList->Destroy();
|
||||
m_forceFeedbackList = next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef uint16 TMFXEffectId;
|
||||
static const TMFXEffectId InvalidEffectId = 0;
|
||||
|
||||
struct SMFXCustomParamValue
|
||||
{
|
||||
float fValue;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IMaterialEffects
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IMaterialEffects(){}
|
||||
virtual void LoadFXLibraries() = 0;
|
||||
virtual void Reset(bool bCleanup) = 0;
|
||||
virtual void ClearDelayedEffects() = 0;
|
||||
virtual TMFXEffectId GetEffectIdByName(const char* libName, const char* effectName) = 0;
|
||||
virtual TMFXEffectId GetEffectId(int surfaceIndex1, int surfaceIndex2) = 0;
|
||||
virtual TMFXEffectId GetEffectId(const char* customName, int surfaceIndex2) = 0;
|
||||
virtual SMFXResourceListPtr GetResources(TMFXEffectId effectId) const = 0;
|
||||
virtual void PreLoadAssets() = 0;
|
||||
virtual bool ExecuteEffect(TMFXEffectId effectId, SMFXRunTimeEffectParams& runtimeParams) = 0;
|
||||
virtual int GetDefaultSurfaceIndex() = 0;
|
||||
virtual int GetDefaultCanopyIndex() = 0;
|
||||
|
||||
virtual bool PlayBreakageEffect(ISurfaceType* pSurfaceType, const char* breakageType, const SMFXBreakageParams& mfxBreakageParams) = 0;
|
||||
|
||||
virtual void SetCustomParameter(TMFXEffectId effectId, const char* customParameter, const SMFXCustomParamValue& customParameterValue) = 0;
|
||||
|
||||
virtual void CompleteInit() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_IMATERIALEFFECTS_H
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_INOTIFICATIONNETWORK_H
|
||||
#define CRYINCLUDE_CRYCOMMON_INOTIFICATIONNETWORK_H
|
||||
#pragma once
|
||||
|
||||
|
||||
// Constants
|
||||
|
||||
#define NN_CHANNEL_NAME_LENGTH_MAX 16
|
||||
|
||||
struct INotificationNetworkClient;
|
||||
|
||||
// User Interfaces
|
||||
|
||||
struct INotificationNetworkListener
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~INotificationNetworkListener(){}
|
||||
// Called upon receiving data from the Channel the Listener is binded to.
|
||||
virtual void OnNotificationNetworkReceive(const void* pBuffer, size_t length) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
struct INotificationNetworkConnectionCallback
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~INotificationNetworkConnectionCallback(){}
|
||||
virtual void OnConnect(INotificationNetworkClient* pClient, bool bSucceeded) = 0;
|
||||
virtual void OnDisconnected(INotificationNetworkClient* pClient) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
// Interfaces
|
||||
|
||||
struct INotificationNetworkClient
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~INotificationNetworkClient(){}
|
||||
virtual void Release() = 0;
|
||||
|
||||
// Binds a Listener to the given Notification Channel.
|
||||
// Each Listener can be binded only to one Channel, calling the method
|
||||
// again with an already added Listener and a different Channel will rebind it.
|
||||
// The Channel name cannot exceed NN_CHANNEL_NAME_LENGTH_MAX chars.
|
||||
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener) = 0;
|
||||
|
||||
// If it exist, removes the given Listener form the Notification Network.
|
||||
virtual bool ListenerRemove(INotificationNetworkListener* pListener) = 0;
|
||||
|
||||
// Sends arbitrary data to the Notification Network the Client is connected to.
|
||||
virtual bool Send(const char* channelName, const void* pBuffer, size_t length) = 0;
|
||||
|
||||
// Checks if the current client is connected.
|
||||
// Returns true if it is connected, false otherwise.
|
||||
virtual bool IsConnected() = 0;
|
||||
|
||||
// Checks if the connection attempt failed.
|
||||
// Returns true if it failed to connect by any reason (such as timeout).
|
||||
virtual bool IsFailedToConnect() const = 0;
|
||||
|
||||
// Start the connection request for this particular client.
|
||||
// Parameters:
|
||||
// address - Is the host name or ipv4 (for now) address string to which
|
||||
// we want to connect.
|
||||
// port - Is the TCP port to which we want to connect.
|
||||
// Remarks: Port 9432 is being used by the live preview already.
|
||||
virtual bool Connect(const char* address, uint16 port) = 0;
|
||||
|
||||
// Tries to register a callback listener object.
|
||||
// A callback listener object will receive events from the client element,
|
||||
// such as connection result information.
|
||||
// Parameters:
|
||||
// - pConnectionCallback - Is a pointer to an object implementing interface
|
||||
// INotificationNetworkConnectionCallback which will be called when
|
||||
// the events happen, such as connection, disconnection and failed attempt
|
||||
// to connect.
|
||||
// Return Value:
|
||||
// - It will return true if registered the callback object successfully.
|
||||
// - It will return false when there the callback object is already
|
||||
// registered.
|
||||
virtual bool RegisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback) = 0;
|
||||
|
||||
// Tries to unregister a callback listener object.
|
||||
// A callback listener object will receive events from the client element,
|
||||
// such as connection result information.
|
||||
// Parameters:
|
||||
// - pConnectionCallback - Is a pointer to an object implementing interface
|
||||
// INotificationNetworkConnectionCallback which will be called when
|
||||
// the events happen, such as connection, disconnection and failed attempt
|
||||
// to connect and that we want to unregister.
|
||||
// Return Value:
|
||||
// - It will return true if unregistered the callback object successfully.
|
||||
// - It will return false when no object matching the one requested is found
|
||||
// int the object.
|
||||
virtual bool UnregisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
struct INotificationNetwork
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~INotificationNetwork(){}
|
||||
|
||||
virtual void Release() = 0;
|
||||
|
||||
// Creates a disconnected client.
|
||||
virtual INotificationNetworkClient* CreateClient() = 0;
|
||||
|
||||
// Attempts to connect to the Notification Network at the given address,
|
||||
// returns a Client interface if communication is possible.
|
||||
virtual INotificationNetworkClient* Connect(const char* address, uint16 port) = 0;
|
||||
|
||||
// Returns the Connection count of the given Channel. If NULL is passed
|
||||
// instead of a valid Channel name the total count of all Connections is
|
||||
// returned.
|
||||
virtual size_t GetConnectionCount(const char* channelName = NULL) = 0;
|
||||
|
||||
// Has to be called from the main thread to process received notifications.
|
||||
virtual void Update() = 0;
|
||||
|
||||
// Binds a Listener to the given Notification Channel.
|
||||
// Each Listener can be binded only to one Channel, calling the method
|
||||
// again with an already added Listener and a different Channel will rebind it.
|
||||
// The Channel name cannot exceed NN_CHANNEL_NAME_LENGTH_MAX chars.
|
||||
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener) = 0;
|
||||
|
||||
// If it exist, removes the given Listener form the Notification Network.
|
||||
virtual bool ListenerRemove(INotificationNetworkListener* pListener) = 0;
|
||||
|
||||
// Sends arbitrary data to all the Connections listening to the given Channel.
|
||||
virtual uint32 Send(const char* channel, const void* pBuffer, size_t length) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_INOTIFICATIONNETWORK_H
|
||||
@@ -16,12 +16,12 @@
|
||||
#include "Cry_Geo.h"
|
||||
#include "Cry_Camera.h"
|
||||
#include "ITexture.h"
|
||||
#include <IFlares.h> // <> required for Interfuscator
|
||||
#include <IFuncVariable.h> // <> required for Interfuscator
|
||||
#include <IXml.h> // <> required for Interfuscator
|
||||
#include "smartptr.h"
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/std/containers/intrusive_slist.h>
|
||||
|
||||
#include "IResourceCompilerHelper.h" // for IResourceCompilerHelper::ERcCallResult
|
||||
|
||||
// forward declarations
|
||||
struct SRenderingPassInfo;
|
||||
struct SRTStack;
|
||||
@@ -95,7 +95,6 @@ struct IFFont;
|
||||
struct IFFont_RenderProxy;
|
||||
struct STextDrawContext;
|
||||
struct IRenderMesh;
|
||||
class IOpticsManager;
|
||||
struct ShadowFrustumMGPUCache;
|
||||
struct IAsyncTextureCompileListener;
|
||||
struct IClipVolume;
|
||||
@@ -955,25 +954,6 @@ protected:
|
||||
virtual ~ITextureStreamListener() {}
|
||||
};
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Listener for asynchronous texture compilation.
|
||||
// Connects the listener to the task-queue of pending compilation requests.
|
||||
enum ERcExitCode;
|
||||
struct IAsyncTextureCompileListener
|
||||
{
|
||||
public:
|
||||
virtual void OnCompilationStarted(const char* source, const char* target, int nPending) = 0;
|
||||
virtual void OnCompilationFinished(const char* source, const char* target, IResourceCompilerHelper::ERcCallResult nReturnCode) = 0;
|
||||
|
||||
virtual void OnCompilationQueueTriggered(int nPending) = 0;
|
||||
virtual void OnCompilationQueueDepleted() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IAsyncTextureCompileListener() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
enum eDolbyVisionMode
|
||||
{
|
||||
eDVM_Disabled,
|
||||
@@ -1869,8 +1849,6 @@ struct IRenderer
|
||||
virtual SDepthTexture* CreateDepthSurface(int nWidth, int nHeight, bool shaderResourceView = false) = 0;
|
||||
virtual void DestroyDepthSurface(SDepthTexture* pDepthSurf) = 0;
|
||||
|
||||
virtual IOpticsElementBase* CreateOptics(EFlareType type) const = 0;
|
||||
|
||||
// Note:
|
||||
// Used for pausing timer related stuff.
|
||||
// Example:
|
||||
|
||||
@@ -1,378 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include "IResourceCompilerHelper.h"
|
||||
|
||||
#include <AzCore/base.h>
|
||||
// DO NOT USE AZSTD.
|
||||
|
||||
#include <string> // std string used here.
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
// the following block is for _mkdir on windows and mkdir on other platforms.
|
||||
#if defined(_WIN32)
|
||||
# include <direct.h>
|
||||
#else
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace RCPathUtil
|
||||
{
|
||||
const char* GetExt(const char* filepath)
|
||||
{
|
||||
const char* str = filepath;
|
||||
size_t len = strlen(filepath);
|
||||
for (const char* p = str + len - 1; p >= str; --p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
// we've reached a path separator - it means there's no extension in this name
|
||||
return "";
|
||||
case '.':
|
||||
// there's an extension in this file name
|
||||
return p + 1;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* GetFile(const char* filepath)
|
||||
{
|
||||
const size_t len = strlen(filepath);
|
||||
for (const char* p = filepath + len - 1; p >= filepath; --p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
return p + 1;
|
||||
}
|
||||
}
|
||||
return filepath;
|
||||
}
|
||||
|
||||
|
||||
//! Replace extension for given file.
|
||||
std::string RemoveExtension(const char* filepath)
|
||||
{
|
||||
std::string filepathstr = filepath;
|
||||
const char* str = filepathstr.c_str();
|
||||
for (const char* p = str + filepathstr.length() - 1; p >= str; --p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
// we've reached a path separator - it means there's no extension in this name
|
||||
return filepathstr;
|
||||
case '.':
|
||||
// there's an extension in this file name
|
||||
filepathstr.erase(p - str);
|
||||
return filepathstr;
|
||||
}
|
||||
}
|
||||
// it seems the file name is a pure name, without path or extension
|
||||
return filepathstr;
|
||||
}
|
||||
|
||||
std::string ReplaceExtension(const char* filepath, const char* ext)
|
||||
{
|
||||
std::string str = filepath;
|
||||
if (ext != 0)
|
||||
{
|
||||
str = RemoveExtension(str.c_str());
|
||||
if (ext[0] != 0 && ext[0] != '.')
|
||||
{
|
||||
str += ".";
|
||||
}
|
||||
str += ext;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string GetPath(const char* filepath)
|
||||
{
|
||||
std::string filepathstr = filepath;
|
||||
const char* str = filepathstr.c_str();
|
||||
for (const char* p = str + filepathstr.length() - 1; p >= str; --p)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ':':
|
||||
case '/':
|
||||
case '\\':
|
||||
// we've reached a path separator - it means there's no extension in this name
|
||||
return filepathstr.substr(0, p - str);
|
||||
}
|
||||
}
|
||||
// it seems the file name is a pure name, without path
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool IsRelativePath(const char* p)
|
||||
{
|
||||
if (!p || !p[0])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return p[0] != '/' && p[0] != '\\' && !strchr(p, ':');
|
||||
}
|
||||
}
|
||||
|
||||
const char* IResourceCompilerHelper::SourceImageFormatExts[NUM_SOURCE_IMAGE_TYPE] = { "tif", "bmp", "gif", "jpg", "jpeg", "jpe", "tga", "png" };
|
||||
const char* IResourceCompilerHelper::SourceImageFormatExtsWithDot[NUM_SOURCE_IMAGE_TYPE] = { ".tif", ".bmp", ".gif", ".jpg", ".jpeg", ".jpe", ".tga", ".png" };
|
||||
const char* IResourceCompilerHelper::EngineImageFormatExts[NUM_ENGINE_IMAGE_TYPE] = { "dds" };
|
||||
const char* IResourceCompilerHelper::EngineImageFormatExtsWithDot[NUM_ENGINE_IMAGE_TYPE] = { ".dds" };
|
||||
|
||||
|
||||
IResourceCompilerHelper::ERcCallResult IResourceCompilerHelper::ConvertResourceCompilerExitCodeToResultCode(int exitCode)
|
||||
{
|
||||
switch (exitCode)
|
||||
{
|
||||
case eRcExitCode_Success:
|
||||
case eRcExitCode_UserFixing:
|
||||
return eRcCallResult_success;
|
||||
|
||||
case eRcExitCode_Error:
|
||||
return eRcCallResult_error;
|
||||
|
||||
case eRcExitCode_FatalError:
|
||||
return eRcCallResult_error;
|
||||
case eRcExitCode_Crash:
|
||||
return eRcCallResult_crash;
|
||||
}
|
||||
return eRcCallResult_error;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* IResourceCompilerHelper::GetCallResultDescription(IResourceCompilerHelper::ERcCallResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case eRcCallResult_success:
|
||||
return "Success.";
|
||||
case eRcCallResult_notFound:
|
||||
return "ResourceCompiler executable was not found.";
|
||||
case eRcCallResult_error:
|
||||
return "ResourceCompiler exited with an error.";
|
||||
case eRcCallResult_crash:
|
||||
return "ResourceCompiler crashed! Please report this. Include source asset and this log in the report.";
|
||||
default:
|
||||
return "Unexpected failure in ResultCompilerHelper.";
|
||||
}
|
||||
}
|
||||
|
||||
// Arguments:
|
||||
// szFilePath - could be source or destination filename
|
||||
void IResourceCompilerHelper::GetOutputFilename(const char* szFilePath, char* buffer, size_t bufferSizeInBytes)
|
||||
{
|
||||
if (IResourceCompilerHelper::IsSourceImageFormatSupported(szFilePath))
|
||||
{
|
||||
std::string newString = RCPathUtil::ReplaceExtension(szFilePath, "dds");
|
||||
azstrncpy(buffer, bufferSizeInBytes, newString.c_str(), bufferSizeInBytes - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
azstrncpy(buffer, bufferSizeInBytes, szFilePath, bufferSizeInBytes - 1);
|
||||
}
|
||||
|
||||
IResourceCompilerHelper::ERcCallResult IResourceCompilerHelper::InvokeResourceCompiler(const char* szSrcFilePath, const char* szDstFilePath, const bool bUserDialog)
|
||||
{
|
||||
|
||||
const char* szDstFileName = RCPathUtil::GetFile(szDstFilePath);
|
||||
std::string pathOnly = RCPathUtil::GetPath(szDstFilePath);
|
||||
const int maxStringSize = 512;
|
||||
char szRemoteCmdLine[maxStringSize] = { 0 };
|
||||
char szFullPathToSourceFile[maxStringSize] = { 0 };
|
||||
|
||||
if (RCPathUtil::IsRelativePath(szSrcFilePath))
|
||||
{
|
||||
azstrcat(szFullPathToSourceFile, maxStringSize, "#ENGINEROOT#");
|
||||
azstrcat(szFullPathToSourceFile, maxStringSize, "\\");
|
||||
}
|
||||
azstrcat(szFullPathToSourceFile, maxStringSize, szSrcFilePath);
|
||||
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, " /targetroot=\"");
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, pathOnly.c_str());
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, "\"");
|
||||
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, " /overwritefilename=\"");
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, szDstFileName);
|
||||
azstrcat(szRemoteCmdLine, maxStringSize, "\"");
|
||||
|
||||
return CallResourceCompiler(szFullPathToSourceFile, szRemoteCmdLine, nullptr, true, false, !bUserDialog);
|
||||
}
|
||||
|
||||
unsigned int IResourceCompilerHelper::GetNumSourceImageFormats()
|
||||
{
|
||||
return NUM_SOURCE_IMAGE_TYPE;
|
||||
}
|
||||
|
||||
const char* IResourceCompilerHelper::GetSourceImageFormat(unsigned int index, bool bWithDot)
|
||||
{
|
||||
if (index >= GetNumSourceImageFormats())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (bWithDot)
|
||||
{
|
||||
return SourceImageFormatExtsWithDot[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return SourceImageFormatExts[index];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int IResourceCompilerHelper::GetNumEngineImageFormats()
|
||||
{
|
||||
return NUM_ENGINE_IMAGE_TYPE;
|
||||
}
|
||||
|
||||
const char* IResourceCompilerHelper::GetEngineImageFormat(unsigned int index, bool bWithDot)
|
||||
{
|
||||
if (index >= GetNumEngineImageFormats())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (bWithDot)
|
||||
{
|
||||
return EngineImageFormatExtsWithDot[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return EngineImageFormatExts[index];
|
||||
}
|
||||
}
|
||||
|
||||
bool IResourceCompilerHelper::IsSourceImageFormatSupported(const char* szFileNameOrExtension)
|
||||
{
|
||||
if (!szFileNameOrExtension) // if this hits, might want to check the call site
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//check the string length
|
||||
size_t len = strlen(szFileNameOrExtension);
|
||||
if (len < 3)//no point in going on if the smallest valid ext is 3 characters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//find the ext by starting at the last character and moving backward to first he first '.'
|
||||
const char* szExtension = nullptr;
|
||||
size_t cur = len - 1;
|
||||
while (cur && !szExtension)
|
||||
{
|
||||
if (szFileNameOrExtension[cur] == '.')
|
||||
{
|
||||
szExtension = &szFileNameOrExtension[cur];
|
||||
}
|
||||
cur--;
|
||||
}
|
||||
if (len - cur < 3)//no point in going on if the smallest valid ext is 3 characters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if we didn't find a '.' it could still be valid, they may not have
|
||||
//passed it in. i.e. "dds" instead of ".dds" which is still valid
|
||||
if (!szExtension)
|
||||
{
|
||||
//with no '.' the largest ext is currently 4 characters
|
||||
//no point in going on if it is larger
|
||||
if (len > 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
szExtension = szFileNameOrExtension;
|
||||
}
|
||||
|
||||
//loop over all the valid exts and see if it is one of them
|
||||
for (unsigned int i = 0; i < GetNumSourceImageFormats(); ++i)
|
||||
{
|
||||
if (!azstricmp(szExtension, GetSourceImageFormat(i, szExtension[0] == '.')))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IResourceCompilerHelper::IsGameImageFormatSupported(const char* szFileNameOrExtension)
|
||||
{
|
||||
if (!szFileNameOrExtension) // if this hits, might want to check the call site
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//check the string length
|
||||
size_t len = strlen(szFileNameOrExtension);
|
||||
if (len < 3)//no point in going on if the smallest valid ext is 3 characters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//find the ext by starting at the last character and moving backward to first he first '.'
|
||||
const char* szExtension = nullptr;
|
||||
size_t cur = len - 1;
|
||||
while (cur && !szExtension)
|
||||
{
|
||||
if (szFileNameOrExtension[cur] == '.')
|
||||
{
|
||||
szExtension = &szFileNameOrExtension[cur];
|
||||
}
|
||||
cur--;
|
||||
}
|
||||
if (len - cur < 3)//no point in going on if the smallest valid ext is 3 characters
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if we didn't find a '.' it could still be valid, they may not have
|
||||
//passed it in. i.e. "dds" instead of ".dds" which is still valid
|
||||
if (!szExtension)
|
||||
{
|
||||
//with no '.' the largest ext is currently 4 characters
|
||||
//no point in going on if it is larger
|
||||
if (len > 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
szExtension = szFileNameOrExtension;
|
||||
}
|
||||
|
||||
//loop over all the valid exts and see if it is one of them
|
||||
for (unsigned int i = 0; i < GetNumEngineImageFormats(); ++i)
|
||||
{
|
||||
if (!azstricmp(szExtension, GetEngineImageFormat(i, szExtension[0] == '.')))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_IRESOURCECOMPILERHELPER_H
|
||||
#define CRYINCLUDE_CRYCOMMON_IRESOURCECOMPILERHELPER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// DO NOT USE AZSTD
|
||||
|
||||
#include <string>
|
||||
|
||||
// IResourceCompilerHelper exists to define an interface that allows
|
||||
// remote or local compilation of resources through the "resource Compiler" executable
|
||||
// in most tools it will be implemented as a local execution. However, in the engine
|
||||
// it will be substituted for a remote RC invocation through the Asset Processor if
|
||||
// that system is enabled (via con var and define)
|
||||
|
||||
// DO NOT USE CRYSTRING or CRY ALLOCATORS HERE. This is used in maya plugins, that kind of thing.
|
||||
// the following path utils are special versions of these functions which take pains
|
||||
// to not use crystring.
|
||||
// the functions in this interface must be cross platform.
|
||||
namespace RCPathUtil
|
||||
{
|
||||
// given a full path, return the extension (it will be a pointer into the existing string)
|
||||
const char* GetExt(const char* filepath);
|
||||
|
||||
// given a full path, return the file only (it will be a pointer into the existing string)
|
||||
const char* GetFile(const char* filepath);
|
||||
|
||||
// given a filepath, get only the path.
|
||||
std::string GetPath(const char* filepath);
|
||||
std::string ReplaceExtension(const char* filepath, const char* ext);
|
||||
bool IsRelativePath(const char* p);
|
||||
}
|
||||
|
||||
class IResourceCompilerListener;
|
||||
|
||||
enum ERcExitCode
|
||||
{
|
||||
eRcExitCode_Success = 0, // must be 0
|
||||
eRcExitCode_Error = 1,
|
||||
eRcExitCode_FatalError = 100,
|
||||
eRcExitCode_Crash = 101,
|
||||
eRcExitCode_UserFixing = 200,
|
||||
eRcExitCode_Pending = 666,
|
||||
};
|
||||
|
||||
/// A pure virtual interface to the RC Helper system
|
||||
/// the RC helper system allows you to make requests to a remote process in order to process
|
||||
/// an asset for you.
|
||||
class IResourceCompilerHelper
|
||||
{
|
||||
public:
|
||||
virtual ~IResourceCompilerHelper() {}
|
||||
|
||||
// defines the result of a call via this API to the RC system
|
||||
enum ERcCallResult
|
||||
{
|
||||
eRcCallResult_success, // everything is OK
|
||||
eRcCallResult_notFound, // the RC executable is not found
|
||||
eRcCallResult_error, // the RC executable returned an error
|
||||
eRcCallResult_crash, // the RC executable did not finish
|
||||
};
|
||||
|
||||
//
|
||||
// Arguments:
|
||||
// szFileName null terminated ABSOLUTE file path or 0 can be used to test for rc.exe existence
|
||||
// relative path needs to be relative to rc_plugins directory
|
||||
// szAdditionalSettings - 0 or e.g. "/refresh" or "/refresh /xyz=56"
|
||||
//
|
||||
// this is a SYNCHRONOUS, BLOCKING call and will return once the process is complete
|
||||
virtual ERcCallResult CallResourceCompiler(
|
||||
const char* szFileName = 0,
|
||||
const char* szAdditionalSettings = 0,
|
||||
IResourceCompilerListener* listener = 0,
|
||||
bool bMayShowWindow = true,
|
||||
bool bSilent = false,
|
||||
bool bNoUserDialog = false,
|
||||
const wchar_t* szWorkingDirectory = 0,
|
||||
const wchar_t* szRootPath = 0) = 0;
|
||||
|
||||
// InvokeResourceCompiler - a utility that calls the above CallResourceCompiler function
|
||||
// but generates appropriate settings so you don't have to specify each option.
|
||||
// This is a BLOCKING call
|
||||
// the srcFile can be relative to the project root or an absolute path
|
||||
// the dstFilePath MUST be relative to the same folder as the Src File path
|
||||
// this will output dstFilePath in the same folder as srcFile.
|
||||
virtual ERcCallResult InvokeResourceCompiler(const char* szSrcFilePath, const char* szDstFilePath, const bool bUserDialog);
|
||||
|
||||
// --------------------- utility functions ---------------------------------
|
||||
|
||||
// given a RC.EXE process exit code like 101, convert it to the above ERcCallResult
|
||||
ERcCallResult ConvertResourceCompilerExitCodeToResultCode(int exitCode);
|
||||
|
||||
// given a ERcCallResult, convert it to a simple english string for debugging.
|
||||
static const char* GetCallResultDescription(ERcCallResult result);
|
||||
|
||||
// given a filename such as "blah.tif" convert it to the appropriate output name "blah.dds" for example
|
||||
static void GetOutputFilename(const char* szFilePath, char* buffer, size_t bufferSizeInBytes);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum SourceImageTypes
|
||||
{
|
||||
SOURCE_IMAGE_TYPE_TIF,
|
||||
SOURCE_IMAGE_TYPE_BMP,
|
||||
SOURCE_IMAGE_TYPE_GIF,
|
||||
SOURCE_IMAGE_TYPE_JPG,
|
||||
SOURCE_IMAGE_TYPE_JPEG,
|
||||
SOURCE_IMAGE_TYPE_JPE,
|
||||
SOURCE_IMAGE_TYPE_TGA,
|
||||
SOURCE_IMAGE_TYPE_PNG,
|
||||
NUM_SOURCE_IMAGE_TYPE
|
||||
};
|
||||
|
||||
enum EngineImageTypes
|
||||
{
|
||||
ENGINE_IMAGE_TYPE_DDS,
|
||||
NUM_ENGINE_IMAGE_TYPE
|
||||
};
|
||||
|
||||
private:
|
||||
static const char* SourceImageFormatExts[NUM_SOURCE_IMAGE_TYPE];
|
||||
static const char* SourceImageFormatExtsWithDot[NUM_SOURCE_IMAGE_TYPE];
|
||||
static const char* EngineImageFormatExts[NUM_ENGINE_IMAGE_TYPE];
|
||||
static const char* EngineImageFormatExtsWithDot[NUM_ENGINE_IMAGE_TYPE];
|
||||
|
||||
public:
|
||||
static unsigned int GetNumSourceImageFormats();
|
||||
static const char* GetSourceImageFormat(unsigned int index, bool bWithDot);
|
||||
|
||||
static unsigned int GetNumEngineImageFormats();
|
||||
static const char* GetEngineImageFormat(unsigned int index, bool bWithDot);
|
||||
|
||||
static bool IsSourceImageFormatSupported(const char* szExtension);
|
||||
static bool IsGameImageFormatSupported(const char* szExtension);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Listener for synchronous resource-compilation.
|
||||
// Connects the listener to the output of the RC process.
|
||||
class IResourceCompilerListener
|
||||
{
|
||||
public:
|
||||
// FbxImportDialog relies on this enum being in the order from most verbose to least verbose
|
||||
enum MessageSeverity
|
||||
{
|
||||
MessageSeverity_Debug = 0,
|
||||
MessageSeverity_Info,
|
||||
MessageSeverity_Warning,
|
||||
MessageSeverity_Error
|
||||
};
|
||||
|
||||
virtual void OnRCMessage(MessageSeverity /*severity*/, const char* /*text*/) {}
|
||||
virtual ~IResourceCompilerListener() {}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_IRESOURCECOMPILERHELPER_H
|
||||
@@ -24,7 +24,9 @@
|
||||
#endif
|
||||
|
||||
#include "smartptr.h"
|
||||
#include <IFlares.h> // <> required for Interfuscator
|
||||
#include <IFuncVariable.h> // <> required for Interfuscator
|
||||
#include <IXml.h> // <> required for Interfuscator
|
||||
#include "smartptr.h"
|
||||
#include "VertexFormats.h"
|
||||
#include <Vertex.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
@@ -2828,7 +2830,6 @@ struct SRenderLight
|
||||
m_ObjMatrix.SetIdentity();
|
||||
m_BaseObjMatrix.SetIdentity();
|
||||
m_sName = "";
|
||||
m_pSoftOccQuery = NULL;
|
||||
m_pLightAnim = NULL;
|
||||
m_fAreaWidth = 1;
|
||||
m_fAreaHeight = 1;
|
||||
@@ -2884,11 +2885,6 @@ struct SRenderLight
|
||||
return m_pLightImage ? m_pLightImage : NULL;
|
||||
}
|
||||
|
||||
IOpticsElementBase* GetLensOpticsElement() const
|
||||
{
|
||||
return m_pLensOpticsElement;
|
||||
}
|
||||
|
||||
void SetOpticsParams(const SOpticsInstanceParameters& params)
|
||||
{
|
||||
m_opticsParams = params;
|
||||
@@ -2899,24 +2895,6 @@ struct SRenderLight
|
||||
return m_opticsParams;
|
||||
}
|
||||
|
||||
void SetLensOpticsElement(IOpticsElementBase* pOptics)
|
||||
{
|
||||
if (m_pLensOpticsElement == pOptics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (pOptics && pOptics->GetType() != eFT_Root)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SAFE_RELEASE(m_pLensOpticsElement);
|
||||
m_pLensOpticsElement = pOptics;
|
||||
if (m_pLensOpticsElement)
|
||||
{
|
||||
m_pLensOpticsElement->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const { /*LATER*/}
|
||||
|
||||
void AcquireResources()
|
||||
@@ -2937,14 +2915,6 @@ struct SRenderLight
|
||||
{
|
||||
m_pSpecularCubemap->AddRef();
|
||||
}
|
||||
if (m_pLensOpticsElement)
|
||||
{
|
||||
m_pLensOpticsElement->AddRef();
|
||||
}
|
||||
if (m_pSoftOccQuery)
|
||||
{
|
||||
m_pSoftOccQuery->AddRef();
|
||||
}
|
||||
if (m_pLightAnim)
|
||||
{
|
||||
m_pLightAnim->AddRef();
|
||||
@@ -2961,8 +2931,6 @@ struct SRenderLight
|
||||
SAFE_RELEASE(m_pLightImage);
|
||||
SAFE_RELEASE(m_pDiffuseCubemap);
|
||||
SAFE_RELEASE(m_pSpecularCubemap);
|
||||
SAFE_RELEASE(m_pLensOpticsElement);
|
||||
SAFE_RELEASE(m_pSoftOccQuery);
|
||||
SAFE_RELEASE(m_pLightAnim);
|
||||
SAFE_RELEASE(m_pLightAttenMap);
|
||||
}
|
||||
@@ -3046,8 +3014,6 @@ struct SRenderLight
|
||||
const char* m_sName; // Optional name of the light source.
|
||||
SShaderItem m_Shader; // Shader item
|
||||
CRenderObject* m_pObject[MAX_RECURSION_LEVELS]; // Object for light coronas and light flares.
|
||||
IOpticsElementBase* m_pLensOpticsElement; // Optics element for this shader instance
|
||||
ISoftOcclusionQuery* m_pSoftOccQuery;
|
||||
ILightAnimWrapper* m_pLightAnim;
|
||||
|
||||
Matrix34 m_BaseObjMatrix;
|
||||
@@ -3146,9 +3112,7 @@ public:
|
||||
m_fShadowSlopeBias = dl.m_fShadowSlopeBias;
|
||||
m_fShadowResolutionScale = dl.m_fShadowResolutionScale;
|
||||
m_fHDRDynamic = dl.m_fHDRDynamic;
|
||||
m_pLensOpticsElement = dl.m_pLensOpticsElement;
|
||||
m_LensOpticsFrustumAngle = dl.m_LensOpticsFrustumAngle;
|
||||
m_pSoftOccQuery = dl.m_pSoftOccQuery;
|
||||
m_fLightFrustumAngle = dl.m_fLightFrustumAngle;
|
||||
m_fProjectorNearPlane = dl.m_fProjectorNearPlane;
|
||||
m_Flags = dl.m_Flags;
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Interface to manage SoftCode module loading and patching
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H
|
||||
#pragma once
|
||||
|
||||
|
||||
// Provides the generic interface for exchanging member values between SoftCode modules,
|
||||
struct IExchangeValue
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IExchangeValue() {}
|
||||
|
||||
// Allocates a new IExchangeValue with the underlying type
|
||||
virtual IExchangeValue* Clone() const = 0;
|
||||
// Returns the size of the underlying type (to check compatibility)
|
||||
virtual size_t GetSizeOf() const = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ExchangeValue
|
||||
: public IExchangeValue
|
||||
{
|
||||
ExchangeValue(T& value)
|
||||
: m_value(value)
|
||||
{}
|
||||
|
||||
virtual IExchangeValue* Clone() const { return new ExchangeValue(*this); }
|
||||
virtual size_t GetSizeOf() const { return sizeof(m_value); }
|
||||
|
||||
T m_value;
|
||||
};
|
||||
|
||||
template <typename T, size_t S>
|
||||
struct ExchangeArray
|
||||
: public IExchangeValue
|
||||
{
|
||||
ExchangeArray(T* pArr)
|
||||
{
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
{
|
||||
m_array[i] = pArr[i];
|
||||
}
|
||||
}
|
||||
|
||||
virtual IExchangeValue* Clone() const { return new ExchangeArray(*this); }
|
||||
virtual size_t GetSizeOf() const { return sizeof(m_array); }
|
||||
|
||||
T m_array[S];
|
||||
};
|
||||
|
||||
/*
|
||||
This is a non-intrusive support function for types where default construction does no initialization.
|
||||
SoftCoding relies on default construction to initialize object state correctly.
|
||||
For most types this works as expected but for some types (typically things like vectors or matrices)
|
||||
default initialization would be too costly and is therefore not implemented.
|
||||
This function allows a specialized implementation to be used for such types that will perform
|
||||
initialization on the newly constructed instance. For example:
|
||||
|
||||
inline void DefaultInitialize(Matrix34& matrix)
|
||||
{
|
||||
matrix.SetIdentity();
|
||||
}
|
||||
*/
|
||||
template <typename T>
|
||||
void DefaultInitialize(T& t)
|
||||
{
|
||||
t = T();
|
||||
}
|
||||
|
||||
// Vector support
|
||||
template<class F>
|
||||
struct Vec2_tpl;
|
||||
template<typename T>
|
||||
struct Vec3_tpl;
|
||||
template <class F>
|
||||
void DefaultInitialize(Vec2_tpl<F>& vec) { vec.zero(); }
|
||||
template <typename T>
|
||||
void DefaultInitialize(Vec3_tpl<T>& vec) { vec.zero(); }
|
||||
|
||||
// Matrix support
|
||||
template<typename F>
|
||||
struct Matrix33_tpl;
|
||||
template<typename F>
|
||||
struct Matrix34_tpl;
|
||||
template<typename F>
|
||||
struct Matrix44_tpl;
|
||||
|
||||
template <typename F>
|
||||
void DefaultInitialize(Matrix33_tpl<F>& matrix) { matrix.SetIdentity(); }
|
||||
template <typename F>
|
||||
void DefaultInitialize(Matrix34_tpl<F>& matrix) { matrix.SetIdentity(); }
|
||||
template <typename F>
|
||||
void DefaultInitialize(Matrix44_tpl<F>& matrix) { matrix.SetIdentity(); }
|
||||
|
||||
// Quat support
|
||||
template <typename F>
|
||||
struct Quat_tpl;
|
||||
template <typename F>
|
||||
void DefaultInitialize(Quat_tpl<F>& quat) { quat.SetIdentity(); }
|
||||
|
||||
// Interface for performing an exchange of instance data
|
||||
struct IExchanger
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IExchanger() {}
|
||||
|
||||
// True if data is being read from instance members
|
||||
virtual bool IsLoading() const = 0;
|
||||
|
||||
virtual size_t InstanceCount() const = 0;
|
||||
|
||||
virtual bool BeginInstance(void* pInstance) = 0;
|
||||
virtual bool SetValue(const char* name, IExchangeValue& value) = 0;
|
||||
virtual IExchangeValue* GetValue(const char* name, void* pTarget, size_t targetSize) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
template <typename T>
|
||||
void Visit(const char* name, T& instance);
|
||||
|
||||
template <typename T, size_t S>
|
||||
void Visit(const char* name, T (&arr)[S]);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void IExchanger::Visit(const char* name, T& value)
|
||||
{
|
||||
if (IsLoading())
|
||||
{
|
||||
IExchangeValue* pValue = GetValue(name, &value, sizeof(value));
|
||||
if (pValue)
|
||||
{
|
||||
ExchangeValue<T>* pTypedValue = static_cast<ExchangeValue<T>*>(pValue);
|
||||
value = pTypedValue->m_value;
|
||||
}
|
||||
}
|
||||
else // Saving
|
||||
{
|
||||
// If this member is stored
|
||||
if (SetValue(name, ExchangeValue<T>(value)))
|
||||
{
|
||||
// Set the original value to the default state (to allow safe destruction)
|
||||
DefaultInitialize(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, size_t S>
|
||||
void IExchanger::Visit(const char* name, T (&arr)[S])
|
||||
{
|
||||
if (IsLoading())
|
||||
{
|
||||
IExchangeValue* pValue = GetValue(name, &arr, sizeof(arr));
|
||||
if (pValue)
|
||||
{
|
||||
ExchangeArray<T, S>* pTypedArray = static_cast<ExchangeArray<T, S>*>(pValue);
|
||||
// TODO: Accommodate array resizing? Complex however...
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
{
|
||||
arr[i] = pTypedArray->m_array[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Saving
|
||||
{
|
||||
// If this member is stored
|
||||
if (SetValue(name, ExchangeArray<T, S>(arr)))
|
||||
{
|
||||
T defaultValue;
|
||||
DefaultInitialize(defaultValue);
|
||||
|
||||
// Set the original value to the default value (to allow safe destruction)
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
{
|
||||
arr[i] = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InstanceTracker;
|
||||
|
||||
struct ITypeRegistrar
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ITypeRegistrar() {}
|
||||
|
||||
virtual const char* GetName() const = 0;
|
||||
|
||||
// Creates an instance of the type
|
||||
virtual void* CreateInstance() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
#ifdef SOFTCODE_ENABLED
|
||||
// How many active instances exist of this type?
|
||||
virtual size_t InstanceCount() const = 0;
|
||||
// Used to remove a tracked instance from the Registrar
|
||||
virtual void RemoveInstance(InstanceTracker* pTracker) = 0;
|
||||
// Exchanges the instance state with the given exchanger data set
|
||||
virtual bool ExchangeInstances(IExchanger& exchanger) = 0;
|
||||
// Destroys all tracked instances of this type
|
||||
virtual bool DestroyInstances() = 0;
|
||||
// Returns true if pInstance is of this type (linear search)
|
||||
virtual bool HasInstance(void* pInstance) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ITypeLibrary
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ITypeLibrary() {}
|
||||
|
||||
virtual const char* GetName() = 0;
|
||||
virtual void* CreateInstanceVoid(const char* typeName) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
#ifdef SOFTCODE_ENABLED
|
||||
virtual void SetOverride(ITypeLibrary* pOverrideLib) = 0;
|
||||
|
||||
// Fills in the supplied type list if large enough, and sets count to number of types
|
||||
virtual size_t GetTypes(ITypeRegistrar** ppRegistrar, size_t& count) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ISoftCodeListener
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ISoftCodeListener() {}
|
||||
|
||||
// Called when an instance is replaced to allow managing systems to fixup pointers
|
||||
virtual void InstanceReplaced(void* pOldInstance, void* pNewInstance) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
/// Interface for ...
|
||||
struct ISoftCodeMgr
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ISoftCodeMgr() {}
|
||||
|
||||
// Used to register built-in libraries on first use
|
||||
virtual void RegisterLibrary(ITypeLibrary* pLib) = 0;
|
||||
|
||||
// Loads any new SoftCode modules
|
||||
virtual void LoadNewModules() = 0;
|
||||
|
||||
virtual void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName) = 0;
|
||||
virtual void RemoveListener(const char* libraryName, ISoftCodeListener* pListener) = 0;
|
||||
|
||||
// To be called regularly to poll for library updates
|
||||
virtual void PollForNewModules() = 0;
|
||||
|
||||
// Stops thread execution until a new SoftCode instance is available
|
||||
virtual void* WaitForUpdate(void* pInstance) = 0;
|
||||
|
||||
/// Frees this instance from memory
|
||||
//virtual void Release() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ISOFTCODEMGR_H
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#include <list>
|
||||
#include "smartptr.h"
|
||||
#include <IThreadTask.h> // <> required for Interfuscator
|
||||
#include "CryThread.h"
|
||||
|
||||
#include "IStreamEngineDefs.h"
|
||||
|
||||
@@ -49,19 +49,15 @@
|
||||
#include <ILog.h> // <> required for Interfuscator
|
||||
#include "CryVersion.h"
|
||||
#include "smartptr.h"
|
||||
#include <ISystemScheduler.h> // <> required for Interfuscator
|
||||
#include <memory> // shared_ptr
|
||||
#include <CrySystemBus.h>
|
||||
|
||||
struct ISystem;
|
||||
struct ILog;
|
||||
struct IProfileLogSystem;
|
||||
namespace AZ::IO
|
||||
{
|
||||
struct IArchive;
|
||||
}
|
||||
struct IKeyboard;
|
||||
struct IMouse;
|
||||
struct IConsole;
|
||||
struct IRemoteConsole;
|
||||
struct IRenderer;
|
||||
@@ -79,29 +75,21 @@ struct SFileVersion;
|
||||
struct INameTable;
|
||||
struct ILevelSystem;
|
||||
struct IViewSystem;
|
||||
struct IMaterialEffects;
|
||||
class IOpticsManager;
|
||||
class ICrySizer;
|
||||
class IXMLBinarySerializer;
|
||||
struct IReadWriteXMLSink;
|
||||
struct IThreadTaskManager;
|
||||
struct IResourceManager;
|
||||
struct ITextModeConsole;
|
||||
struct IAVI_Reader;
|
||||
class CPNoise3;
|
||||
struct IVisualLog;
|
||||
struct ILocalizationManager;
|
||||
struct ISoftCodeMgr;
|
||||
struct IZLibCompressor;
|
||||
struct IZLibDecompressor;
|
||||
struct ILZ4Decompressor;
|
||||
class IZStdDecompressor;
|
||||
struct IOutputPrintSink;
|
||||
struct IThreadManager;
|
||||
struct IWindowMessageHandler;
|
||||
struct IImageHandler;
|
||||
class IResourceCompilerHelper;
|
||||
class ILmbrAWS;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -111,12 +99,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
class IResourceCompilerHelper;
|
||||
|
||||
namespace Serialization {
|
||||
struct IArchiveHost;
|
||||
}
|
||||
|
||||
typedef void* WIN_HWND;
|
||||
|
||||
class CCamera;
|
||||
@@ -124,39 +106,13 @@ struct CLoadingTimeProfiler;
|
||||
|
||||
class ICmdLine;
|
||||
|
||||
struct INotificationNetwork;
|
||||
class ILyShine;
|
||||
|
||||
namespace JobManager {
|
||||
struct IJobManager;
|
||||
}
|
||||
|
||||
#define PROC_MENU 1
|
||||
#define PROC_3DENGINE 2
|
||||
|
||||
// Summary:
|
||||
// IDs for script userdata typing.
|
||||
// Remarks:
|
||||
// Maybe they should be moved into the game.dll .
|
||||
//##@{
|
||||
#define USER_DATA_SOUND 1
|
||||
#define USER_DATA_TEXTURE 2
|
||||
#define USER_DATA_OBJECT 3
|
||||
#define USER_DATA_LIGHT 4
|
||||
#define USER_DATA_BONEHANDLER 5
|
||||
#define USER_DATA_POINTER 6
|
||||
//##@}
|
||||
|
||||
enum ESystemUpdateFlags
|
||||
{
|
||||
ESYSUPDATE_IGNORE_PHYSICS = 0x0002,
|
||||
// Summary:
|
||||
// Special update mode for editor.
|
||||
ESYSUPDATE_EDITOR = 0x0004,
|
||||
ESYSUPDATE_MULTIPLAYER = 0x0008,
|
||||
ESYSUPDATE_EDITOR_AI_PHYSICS = 0x0010,
|
||||
ESYSUPDATE_EDITOR_ONLY = 0x0020,
|
||||
ESYSUPDATE_UPDATE_VIEW_ONLY = 0x0040
|
||||
ESYSUPDATE_EDITOR = 0x0004
|
||||
};
|
||||
|
||||
// Description:
|
||||
@@ -189,29 +145,6 @@ enum ESystemConfigPlatform
|
||||
END_CONFIG_PLATFORM_ENUM, // MUST BE LAST VALUE. USED FOR ERROR CHECKING.
|
||||
};
|
||||
|
||||
enum ESubsystem
|
||||
{
|
||||
ESubsys_3DEngine = 0,
|
||||
ESubsys_AI = 1,
|
||||
ESubsys_Physics = 2,
|
||||
ESubsys_Renderer = 3,
|
||||
ESubsys_Script = 4
|
||||
};
|
||||
|
||||
// Summary:
|
||||
// Collates cycles taken per update.
|
||||
struct sUpdateTimes
|
||||
{
|
||||
uint32 PhysYields;
|
||||
uint64 SysUpdateTime;
|
||||
uint64 PhysStepTime;
|
||||
uint64 RenderTime;
|
||||
//extended yimes info
|
||||
uint64 physWaitTime;
|
||||
uint64 streamingWaitTime;
|
||||
uint64 animationWaitTime;
|
||||
};
|
||||
|
||||
enum ESystemGlobalState
|
||||
{
|
||||
ESYSTEM_GLOBAL_STATE_UNKNOWN,
|
||||
@@ -568,33 +501,6 @@ struct IErrorObserver
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
enum ESystemProtectedFunctions
|
||||
{
|
||||
eProtectedFunc_Save = 0,
|
||||
eProtectedFunc_Load = 1,
|
||||
eProtectedFuncsLast = 10,
|
||||
};
|
||||
|
||||
struct SCvarsDefault
|
||||
{
|
||||
SCvarsDefault()
|
||||
{
|
||||
sz_r_DriverDef = NULL;
|
||||
}
|
||||
|
||||
const char* sz_r_DriverDef;
|
||||
};
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
struct ICVarsWhitelist
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ICVarsWhitelist() {};
|
||||
virtual bool IsWhiteListed(const string& command, bool silent) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION ISYSTEM_H_SECTION_3
|
||||
#include AZ_RESTRICTED_FILE(ISystem_h)
|
||||
@@ -616,9 +522,6 @@ struct SSystemInitParams
|
||||
{
|
||||
void* hInstance; //
|
||||
void* hWnd; //
|
||||
void* hWndForInputSystem; // the HWND for the input devices, distinct from the hWnd, which the rendering system overrides anyways
|
||||
|
||||
bool remoteResourceCompiler;
|
||||
|
||||
ILog* pLog; // You can specify your own ILog to be used by System.
|
||||
ILogCallback* pLogCallback; // You can specify your own ILogCallback to be added on log creation (used by Editor).
|
||||
@@ -633,33 +536,14 @@ struct SSystemInitParams
|
||||
bool bPreview; // When running in Preview mode (Minimal initialization).
|
||||
bool bTestMode; // When running in Automated testing mode.
|
||||
bool bDedicatedServer; // When running a dedicated server.
|
||||
bool bExecuteCommandLine; // can be switched of to suppress the feature or do it later during the initialization.
|
||||
bool bSkipFont; // Don't load CryFont.dll
|
||||
bool bSkipConsole; // Don't create console
|
||||
bool bSkipNetwork; // Don't create Network
|
||||
bool bSkipWebsocketServer; // Don't create the WebSocket server
|
||||
bool bMinimal; // Don't load banks
|
||||
bool bTesting; // CryUnit
|
||||
bool bNoRandom; //use fixed generator init/seed
|
||||
bool bUnattendedMode; // When running as part of a build on build-machines: Prevent popping up of any dialog
|
||||
bool bSkipMovie; // Don't load movie
|
||||
bool bSkipAnimation; // Don't load animation
|
||||
|
||||
bool bToolMode; // System is running inside a tool. Will not create USER directory or anything else that the game needs to do
|
||||
|
||||
bool bSkipPhysics; // Don't initialize CryPhysics.
|
||||
|
||||
ISystem* pSystem; // Pointer to existing ISystem interface, it will be reused if not NULL.
|
||||
|
||||
typedef void* (*ProtectedFunction)(void* param1, void* param2);
|
||||
ProtectedFunction pProtectedFunctions[eProtectedFuncsLast]; // Protected functions.
|
||||
|
||||
SCvarsDefault* pCvarsDefault; // to override the default value of some cvar
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
ICVarsWhitelist* pCVarsWhitelist; // CVars whitelist callback
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
SharedEnvironmentInstance* pSharedEnvironment;
|
||||
|
||||
// Summary:
|
||||
@@ -668,16 +552,10 @@ struct SSystemInitParams
|
||||
{
|
||||
hInstance = NULL;
|
||||
hWnd = NULL;
|
||||
hWndForInputSystem = NULL;
|
||||
|
||||
remoteResourceCompiler = false;
|
||||
|
||||
pLog = NULL;
|
||||
pLogCallback = NULL;
|
||||
pUserCallback = NULL;
|
||||
#if defined(CVARS_WHITELIST)
|
||||
pCVarsWhitelist = NULL;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
sLogFileName = NULL;
|
||||
autoBackupLogs = true;
|
||||
pValidator = NULL;
|
||||
@@ -688,32 +566,13 @@ struct SSystemInitParams
|
||||
bPreview = false;
|
||||
bTestMode = false;
|
||||
bDedicatedServer = false;
|
||||
bExecuteCommandLine = true;
|
||||
bExecuteCommandLine = true;
|
||||
bSkipFont = false;
|
||||
bSkipConsole = false;
|
||||
bSkipNetwork = false;
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
// create websocket server by default. bear in mind that USE_HTTP_WEBSOCKETS is not defined in release.
|
||||
bSkipWebsocketServer = false;
|
||||
#else
|
||||
// CTCPStreamSocket only seems to fully support Win32 and 64
|
||||
bSkipWebsocketServer = true;
|
||||
#endif
|
||||
bMinimal = false;
|
||||
bTesting = false;
|
||||
bNoRandom = false;
|
||||
bUnattendedMode = false;
|
||||
bSkipMovie = false;
|
||||
bSkipAnimation = false;
|
||||
bToolMode = false;
|
||||
bSkipPhysics = false;
|
||||
|
||||
pSystem = NULL;
|
||||
|
||||
memset(pProtectedFunctions, 0, sizeof(pProtectedFunctions));
|
||||
pCvarsDefault = NULL;
|
||||
|
||||
pSharedEnvironment = nullptr;
|
||||
}
|
||||
};
|
||||
@@ -782,8 +641,6 @@ struct SSystemGlobalEnvironment
|
||||
{
|
||||
AZ::IO::IArchive* pCryPak;
|
||||
AZ::IO::FileIOBase* pFileIO;
|
||||
IProfileLogSystem* pProfileLogSystem;
|
||||
IOpticsManager* pOpticsManager;
|
||||
ITimer* pTimer;
|
||||
ICryFont* pCryFont;
|
||||
::IConsole* pConsole;
|
||||
@@ -791,81 +648,27 @@ struct SSystemGlobalEnvironment
|
||||
ILog* pLog;
|
||||
IMovieSystem* pMovieSystem;
|
||||
INameTable* pNameTable;
|
||||
IVisualLog* pVisualLog;
|
||||
IRenderer* pRenderer;
|
||||
IMaterialEffects* pMaterialEffects;
|
||||
ISoftCodeMgr* pSoftCodeMgr;
|
||||
ILyShine* pLyShine;
|
||||
IResourceCompilerHelper* pResourceCompilerHelper;
|
||||
SharedEnvironmentInstance* pSharedEnvironment;
|
||||
IThreadManager* pThreadManager;
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION ISYSTEM_H_SECTION_4
|
||||
#include AZ_RESTRICTED_FILE(ISystem_h)
|
||||
#endif
|
||||
|
||||
ISystemScheduler* pSystemScheduler;
|
||||
|
||||
threadID mMainThreadId; //The main thread ID is used in multiple systems so should be stored globally
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 nMainFrameID;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* szCmdLine; // Startup command line.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Generic debug string which can be easily updated by any system and output by the debug handler
|
||||
enum
|
||||
{
|
||||
MAX_DEBUG_STRING_LENGTH = 128
|
||||
};
|
||||
char szDebugStatus[MAX_DEBUG_STRING_LENGTH];
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Used to tell if this is a server/multiplayer instance
|
||||
bool bServer;
|
||||
bool bMultiplayer;
|
||||
bool bHostMigrating;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Indicate Editor status.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Used by CRY_ASSERT
|
||||
bool bIgnoreAllAsserts;
|
||||
bool bNoAssertDialog;
|
||||
bool bTesting;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool bNoRandomSeed;
|
||||
|
||||
SPlatformInfo pi;
|
||||
|
||||
// Protected functions.
|
||||
SSystemInitParams::ProtectedFunction pProtectedFunctions[eProtectedFuncsLast]; // Protected functions.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Flag to able to print out of memory conditon
|
||||
bool bIsOutOfMemory;
|
||||
bool bIsOutOfVideoMemory;
|
||||
|
||||
bool bToolMode;
|
||||
|
||||
int retCode = 0;
|
||||
|
||||
ILINE const bool IsClient() const
|
||||
{
|
||||
#if defined(CONSOLE)
|
||||
return true;
|
||||
#else
|
||||
return bClient;
|
||||
#endif
|
||||
}
|
||||
|
||||
ILINE const bool IsDedicated() const
|
||||
{
|
||||
#if defined(CONSOLE)
|
||||
@@ -895,11 +698,6 @@ struct SSystemGlobalEnvironment
|
||||
{
|
||||
bDedicated = isDedicated;
|
||||
}
|
||||
|
||||
ILINE void SetIsClient(bool isClient)
|
||||
{
|
||||
bClient = isClient;
|
||||
}
|
||||
#endif
|
||||
|
||||
//this way the compiler can strip out code for consoles
|
||||
@@ -939,26 +737,6 @@ struct SSystemGlobalEnvironment
|
||||
#endif
|
||||
}
|
||||
|
||||
ILINE const bool IsFMVPlaying() const
|
||||
{
|
||||
return m_isFMVPlaying;
|
||||
}
|
||||
|
||||
ILINE void SetFMVIsPlaying(const bool isPlaying)
|
||||
{
|
||||
m_isFMVPlaying = isPlaying;
|
||||
}
|
||||
|
||||
ILINE const bool IsCutscenePlaying() const
|
||||
{
|
||||
return m_isCutscenePlaying;
|
||||
}
|
||||
|
||||
ILINE void SetCutsceneIsPlaying(const bool isPlaying)
|
||||
{
|
||||
m_isCutscenePlaying = isPlaying;
|
||||
}
|
||||
|
||||
ILINE bool IsInToolMode() const
|
||||
{
|
||||
return bToolMode;
|
||||
@@ -969,35 +747,17 @@ struct SSystemGlobalEnvironment
|
||||
bToolMode = bNewToolMode;
|
||||
}
|
||||
|
||||
ILINE void SetDynamicMergedMeshGenerationEnabled(bool mmgenEnable)
|
||||
{
|
||||
m_bDynamicMergedMeshGenerationEnabled = mmgenEnable;
|
||||
}
|
||||
|
||||
ILINE const bool IsDynamicMergedMeshGenerationEnabled() const
|
||||
{
|
||||
return m_bDynamicMergedMeshGenerationEnabled;
|
||||
}
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
private:
|
||||
bool bClient;
|
||||
bool bEditor; // Engine is running under editor.
|
||||
bool bEditorGameMode; // Engine is in editor game mode.
|
||||
bool bEditorSimulationMode; // Engine is in editor simulation mode.
|
||||
bool bDedicated; // Engine is in dedicated
|
||||
#endif
|
||||
|
||||
bool m_isFMVPlaying;
|
||||
bool m_isCutscenePlaying;
|
||||
bool m_bDynamicMergedMeshGenerationEnabled;
|
||||
|
||||
public:
|
||||
SSystemGlobalEnvironment()
|
||||
: pSystemScheduler(nullptr)
|
||||
, szCmdLine("")
|
||||
, bToolMode(false)
|
||||
, m_bDynamicMergedMeshGenerationEnabled(false)
|
||||
: bToolMode(false)
|
||||
{
|
||||
};
|
||||
};
|
||||
@@ -1035,37 +795,11 @@ struct IProfilingSystem
|
||||
// Initialize and dispatch all engine's subsystems.
|
||||
struct ISystem
|
||||
{
|
||||
struct ILoadingProgressListener
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ILoadingProgressListener() {}
|
||||
virtual void OnLoadingProgress(int steps) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
#ifndef _RELEASE
|
||||
enum LevelLoadOrigin
|
||||
{
|
||||
eLLO_Unknown,
|
||||
eLLO_NewLevel,
|
||||
eLLO_Level2Level,
|
||||
eLLO_Resumed,
|
||||
eLLO_MapCmd,
|
||||
};
|
||||
|
||||
struct ICheckpointData
|
||||
{
|
||||
int m_totalLoads;
|
||||
LevelLoadOrigin m_loadOrigin;
|
||||
};
|
||||
#endif
|
||||
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ISystem() {}
|
||||
// Summary:
|
||||
// Releases ISystem.
|
||||
virtual void Release() = 0;
|
||||
virtual ILoadConfigurationEntrySink* GetCVarsWhiteListConfigSink() const = 0; // will return NULL if no whitelisting
|
||||
|
||||
// Summary:
|
||||
// Returns pointer to the global environment structure.
|
||||
@@ -1094,9 +828,6 @@ struct ISystem
|
||||
virtual void DoWorkDuringOcclusionChecks() = 0;
|
||||
virtual bool NeedDoWorkDuringOcclusionChecks() = 0;
|
||||
|
||||
//! Update screen and call some important tick functions during loading.
|
||||
virtual void SynchronousLoadingTick(const char* pFunc, int line) = 0;
|
||||
|
||||
// Summary:
|
||||
// Returns the current used memory.
|
||||
virtual uint32 GetUsedMemory() = 0;
|
||||
@@ -1170,7 +901,6 @@ struct ISystem
|
||||
virtual IZLibDecompressor* GetIZLibDecompressor() = 0;
|
||||
virtual ILZ4Decompressor* GetLZ4Decompressor() = 0;
|
||||
virtual IZStdDecompressor* GetZStdDecompressor() = 0;
|
||||
virtual INotificationNetwork* GetINotificationNetwork() = 0;
|
||||
virtual IViewSystem* GetIViewSystem() = 0;
|
||||
virtual ILevelSystem* GetILevelSystem() = 0;
|
||||
virtual INameTable* GetINameTable() = 0;
|
||||
@@ -1187,24 +917,10 @@ struct ISystem
|
||||
// Returns:
|
||||
// Can be NULL, because it only exists when running through the editor, not in pure game mode.
|
||||
virtual IResourceManager* GetIResourceManager() = 0;
|
||||
virtual IThreadTaskManager* GetIThreadTaskManager() = 0;
|
||||
virtual IProfilingSystem* GetIProfilingSystem() = 0;
|
||||
virtual ISystemEventDispatcher* GetISystemEventDispatcher() = 0;
|
||||
virtual IVisualLog* GetIVisualLog() = 0;
|
||||
|
||||
virtual ITimer* GetITimer() = 0;
|
||||
virtual IThreadManager* GetIThreadManager() = 0;
|
||||
|
||||
virtual void SetLoadingProgressListener(ILoadingProgressListener* pListener) = 0;
|
||||
virtual ISystem::ILoadingProgressListener* GetLoadingProgressListener() const = 0;
|
||||
|
||||
// Summary:
|
||||
// Game is created after System init, so has to be set explicitly.
|
||||
virtual void SetIMaterialEffects(IMaterialEffects* pMaterialEffects) = 0;
|
||||
virtual void SetIOpticsManager(IOpticsManager* pOpticsManager) = 0;
|
||||
virtual void SetIVisualLog(IVisualLog* pVisualLog) = 0;
|
||||
|
||||
//virtual const char *GetGamePath()=0;
|
||||
|
||||
virtual void DebugStats(bool checkpoint, bool leaks) = 0;
|
||||
virtual void DumpWinHeaps() = 0;
|
||||
@@ -1219,7 +935,6 @@ struct ISystem
|
||||
virtual bool WasInDevMode() const = 0;
|
||||
virtual bool IsDevMode() const = 0;
|
||||
virtual bool IsMODValid(const char* szMODName) const = 0;
|
||||
virtual bool IsMinimalMode() const = 0;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1334,12 +1049,6 @@ struct ISystem
|
||||
// Detects and set optimal spec.
|
||||
virtual void AutoDetectSpec(bool detectResolution) = 0;
|
||||
|
||||
// Summary:
|
||||
// Thread management for subsystems
|
||||
// Return Value:
|
||||
// Non-0 if the state was indeed changed, 0 if already in that state.
|
||||
virtual int SetThreadState(ESubsystem subsys, bool bActive) = 0;
|
||||
|
||||
// Summary:
|
||||
// Query if system is now paused.
|
||||
// Pause flag is set when calling system update with pause mode.
|
||||
@@ -1406,14 +1115,6 @@ struct ISystem
|
||||
// Get log index of the currently running Open 3D Engine application. (0 = first instance, 1 = second instance, etc)
|
||||
virtual int GetApplicationLogInstance(const char* logFilePath) = 0;
|
||||
|
||||
// Summary:
|
||||
// Retrieves the current stats for systems to update the respective time taken
|
||||
virtual sUpdateTimes& GetCurrentUpdateTimeStats() = 0;
|
||||
|
||||
// Summary:
|
||||
// Retrieves the array of update times and the number of entries
|
||||
virtual const sUpdateTimes* GetUpdateTimeStats(uint32&, uint32&) = 0;
|
||||
|
||||
// Summary:
|
||||
// Clear all currently logged and drawn on screen error messages
|
||||
virtual void ClearErrorMessages() = 0;
|
||||
@@ -1458,17 +1159,6 @@ struct ISystem
|
||||
virtual void AsyncMemcpy(void* dst, const void* src, size_t size, int nFlags, volatile int* sync) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
virtual ICVarsWhitelist* GetCVarsWhiteList() const = 0;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
#ifndef _RELEASE
|
||||
virtual void GetCheckpointData(ICheckpointData& data) = 0;
|
||||
virtual void IncreaseCheckpointLoadCount() = 0;
|
||||
virtual void SetLoadOrigin(LevelLoadOrigin origin) = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
virtual bool IsSavingResourceList() const = 0;
|
||||
#endif
|
||||
@@ -1513,11 +1203,6 @@ struct ISystem
|
||||
using CrySystemNotificationBus = AZ::EBus<CrySystemNotifications>;
|
||||
};
|
||||
|
||||
//JAT - this is a very important function for the dedicated server - it lets us run >1000 players per piece of server hardware
|
||||
//JAT - this saves us lots of money on the dedicated server hardware
|
||||
#define SYNCHRONOUS_LOADING_TICK() do { if (gEnv && gEnv->pSystem) {gEnv->pSystem->SynchronousLoadingTick(__FUNC__, __LINE__); } \
|
||||
} while (0)
|
||||
|
||||
#if defined(USE_DISK_PROFILER)
|
||||
|
||||
struct DiskOperationInfo
|
||||
@@ -1594,7 +1279,7 @@ typedef ISystem* (*PFNCREATESYSTEMINTERFACE)(SSystemInitParams& initParams);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Global environment variable.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
extern SC_API SSystemGlobalEnvironment* gEnv;
|
||||
extern SSystemGlobalEnvironment* gEnv;
|
||||
|
||||
|
||||
// Summary:
|
||||
@@ -1613,11 +1298,6 @@ inline ISystem* GetISystem()
|
||||
}
|
||||
return systemInterface;
|
||||
};
|
||||
|
||||
inline ISystemScheduler* GetISystemScheduler(void)
|
||||
{
|
||||
return gEnv->pSystemScheduler;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Description:
|
||||
@@ -1640,7 +1320,6 @@ void* GetDetachEnvironmentSymbol();
|
||||
|
||||
|
||||
extern bool g_bProfilerEnabled;
|
||||
extern int g_iTraceAllocations;
|
||||
|
||||
// Summary:
|
||||
// Interface of the DLL.
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ISYSTEMSCHEDULER_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ISYSTEMSCHEDULER_H
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define SLICE_AND_SLEEP() do { if (GetISystemScheduler()) { GetISystemScheduler()->SliceAndSleep(__FUNC__, __LINE__); } \
|
||||
} while (0)
|
||||
#define SLICE_SCOPE_DEFINE() CSliceLoadingMonitor sliceScope
|
||||
#else
|
||||
extern void SliceAndSleep(const char* pFunc, int line);
|
||||
#define SLICE_AND_SLEEP() SliceAndSleep(__FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
struct ISystemScheduler
|
||||
{
|
||||
virtual ~ISystemScheduler(){}
|
||||
|
||||
// <interfuscator:shuffle>
|
||||
// Map load slicing functionality support
|
||||
virtual void SliceAndSleep(const char* sliceName, int line) = 0;
|
||||
virtual void SliceLoadingBegin() = 0;
|
||||
virtual void SliceLoadingEnd() = 0;
|
||||
|
||||
virtual void SchedulingSleepIfNeeded(void) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
ISystemScheduler* GetISystemScheduler(void);
|
||||
|
||||
class CSliceLoadingMonitor
|
||||
{
|
||||
public:
|
||||
CSliceLoadingMonitor()
|
||||
{
|
||||
if (GetISystemScheduler())
|
||||
{
|
||||
GetISystemScheduler()->SliceLoadingBegin();
|
||||
}
|
||||
}
|
||||
|
||||
~CSliceLoadingMonitor()
|
||||
{
|
||||
if (GetISystemScheduler())
|
||||
{
|
||||
GetISystemScheduler()->SliceLoadingEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ISYSTEMSCHEDULER_H
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
|
||||
class IThreadConfigManager;
|
||||
|
||||
enum EJoinMode
|
||||
{
|
||||
eJM_TryJoin,
|
||||
eJM_Join,
|
||||
};
|
||||
|
||||
class IThread
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IThread()
|
||||
{
|
||||
}
|
||||
|
||||
//! Entry functions for code executed on thread.
|
||||
virtual void ThreadEntry() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
enum EFPE_Severity
|
||||
{
|
||||
eFPE_None, //!< No Floating Point Exceptions.
|
||||
eFPE_Basic, //!< Invalid operation, Div by 0.
|
||||
eFPE_All, //!< Invalid operation, Div by 0, Denormalized operand, Overflow, Underflow, Inexact.
|
||||
eFPE_LastEntry
|
||||
};
|
||||
|
||||
//temp disable CRY DX12
|
||||
//#define SCOPED_ENABLE_FLOAT_EXCEPTIONS(eFPESeverity) CScopedFloatingPointException scopedSetFloatExceptionMask(eFPESeverity)
|
||||
//#define SCOPED_DISABLE_FLOAT_EXCEPTIONS() CScopedFloatingPointException scopedSetFloatExceptionMask(eFPE_None)
|
||||
|
||||
struct IThreadManager
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IThreadManager()
|
||||
{
|
||||
}
|
||||
|
||||
//! Get thread config manager.
|
||||
virtual IThreadConfigManager* GetThreadConfigManager() = 0;
|
||||
|
||||
//! Spawn a new thread and apply thread config settings at thread beginning.
|
||||
virtual bool SpawnThread(IThread* pThread, const char* sThreadName, ...) = 0;
|
||||
|
||||
//! Wait on another thread to exit (Blocking).
|
||||
//! Use eJM_TryJoin if you cannot be sure that the target thread is awake.
|
||||
//! \retval true if target thread has not been started yet or has already exited.
|
||||
//! \retval false if target thread is still running and therefore not in a state to exit.
|
||||
virtual bool JoinThread(IThread* pThreadTask, EJoinMode joinStatus) = 0;
|
||||
|
||||
//! Register 3rd party thread with the thread manager.
|
||||
//! Applies thread config for thread if found.
|
||||
//! \param pThreadHandle If NULL, the current thread handle will be used.
|
||||
virtual bool RegisterThirdPartyThread(void* pThreadHandle, const char* sThreadName, ...) = 0;
|
||||
|
||||
//! Unregister 3rd party thread with the thread manager.
|
||||
virtual bool UnRegisterThirdPartyThread(const char* sThreadName, ...) = 0;
|
||||
|
||||
//! Get Thread Name.
|
||||
//! Returns "" if thread not found.
|
||||
virtual const char* GetThreadName(threadID nThreadId) = 0;
|
||||
|
||||
//! Get ThreadID.
|
||||
virtual threadID GetThreadId(const char* sThreadName, ...) = 0;
|
||||
|
||||
//! Execute function for each other thread but this one.
|
||||
typedef void (* ThreadModifFunction)(threadID nThreadId, void* pData);
|
||||
virtual void ForEachOtherThread(IThreadManager::ThreadModifFunction fpThreadModiFunction, void* pFuncData = 0) = 0;
|
||||
|
||||
virtual void EnableFloatExceptions(EFPE_Severity eFPESeverity, threadID nThreadId = 0) = 0;
|
||||
virtual void EnableFloatExceptionsForEachOtherThread(EFPE_Severity eFPESeverity) = 0;
|
||||
|
||||
virtual uint GetFloatingPointExceptionMask() = 0;
|
||||
virtual void SetFloatingPointExceptionMask(uint nMask) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
/*TEMP DISABLE CRY DX12
|
||||
class CScopedFloatingPointException
|
||||
{
|
||||
public:
|
||||
CScopedFloatingPointException(EFPE_Severity eFPESeverity)
|
||||
{
|
||||
oldMask = gEnv->pThreadManager->GetFloatingPointExceptionMask();
|
||||
gEnv->pThreadManager->EnableFloatExceptions(eFPESeverity);
|
||||
}
|
||||
~CScopedFloatingPointException()
|
||||
{
|
||||
gEnv->pThreadManager->SetFloatingPointExceptionMask(oldMask);
|
||||
}
|
||||
private:
|
||||
uint oldMask;
|
||||
};
|
||||
*/
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "BitFiddling.h"
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ITHREADTASK_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ITHREADTASK_H
|
||||
#pragma once
|
||||
|
||||
#include <smartptr.h>
|
||||
|
||||
// forward declarations
|
||||
struct SThreadTaskInfo;
|
||||
|
||||
enum EThreadTaskFlags
|
||||
{
|
||||
THREAD_TASK_BLOCKING = BIT(0), // Blocking tasks will be allocated on their own thread.
|
||||
THREAD_TASK_ASSIGN_TO_POOL = BIT(1), // Task can be assigned to any thread in the group of threads
|
||||
};
|
||||
|
||||
class IThreadTask_Thread
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IThreadTask_Thread() {};
|
||||
virtual void AddTask(SThreadTaskInfo* pTaskInfo) = 0;
|
||||
virtual void RemoveTask(SThreadTaskInfo* pTaskInfo) = 0;
|
||||
virtual void RemoveAllTasks() = 0;
|
||||
virtual void SingleUpdate() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
typedef int ThreadPoolHandle;
|
||||
|
||||
struct SThreadTaskParams
|
||||
{
|
||||
uint32 nFlags; // Task flags. @see ETaskFlags
|
||||
union
|
||||
{
|
||||
int nPreferedThread; // Preferred Thread index (0,1,2,3...)
|
||||
ThreadPoolHandle nThreadsGroupId; // Id of group of threads(useful only if THREAD_TASK_ASSIGN_TO_POOL is set)
|
||||
};
|
||||
int16 nPriorityOff; // If THREAD_TASK_BLOCKING, this will adjust the priority of the thread
|
||||
int16 nStackSizeKB; // If THREAD_TASK_BLOCKING, this will adjust the stack size of the thread
|
||||
const char* name; // Name for this task (thread for the blocking task will be named using this string)
|
||||
|
||||
SThreadTaskParams()
|
||||
: nFlags(0)
|
||||
, nPreferedThread(-1)
|
||||
, nPriorityOff(0)
|
||||
, name("")
|
||||
, nStackSizeKB(SIMPLE_THREAD_STACK_SIZE_KB) {}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Tasks must implement this interface.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IThreadTask
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
// The function to be called on every update for non bocking tasks.
|
||||
// Or will be called only once for the blocking threads.
|
||||
virtual void OnUpdate() = 0;
|
||||
|
||||
// Called to indicate that this task must quit.
|
||||
// Warning! can be called from different thread then OnUpdate call.
|
||||
virtual void Stop() = 0;
|
||||
|
||||
// Returns task info
|
||||
virtual struct SThreadTaskInfo* GetTaskInfo() = 0;
|
||||
|
||||
virtual ~IThreadTask() {}
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
struct SThreadTaskInfo
|
||||
: public CMultiThreadRefCount
|
||||
{
|
||||
IThreadTask_Thread* m_pThread;
|
||||
IThreadTask* m_pTask;
|
||||
SThreadTaskParams m_params;
|
||||
|
||||
SThreadTaskInfo()
|
||||
: m_pThread(NULL)
|
||||
, m_pTask(NULL) { m_params.nFlags = 0; m_params.nPreferedThread = -1; }
|
||||
};
|
||||
|
||||
// Might be changed to uint64 etc in the future
|
||||
typedef uint32 ThreadPoolAffinityMask;
|
||||
#define INVALID_AFFINITY 0
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Description of thread pool to create
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct ThreadPoolDesc
|
||||
{
|
||||
ThreadPoolAffinityMask AffinityMask; // number of bits means number of threads. affinity overlapping is prohibited
|
||||
string sPoolName;
|
||||
int32 nThreadPriority;
|
||||
int32 nThreadStackSizeKB;
|
||||
|
||||
ThreadPoolDesc()
|
||||
: AffinityMask(INVALID_AFFINITY)
|
||||
, sPoolName("UnnamedPool")
|
||||
, nThreadPriority(-1)
|
||||
, nThreadStackSizeKB(-1) { }
|
||||
|
||||
ILINE bool CreateThread(ThreadPoolAffinityMask affinityMask)
|
||||
{
|
||||
if (this->AffinityMask & affinityMask)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this->AffinityMask |= affinityMask;
|
||||
return true;
|
||||
}
|
||||
|
||||
ILINE uint32 GetThreadCount() const
|
||||
{
|
||||
return CountBits(AffinityMask);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Task manager.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IThreadTaskManager
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IThreadTaskManager(){}
|
||||
// Register new task to the manager.
|
||||
virtual void RegisterTask(IThreadTask* pTask, const SThreadTaskParams& options) = 0;
|
||||
virtual void UnregisterTask(IThreadTask* pTask) = 0;
|
||||
|
||||
// Limit number of threads to this amount.
|
||||
virtual void SetMaxThreadCount(int nMaxThreads) = 0;
|
||||
|
||||
// Create a pool of threads
|
||||
virtual ThreadPoolHandle CreateThreadsPool(const ThreadPoolDesc& desc) = 0;
|
||||
virtual const bool DestroyThreadsPool(const ThreadPoolHandle& handle) = 0;
|
||||
virtual const bool GetThreadsPoolDesc(const ThreadPoolHandle handle, ThreadPoolDesc* pDesc) const = 0;
|
||||
virtual const bool SetThreadsPoolAffinity(const ThreadPoolHandle handle, const ThreadPoolAffinityMask AffinityMask) = 0;
|
||||
|
||||
virtual void SetThreadName(threadID dwThreadId, const char* sThreadName) = 0;
|
||||
virtual const char* GetThreadName(threadID dwThreadId) = 0;
|
||||
|
||||
// Return thread handle by thread name
|
||||
virtual threadID GetThreadByName(const char* sThreadName) = 0;
|
||||
|
||||
// if bMark=true the calling thread will dump its stack during crashes
|
||||
virtual void MarkThisThreadForDebugging(const char* name, bool bDump) = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ITHREADTASK_H
|
||||
@@ -585,8 +585,6 @@ public:
|
||||
SDepthTexture * (int, int, bool));
|
||||
MOCK_METHOD1(DestroyDepthSurface,
|
||||
void(SDepthTexture * pDepthSurf));
|
||||
MOCK_CONST_METHOD1(CreateOptics,
|
||||
IOpticsElementBase * (EFlareType type));
|
||||
MOCK_METHOD1(PauseTimer,
|
||||
void(bool bPause));
|
||||
MOCK_METHOD0(CreateShaderPublicParams,
|
||||
|
||||
@@ -23,8 +23,6 @@ class SystemMock
|
||||
public:
|
||||
MOCK_METHOD0(Release,
|
||||
void());
|
||||
MOCK_CONST_METHOD0(GetCVarsWhiteListConfigSink,
|
||||
ILoadConfigurationEntrySink * ());
|
||||
MOCK_METHOD0(GetGlobalEnvironment,
|
||||
SSystemGlobalEnvironment * ());
|
||||
MOCK_METHOD2(UpdatePreTickBus,
|
||||
@@ -37,8 +35,6 @@ public:
|
||||
void());
|
||||
MOCK_METHOD0(NeedDoWorkDuringOcclusionChecks,
|
||||
bool());
|
||||
MOCK_METHOD2(SynchronousLoadingTick,
|
||||
void(const char* pFunc, int line));
|
||||
MOCK_METHOD0(RenderStatistics,
|
||||
void());
|
||||
MOCK_METHOD0(GetUsedMemory,
|
||||
@@ -84,8 +80,6 @@ public:
|
||||
ILZ4Decompressor * ());
|
||||
MOCK_METHOD0(GetZStdDecompressor,
|
||||
IZStdDecompressor * ());
|
||||
MOCK_METHOD0(GetINotificationNetwork,
|
||||
INotificationNetwork * ());
|
||||
MOCK_METHOD0(GetIViewSystem,
|
||||
IViewSystem * ());
|
||||
MOCK_METHOD0(GetILevelSystem,
|
||||
@@ -116,28 +110,12 @@ public:
|
||||
IRemoteConsole * ());
|
||||
MOCK_METHOD0(GetIResourceManager,
|
||||
IResourceManager * ());
|
||||
MOCK_METHOD0(GetIThreadTaskManager,
|
||||
IThreadTaskManager * ());
|
||||
MOCK_METHOD0(GetIProfilingSystem,
|
||||
IProfilingSystem * ());
|
||||
MOCK_METHOD0(GetISystemEventDispatcher,
|
||||
ISystemEventDispatcher * ());
|
||||
MOCK_METHOD0(GetIVisualLog,
|
||||
IVisualLog * ());
|
||||
MOCK_METHOD0(GetITimer,
|
||||
ITimer * ());
|
||||
MOCK_METHOD0(GetIThreadManager,
|
||||
IThreadManager * ());
|
||||
MOCK_METHOD1(SetLoadingProgressListener,
|
||||
void(ILoadingProgressListener * pListener));
|
||||
MOCK_CONST_METHOD0(GetLoadingProgressListener,
|
||||
ISystem::ILoadingProgressListener * ());
|
||||
MOCK_METHOD1(SetIMaterialEffects,
|
||||
void(IMaterialEffects * pMaterialEffects));
|
||||
MOCK_METHOD1(SetIOpticsManager,
|
||||
void(IOpticsManager * pOpticsManager));
|
||||
MOCK_METHOD1(SetIVisualLog,
|
||||
void(IVisualLog * pVisualLog));
|
||||
MOCK_METHOD2(DebugStats,
|
||||
void(bool checkpoint, bool leaks));
|
||||
MOCK_METHOD0(DumpWinHeaps,
|
||||
@@ -154,8 +132,6 @@ public:
|
||||
bool());
|
||||
MOCK_CONST_METHOD1(IsMODValid,
|
||||
bool(const char* szMODName));
|
||||
MOCK_CONST_METHOD0(IsMinimalMode,
|
||||
bool());
|
||||
MOCK_METHOD3(CreateXmlNode,
|
||||
XmlNodeRef(const char*, bool, bool));
|
||||
MOCK_METHOD4(LoadXmlFromBuffer,
|
||||
@@ -209,8 +185,6 @@ public:
|
||||
void(ESystemConfigPlatform platform));
|
||||
MOCK_METHOD1(AutoDetectSpec,
|
||||
void(bool detectResolution));
|
||||
MOCK_METHOD2(SetThreadState,
|
||||
int(ESubsystem subsys, bool bActive));
|
||||
MOCK_CONST_METHOD0(IsPaused,
|
||||
bool());
|
||||
MOCK_METHOD0(GetLocalizationManager,
|
||||
@@ -239,10 +213,6 @@ public:
|
||||
int());
|
||||
MOCK_METHOD1(GetApplicationLogInstance,
|
||||
int(const char* logFilePath));
|
||||
MOCK_METHOD0(GetCurrentUpdateTimeStats,
|
||||
sUpdateTimes & ());
|
||||
MOCK_METHOD2(GetUpdateTimeStats,
|
||||
const sUpdateTimes * (uint32 &, uint32 &));
|
||||
MOCK_METHOD0(ClearErrorMessages,
|
||||
void());
|
||||
MOCK_METHOD2(debug_GetCallStack,
|
||||
@@ -260,20 +230,6 @@ public:
|
||||
MOCK_METHOD5(AsyncMemcpy,
|
||||
void(void* dst, const void* src, size_t size, int nFlags, volatile int* sync));
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
MOCK_CONST_METHOD0(GetCVarsWhiteList,
|
||||
ICVarsWhitelist * ());
|
||||
#endif
|
||||
|
||||
#ifndef _RELEASE
|
||||
MOCK_METHOD1(GetCheckpointData,
|
||||
void(ICheckpointData & data));
|
||||
MOCK_METHOD0(IncreaseCheckpointLoadCount,
|
||||
void());
|
||||
MOCK_METHOD1(SetLoadOrigin,
|
||||
void(LevelLoadOrigin origin));
|
||||
#endif
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
MOCK_CONST_METHOD0(IsSavingResourceList,
|
||||
bool());
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../EngineSettingsBackendApple.cpp
|
||||
../../EngineSettingsBackendApple.h
|
||||
)
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../../EngineSettingsBackendWin32.cpp
|
||||
../../EngineSettingsBackendWin32.h
|
||||
)
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_PROFILELOG_H
|
||||
#define CRYINCLUDE_CRYCOMMON_PROFILELOG_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <ISystem.h> // <> required for Interfuscator
|
||||
#include <ITimer.h> // <> required for Interfuscator
|
||||
|
||||
struct ILogElement
|
||||
{
|
||||
virtual ~ILogElement(){}
|
||||
virtual ILogElement* Log (const char* name, const char* message) = 0;
|
||||
virtual ILogElement* SetTime (float time) = 0;
|
||||
virtual void Flush (stack_string& indent) = 0;
|
||||
};
|
||||
|
||||
struct IProfileLogSystem
|
||||
{
|
||||
virtual ~IProfileLogSystem(){}
|
||||
virtual ILogElement* Log (const char* name, const char* msg) = 0;
|
||||
virtual void SetTime (ILogElement* pElement, float time) = 0;
|
||||
virtual void Release () = 0;
|
||||
};
|
||||
|
||||
struct SHierProfileLogItem
|
||||
{
|
||||
SHierProfileLogItem(const char* name, const char* msg, int inbDoLog)
|
||||
: m_pLogElement(NULL)
|
||||
, m_bDoLog(inbDoLog)
|
||||
{
|
||||
if (m_bDoLog)
|
||||
{
|
||||
m_pLogElement = gEnv->pProfileLogSystem->Log(name, msg);
|
||||
m_startTime = gEnv->pTimer->GetAsyncTime();
|
||||
}
|
||||
}
|
||||
~SHierProfileLogItem()
|
||||
{
|
||||
if (m_bDoLog)
|
||||
{
|
||||
CTimeValue endTime = gEnv->pTimer->GetAsyncTime();
|
||||
gEnv->pProfileLogSystem->SetTime(m_pLogElement, (endTime - m_startTime).GetMilliSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int m_bDoLog;
|
||||
CTimeValue m_startTime;
|
||||
ILogElement* m_pLogElement;
|
||||
};
|
||||
|
||||
#define HPROFILE_BEGIN(msg1, msg2, doLog) { SHierProfileLogItem __hier_profile_uniq_var_in_this_scope__(msg1, msg2, doLog);
|
||||
#define HPROFILE_END() }
|
||||
|
||||
#define HPROFILE(msg1, msg2, doLog) SHierProfileLogItem __hier_profile_uniq_var_in_this_scope__(msg1, msg2, doLog);
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_PROFILELOG_H
|
||||
@@ -78,9 +78,6 @@ typedef uint32 vtx_idx;
|
||||
|
||||
#if defined(WIN32) || defined(WIN64) || LOG_CONST_CVAR_ACCESS
|
||||
#define RELEASE_LOGGING
|
||||
//#if defined(_RELEASE)
|
||||
//#define CVARS_WHITELIST
|
||||
//#endif // defined(_RELEASE)
|
||||
#endif
|
||||
|
||||
#if defined(_RELEASE) && !defined(RELEASE_LOGGING)
|
||||
@@ -181,32 +178,6 @@ typedef uint32 vtx_idx;
|
||||
#define SHADER_REFLECT_TEXTURE_SLOTS 0
|
||||
#endif
|
||||
|
||||
#if (defined(WIN32) || defined(WIN64) || defined(AZ_PLATFORM_MAC)) && (!defined(AZ_MONOLITHIC_BUILD) || defined(RESOURCE_COMPILER))
|
||||
#define CRY_ENABLE_RC_HELPER 1
|
||||
#endif
|
||||
|
||||
#if !defined(_RELEASE) && PROJECTDEFINES_H_TRAIT_ENABLE_SOFTCODE_SYSTEM
|
||||
#define SOFTCODE_SYSTEM_ENABLED
|
||||
#endif
|
||||
|
||||
// Is SoftCoding enabled for this module? Usually set by the SoftCode AddIn in conjunction with a SoftCode.props file.
|
||||
#ifdef SOFTCODE_ENABLED
|
||||
|
||||
// Is this current compilation unit part of a SOFTCODE build?
|
||||
#ifdef SOFTCODE
|
||||
// Import any SC functions from the host module
|
||||
#define SC_API __declspec(dllimport)
|
||||
#else
|
||||
// Export any SC functions from the host module
|
||||
#define SC_API __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#else // SoftCode disabled
|
||||
|
||||
#define SC_API
|
||||
|
||||
#endif
|
||||
|
||||
// these enable and disable certain net features to give compatibility between PCs and consoles / profile and performance builds
|
||||
#define PC_CONSOLE_NET_COMPATIBLE 0
|
||||
#define PROFILE_PERFORMANCE_NET_COMPATIBLE 0
|
||||
@@ -292,10 +263,6 @@ typedef uint32 vtx_idx;
|
||||
# define ENABLE_LOADING_PROFILER // requires AZ_PROFILE_TELEMETRY to also be defined
|
||||
#endif
|
||||
|
||||
#if defined(SOFTCODE_ENABLED)
|
||||
#error "SoftCode currently relies on CryMemoryManager being enabled. Either build without SoftCode support, or enable CryMemoryManager."
|
||||
#endif
|
||||
|
||||
#if PROJECTDEFINES_H_TRAIT_USE_GPU_PARTICLES && !defined(NULL_RENDERER)
|
||||
#define GPU_PARTICLES 1
|
||||
#else
|
||||
|
||||
@@ -1,639 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#include "ResourceCompilerHelper.h"
|
||||
#include "EngineSettingsManager.h"
|
||||
|
||||
// When complining CryTiffPlugin the mayaAssert.h is included that defined
|
||||
// Assert as _Assert. This wreaks havoc with AZ_Assert since under the covers
|
||||
// it calls AzCore::Debug::Trace::Assert, which gets transformed bo
|
||||
// Trace::_Assert, which does not exist. Gotta love macros. Undefine Assert
|
||||
// before we include semaphore so that it can compile correctly
|
||||
#if defined(Assert)
|
||||
#undef Assert
|
||||
#endif
|
||||
|
||||
#include <AzCore/std/parallel/semaphore.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <shellapi.h> // ShellExecuteW()
|
||||
#endif
|
||||
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
#include "AppleSpecific.h"
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#else
|
||||
#undef RC_EXECUTABLE
|
||||
#define RC_EXECUTABLE "rc.exe"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string> // lawsonn - we use std::string internally
|
||||
#include <sstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
class LineStreamBuffer
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
LineStreamBuffer(T* object, void (T::* method)(const char* line))
|
||||
: m_charCount(0)
|
||||
, m_bTruncated(false)
|
||||
{
|
||||
m_target = new Target<T>(object, method);
|
||||
}
|
||||
|
||||
~LineStreamBuffer()
|
||||
{
|
||||
Flush();
|
||||
delete m_target;
|
||||
}
|
||||
|
||||
void HandleText(const char* text, int length)
|
||||
{
|
||||
const char* pos = text;
|
||||
while (pos - text < length)
|
||||
{
|
||||
const char* start = pos;
|
||||
|
||||
while (pos - text < length && *pos != '\n' && *pos != '\r')
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
|
||||
size_t n = pos - start;
|
||||
if (m_charCount + n > kMaxCharCount)
|
||||
{
|
||||
n = kMaxCharCount - m_charCount;
|
||||
m_bTruncated = true;
|
||||
}
|
||||
memcpy(&m_buffer[m_charCount], start, n);
|
||||
m_charCount += n;
|
||||
|
||||
if (pos - text < length)
|
||||
{
|
||||
Flush();
|
||||
while (pos - text < length && (*pos == '\n' || *pos == '\r'))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
if (m_charCount > 0)
|
||||
{
|
||||
m_buffer[m_charCount] = 0;
|
||||
m_target->Call(m_buffer);
|
||||
m_charCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsTruncated() const
|
||||
{
|
||||
return m_bTruncated;
|
||||
}
|
||||
|
||||
private:
|
||||
struct ITarget
|
||||
{
|
||||
virtual ~ITarget() {}
|
||||
virtual void Call(const char* line) = 0;
|
||||
};
|
||||
template <typename T>
|
||||
struct Target
|
||||
: public ITarget
|
||||
{
|
||||
public:
|
||||
Target(T* object, void (T::* method)(const char* line))
|
||||
: object(object)
|
||||
, method(method) {}
|
||||
virtual void Call(const char* line)
|
||||
{
|
||||
(object->*method)(line);
|
||||
}
|
||||
private:
|
||||
T* object;
|
||||
void (T::* method)(const char* line);
|
||||
};
|
||||
|
||||
ITarget* m_target;
|
||||
size_t m_charCount;
|
||||
static const size_t kMaxCharCount = 2047;
|
||||
char m_buffer[kMaxCharCount + 1];
|
||||
bool m_bTruncated;
|
||||
};
|
||||
|
||||
#if !defined(AZ_PLATFORM_WINDOWS)
|
||||
void MessageBoxW(int, const wchar_t* header, const wchar_t* message, unsigned long)
|
||||
{
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
CFStringEncoding encoding = (CFByteOrderLittleEndian == CFByteOrderGetCurrent()) ?
|
||||
kCFStringEncodingUTF32LE : kCFStringEncodingUTF32BE;
|
||||
CFStringRef header_ref = CFStringCreateWithBytes(nullptr, reinterpret_cast<const UInt8*>(header), wcslen(header) * sizeof(wchar_t), encoding, false);
|
||||
CFStringRef message_ref = CFStringCreateWithBytes(nullptr, reinterpret_cast<const UInt8*>(message), wcslen(message) * sizeof(wchar_t), encoding, false);
|
||||
|
||||
CFOptionFlags result; //result code from the message box
|
||||
|
||||
CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel, 0, 0, 0, header_ref, message_ref, 0, 0, 0, &result);
|
||||
|
||||
CFRelease(header_ref);
|
||||
CFRelease(message_ref);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class RcLock
|
||||
{
|
||||
public:
|
||||
RcLock()
|
||||
: m_cs(0u, 1u)
|
||||
{
|
||||
m_cs.release();
|
||||
}
|
||||
~RcLock()
|
||||
{
|
||||
}
|
||||
|
||||
void Lock()
|
||||
{
|
||||
m_cs.acquire();
|
||||
}
|
||||
void Unlock()
|
||||
{
|
||||
m_cs.release();
|
||||
}
|
||||
|
||||
private:
|
||||
AZStd::semaphore m_cs;
|
||||
};
|
||||
|
||||
|
||||
template<class LockClass>
|
||||
class RcAutoLock
|
||||
{
|
||||
public:
|
||||
RcAutoLock(LockClass& lock)
|
||||
: m_lock(lock)
|
||||
{
|
||||
m_lock.Lock();
|
||||
}
|
||||
~RcAutoLock()
|
||||
{
|
||||
m_lock.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
RcAutoLock();
|
||||
RcAutoLock(const RcAutoLock<LockClass>&);
|
||||
RcAutoLock<LockClass>& operator =(const RcAutoLock<LockClass>&);
|
||||
|
||||
private:
|
||||
LockClass& m_lock;
|
||||
};
|
||||
|
||||
|
||||
HANDLE s_rcProcessHandle = 0;
|
||||
RcLock s_rcProcessHandleLock;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void ShowMessageBoxRcNotFound([[maybe_unused]] const wchar_t* const szCmdLine, [[maybe_unused]] const wchar_t* const szDir)
|
||||
{
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH* 4 + 150> tmp;
|
||||
|
||||
tmp.append(L"The resource compiler (RC.EXE) was not found.");
|
||||
MessageBoxW(0, tmp.c_str(), L"Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
class ResourceCompilerLineHandler
|
||||
{
|
||||
public:
|
||||
ResourceCompilerLineHandler(IResourceCompilerListener* listener)
|
||||
: m_listener(listener)
|
||||
{
|
||||
}
|
||||
|
||||
void HandleLine(const char* line)
|
||||
{
|
||||
if (!m_listener || !line)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check the first three characters to see if it's a warning or error.
|
||||
bool bHasPrefix;
|
||||
IResourceCompilerListener::MessageSeverity severity;
|
||||
if ((line[0] == 'E') && (line[1] == ':') && (line[2] == ' '))
|
||||
{
|
||||
bHasPrefix = true;
|
||||
severity = IResourceCompilerListener::MessageSeverity_Error;
|
||||
line += 3; // skip the prefix
|
||||
}
|
||||
else if ((line[0] == 'W') && (line[1] == ':') && (line[2] == ' '))
|
||||
{
|
||||
bHasPrefix = true;
|
||||
severity = IResourceCompilerListener::MessageSeverity_Warning;
|
||||
line += 3; // skip the prefix
|
||||
}
|
||||
else if ((line[0] == ' ') && (line[1] == ' ') && (line[2] == ' '))
|
||||
{
|
||||
bHasPrefix = true;
|
||||
severity = IResourceCompilerListener::MessageSeverity_Info;
|
||||
line += 3; // skip the prefix
|
||||
}
|
||||
else
|
||||
{
|
||||
bHasPrefix = false;
|
||||
severity = IResourceCompilerListener::MessageSeverity_Info;
|
||||
}
|
||||
|
||||
if (bHasPrefix)
|
||||
{
|
||||
// skip thread info "%d>", if present
|
||||
{
|
||||
const char* p = line;
|
||||
while (*p == ' ')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (isdigit(*p))
|
||||
{
|
||||
while (isdigit(*p))
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (*p == '>')
|
||||
{
|
||||
line = p + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// skip time info "%d:%d", if present
|
||||
{
|
||||
const char* p = line;
|
||||
while (*p == ' ')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (isdigit(*p))
|
||||
{
|
||||
while (isdigit(*p))
|
||||
{
|
||||
++p;
|
||||
}
|
||||
if (*p == ':')
|
||||
{
|
||||
++p;
|
||||
if (isdigit(*p))
|
||||
{
|
||||
while (isdigit(*p))
|
||||
{
|
||||
++p;
|
||||
}
|
||||
while (*p == ' ')
|
||||
{
|
||||
++p;
|
||||
}
|
||||
line = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_listener->OnRCMessage(severity, line);
|
||||
}
|
||||
|
||||
private:
|
||||
IResourceCompilerListener* m_listener;
|
||||
};
|
||||
|
||||
// we now support macros like #ENGINEROOT# in the string:
|
||||
void replaceAllInStringInPlace(std::string& inOut, const char* findValue, const char* replaceValue)
|
||||
{
|
||||
if (!findValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!replaceValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string::size_type pos = std::string::npos;
|
||||
std::string::size_type replaceLen = strlen(findValue);
|
||||
|
||||
while ((pos = inOut.find(findValue)) != std::string::npos)
|
||||
{
|
||||
inOut.replace(pos, replaceLen, replaceValue);
|
||||
}
|
||||
}
|
||||
|
||||
// given a string that contains macros (like #ENGINEROOT#), eliminate the macros and replace them with the real data.
|
||||
// note that in the 'remote' implementation, these macros are sent to the remote RC. It can then expand them for its own environment
|
||||
// but in a local RC, these macros are expanded by the local environment.
|
||||
void expandMacros(const char* inputString, char* outputString, std::size_t bufferSize)
|
||||
{
|
||||
if (!inputString)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!outputString)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string_view rootFolder;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(rootFolder, &AZ::ComponentApplicationRequests::GetAppRoot);
|
||||
|
||||
std::string finalString(inputString);
|
||||
const AZStd::string rootFolderStr = rootFolder.data();
|
||||
replaceAllInStringInPlace(finalString, "#ENGINEROOT#", rootFolderStr.c_str());
|
||||
// put additional replacements here.
|
||||
|
||||
azstrcpy(outputString, bufferSize, finalString.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler(
|
||||
const char* szFileName,
|
||||
const char* szAdditionalSettings,
|
||||
IResourceCompilerListener* listener,
|
||||
bool bMayShowWindow,
|
||||
bool bSilent,
|
||||
bool bNoUserDialog,
|
||||
const wchar_t* szWorkingDirectory,
|
||||
[[maybe_unused]] const wchar_t* szRootPath)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
HANDLE hChildStdOutRd = INVALID_HANDLE_VALUE, hChildStdOutWr = INVALID_HANDLE_VALUE;
|
||||
HANDLE hChildStdInRd = INVALID_HANDLE_VALUE, hChildStdInWr = INVALID_HANDLE_VALUE;
|
||||
PROCESS_INFORMATION pi;
|
||||
#else
|
||||
FILE* hChildStdOutRd;
|
||||
#endif
|
||||
|
||||
{
|
||||
RcAutoLock<RcLock> lock(s_rcProcessHandleLock);
|
||||
|
||||
// make command for execution
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH* 3> wRemoteCmdLine;
|
||||
|
||||
|
||||
if (!szAdditionalSettings)
|
||||
{
|
||||
szAdditionalSettings = "";
|
||||
}
|
||||
|
||||
// expand the additioanl settings.
|
||||
char szActualFileName[512] = {0};
|
||||
char szActualAdditionalSettings[512] = {0};
|
||||
|
||||
expandMacros(szFileName, szActualFileName, 512);
|
||||
expandMacros(szAdditionalSettings, szActualAdditionalSettings, 512);
|
||||
|
||||
CSettingsManagerTools smTools = CSettingsManagerTools(); // moved this line to after macro expansion to avoid multiple of these existing at once.
|
||||
|
||||
AZStd::string_view exeFolderName;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(exeFolderName, &AZ::ComponentApplicationRequests::GetExecutableFolder);
|
||||
|
||||
wchar_t szRegSettingsBuffer[1024];
|
||||
smTools.GetEngineSettingsManager()->GetValueByRef("RC_Parameters", SettingsManagerHelpers::CWCharBuffer(szRegSettingsBuffer, sizeof(szRegSettingsBuffer)));
|
||||
bool enableSourceControl = true;
|
||||
smTools.GetEngineSettingsManager()->GetValueByRef("RC_EnableSourceControl", enableSourceControl);
|
||||
|
||||
wRemoteCmdLine.appendAscii("\"");
|
||||
wRemoteCmdLine.appendAscii(exeFolderName.data(), exeFolderName.size());
|
||||
wRemoteCmdLine.appendAscii("/");
|
||||
wRemoteCmdLine.appendAscii(RC_EXECUTABLE);
|
||||
wRemoteCmdLine.appendAscii("\"");
|
||||
|
||||
if (!enableSourceControl)
|
||||
{
|
||||
wRemoteCmdLine.appendAscii(" -nosourcecontrol ");
|
||||
}
|
||||
|
||||
if (!szFileName)
|
||||
{
|
||||
wRemoteCmdLine.appendAscii(" -userdialog=0 ");
|
||||
wRemoteCmdLine.appendAscii(szActualAdditionalSettings);
|
||||
wRemoteCmdLine.appendAscii(" ");
|
||||
wRemoteCmdLine.append(szRegSettingsBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
wRemoteCmdLine.appendAscii(" \"");
|
||||
wRemoteCmdLine.appendAscii(szActualFileName);
|
||||
wRemoteCmdLine.appendAscii("\"");
|
||||
wRemoteCmdLine.appendAscii(bNoUserDialog ? " -userdialog=0 " : " -userdialog=1 ");
|
||||
wRemoteCmdLine.appendAscii(szActualAdditionalSettings);
|
||||
wRemoteCmdLine.appendAscii(" ");
|
||||
wRemoteCmdLine.append(szRegSettingsBuffer);
|
||||
}
|
||||
|
||||
// Create a pipe to read the stdout of the RC.
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
if (listener)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
ZeroMemory(&saAttr, sizeof(saAttr));
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = 0;
|
||||
CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0);
|
||||
SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
|
||||
CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0);
|
||||
SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
STARTUPINFOW si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwX = 100;
|
||||
si.dwY = 100;
|
||||
if (listener)
|
||||
{
|
||||
si.hStdError = hChildStdOutWr;
|
||||
si.hStdOutput = hChildStdOutWr;
|
||||
si.hStdInput = hChildStdInRd;
|
||||
si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
si.dwFlags = STARTF_USEPOSITION;
|
||||
}
|
||||
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
#endif
|
||||
|
||||
bool bShowWindow;
|
||||
if (bMayShowWindow)
|
||||
{
|
||||
wchar_t buffer[20];
|
||||
smTools.GetEngineSettingsManager()->GetValueByRef("ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
|
||||
bShowWindow = (wcscmp(buffer, L"true") == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bShowWindow = false;
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const wchar_t* szStartingDirectory = szWorkingDirectory;
|
||||
if (!szStartingDirectory)
|
||||
{
|
||||
char currentDirectory[MAX_PATH];
|
||||
AZ::Utils::GetExecutableDirectory(currentDirectory, MAX_PATH);
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH> wCurrentDirectory;
|
||||
wCurrentDirectory.appendAscii(currentDirectory);
|
||||
szStartingDirectory = wCurrentDirectory.c_str();
|
||||
}
|
||||
|
||||
|
||||
if (!CreateProcessW(
|
||||
NULL, // No module name (use command line).
|
||||
const_cast<wchar_t*>(wRemoteCmdLine.c_str()), // Command line.
|
||||
NULL, // Process handle not inheritable.
|
||||
NULL, // Thread handle not inheritable.
|
||||
TRUE, // Set handle inheritance to TRUE.
|
||||
bShowWindow ? 0 : CREATE_NO_WINDOW, // creation flags.
|
||||
NULL, // Use parent's environment block.
|
||||
szStartingDirectory, // Set starting directory.
|
||||
&si, // Pointer to STARTUPINFO structure.
|
||||
&pi)) // Pointer to PROCESS_INFORMATION structure.
|
||||
{
|
||||
// The following code block is commented out instead of being deleted
|
||||
// because it's good to have at hand for a debugging session.
|
||||
#if 0
|
||||
const size_t charsInMessageBuffer = 32768; // msdn about FormatMessage(): "The output buffer cannot be larger than 64K bytes."
|
||||
wchar_t szMessageBuffer[charsInMessageBuffer] = L"";
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szMessageBuffer, charsInMessageBuffer, NULL);
|
||||
GetCurrentDirectoryW(charsInMessageBuffer, szMessageBuffer);
|
||||
#endif
|
||||
|
||||
if (!bSilent)
|
||||
{
|
||||
ShowMessageBoxRcNotFound(wRemoteCmdLine.c_str(), szStartingDirectory);
|
||||
}
|
||||
|
||||
return eRcCallResult_notFound;
|
||||
}
|
||||
|
||||
s_rcProcessHandle = pi.hProcess;
|
||||
#else
|
||||
int fd = open(".", O_RDONLY);
|
||||
char remoteCmdLineUtf8[MAX_PATH * 8];
|
||||
char workingDirectory[MAX_PATH * 8];
|
||||
ConvertUtf16ToUtf8(wRemoteCmdLine.c_str(), SettingsManagerHelpers::CCharBuffer(remoteCmdLineUtf8, MAX_PATH * 8));
|
||||
if (szWorkingDirectory)
|
||||
{
|
||||
ConvertUtf16ToUtf8(szWorkingDirectory, SettingsManagerHelpers::CCharBuffer(workingDirectory, MAX_PATH * 8));
|
||||
chdir(workingDirectory);
|
||||
}
|
||||
hChildStdOutRd = popen(remoteCmdLineUtf8, "r");
|
||||
fchdir(fd);
|
||||
if (hChildStdOutRd == nullptr)
|
||||
{
|
||||
if (!bSilent)
|
||||
{
|
||||
ShowMessageBoxRcNotFound(wRemoteCmdLine.c_str(), szWorkingDirectory);
|
||||
}
|
||||
return eRcCallResult_notFound;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool bFailedToReadOutput = false;
|
||||
|
||||
if (listener)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Close the pipe that writes to the child process, since we don't actually have any input for it.
|
||||
CloseHandle(hChildStdInWr);
|
||||
|
||||
// Read all the output from the child process.
|
||||
CloseHandle(hChildStdOutWr);
|
||||
#endif
|
||||
ResourceCompilerLineHandler lineHandler(listener);
|
||||
LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine);
|
||||
for (;; )
|
||||
{
|
||||
char buffer[2048];
|
||||
DWORD bytesRead;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0))
|
||||
#else
|
||||
if (fgets(buffer, sizeof(buffer), hChildStdOutRd) == nullptr || (bytesRead = strlen(buffer) == 0))
|
||||
#endif
|
||||
{
|
||||
break;
|
||||
}
|
||||
lineBuffer.HandleText(buffer, bytesRead);
|
||||
}
|
||||
|
||||
bFailedToReadOutput = lineBuffer.IsTruncated();
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
#else
|
||||
DWORD exitCode = pclose(hChildStdOutRd);
|
||||
#endif
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
RcAutoLock<RcLock> lock(s_rcProcessHandleLock);
|
||||
s_rcProcessHandle = 0;
|
||||
|
||||
DWORD exitCode = eRcExitCode_Error;
|
||||
if (bFailedToReadOutput || GetExitCodeProcess(pi.hProcess, &exitCode) == 0)
|
||||
{
|
||||
exitCode = eRcExitCode_Error;
|
||||
}
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
#endif
|
||||
|
||||
return ConvertResourceCompilerExitCodeToResultCode(exitCode);
|
||||
}
|
||||
|
||||
|
||||
#endif //(CRY_ENABLE_RC_HELPER)
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_RESOURCECOMPILERHELPER_H
|
||||
#define CRYINCLUDE_CRYCOMMON_RESOURCECOMPILERHELPER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#include "IResourceCompilerHelper.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Provides settings and functions to make calls to RC.
|
||||
// calls RC locally. only works on windows, does not exist on other platforms
|
||||
// note: You shouldn't be calling this directly
|
||||
// instead, you should be calling it via the IResourceCompilerHelper interface.
|
||||
// since it may be replaced with a custom RC for your platform or a remote invocation
|
||||
class CResourceCompilerHelper
|
||||
: public IResourceCompilerHelper
|
||||
{
|
||||
public:
|
||||
virtual ERcCallResult CallResourceCompiler(
|
||||
const char* szFileName = 0,
|
||||
const char* szAdditionalSettings = 0,
|
||||
IResourceCompilerListener* listener = 0,
|
||||
bool bMayShowWindow = true,
|
||||
bool bSilent = false,
|
||||
bool bNoUserDialog = false,
|
||||
const wchar_t* szWorkingDirectory = 0,
|
||||
const wchar_t* szRootPath = 0) override;
|
||||
};
|
||||
|
||||
#endif // CRY_ENABLE_RC_HELPER
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_RESOURCECOMPILERHELPER_H
|
||||
@@ -1,325 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#include "SettingsManagerHelpers.h"
|
||||
#include "EngineSettingsManager.h"
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <shellapi.h> //ShellExecuteW()
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
#endif
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
#include "AppleSpecific.h"
|
||||
#endif
|
||||
|
||||
bool SettingsManagerHelpers::Utf16ContainsAsciiOnly(const wchar_t* wstr)
|
||||
{
|
||||
while (*wstr)
|
||||
{
|
||||
if (*wstr > 127 || *wstr < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
++wstr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SettingsManagerHelpers::ConvertUtf16ToUtf8(const wchar_t* src, CCharBuffer dst)
|
||||
{
|
||||
if (dst.getSizeInElements() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (src[0] == 0)
|
||||
{
|
||||
dst[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::codecvt<wchar_t, char, std::mbstate_t>& utf8Utf16Facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale());
|
||||
std::mbstate_t mb{};
|
||||
const wchar_t* from_next;
|
||||
char* to_next;
|
||||
std::codecvt_base::result result = utf8Utf16Facet.out(mb, src, src + wcslen(src), from_next, dst.getPtr(), dst.getPtr() + dst.getSizeInElements(), to_next);
|
||||
if (result != std::codecvt_base::ok)
|
||||
{
|
||||
dst[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
to_next = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SettingsManagerHelpers::ConvertUtf8ToUtf16(const char* src, CWCharBuffer dst)
|
||||
{
|
||||
if (dst.getSizeInElements() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (src[0] == 0)
|
||||
{
|
||||
dst[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::codecvt<wchar_t, char, std::mbstate_t>& utf8Utf16Facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale());
|
||||
std::mbstate_t mb{};
|
||||
const char* from_next;
|
||||
wchar_t* to_next;
|
||||
std::codecvt_base::result result = utf8Utf16Facet.in(mb, src, src + strlen(src), from_next, dst.getPtr(), dst.getPtr() + dst.getSizeInElements(), to_next);
|
||||
if (result != std::codecvt_base::ok)
|
||||
{
|
||||
dst[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
to_next = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SettingsManagerHelpers::GetAsciiFilename(const wchar_t* wfilename, CCharBuffer buffer)
|
||||
{
|
||||
if (buffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wfilename[0] == 0)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utf16ContainsAsciiOnly(wfilename))
|
||||
{
|
||||
ConvertUtf16ToUtf8(wfilename, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// The path is non-ASCII unicode, so let's resort to short filenames (they are always ASCII-only, I hope)
|
||||
wchar_t shortW[MAX_PATH];
|
||||
const int bufferCharCount = sizeof(shortW) / sizeof(shortW[0]);
|
||||
const int charCount = GetShortPathNameW(wfilename, shortW, bufferCharCount);
|
||||
if (charCount <= 0 || charCount >= bufferCharCount)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
shortW[charCount] = 0;
|
||||
if (!Utf16ContainsAsciiOnly(shortW))
|
||||
{
|
||||
buffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ConvertUtf16ToUtf8(shortW, buffer);
|
||||
#else
|
||||
buffer[0] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CSettingsManagerTools::CSettingsManagerTools(const wchar_t* szModuleName)
|
||||
{
|
||||
m_pSettingsManager = new CEngineSettingsManager(szModuleName);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CSettingsManagerTools::~CSettingsManagerTools()
|
||||
{
|
||||
delete m_pSettingsManager;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSettingsManagerTools::GetInstalledBuildPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path)
|
||||
{
|
||||
return m_pSettingsManager->GetInstalledBuildRootPathUtf16(index, name, path);
|
||||
}
|
||||
|
||||
|
||||
bool CSettingsManagerTools::GetInstalledBuildPathAscii(const int index, SettingsManagerHelpers::CCharBuffer name, SettingsManagerHelpers::CCharBuffer path)
|
||||
{
|
||||
wchar_t wName[MAX_PATH];
|
||||
wchar_t wPath[MAX_PATH];
|
||||
if (GetInstalledBuildPathUtf16(index, SettingsManagerHelpers::CWCharBuffer(wName, sizeof(wName)), SettingsManagerHelpers::CWCharBuffer(wPath, sizeof(wPath))))
|
||||
{
|
||||
SettingsManagerHelpers::GetAsciiFilename(wName, name);
|
||||
SettingsManagerHelpers::GetAsciiFilename(wPath, path);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static bool FileExists(const wchar_t* filename)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
const DWORD dwAttrib = GetFileAttributesW(filename);
|
||||
return dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
|
||||
#else
|
||||
char utf8Filename[MAX_PATH];
|
||||
SettingsManagerHelpers::ConvertUtf16ToUtf8(filename, SettingsManagerHelpers::CCharBuffer(utf8Filename, sizeof(utf8Filename)));
|
||||
struct stat buffer;
|
||||
return (stat(utf8Filename, &buffer) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSettingsManagerTools::GetEditorExecutable(SettingsManagerHelpers::CWCharBuffer wbuffer)
|
||||
{
|
||||
if (wbuffer.getSizeInElements() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string_view exePath;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(exePath, &AZ::ComponentApplicationRequests::GetExecutableFolder);
|
||||
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, 1024> editorExe;
|
||||
editorExe = wbuffer.getPtr();
|
||||
editorExe.appendAscii(exePath.data(), exePath.size());
|
||||
|
||||
if (editorExe.length() <= 0)
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
bool bFound = false;
|
||||
if (Is64bitWindows())
|
||||
{
|
||||
const size_t len = editorExe.length();
|
||||
editorExe.appendAscii("/Editor.exe");
|
||||
bFound = FileExists(editorExe.c_str());
|
||||
if (!bFound)
|
||||
{
|
||||
editorExe.setLength(len);
|
||||
}
|
||||
}
|
||||
|
||||
const size_t sizeToCopy = (editorExe.length() + 1) * sizeof(wbuffer[0]);
|
||||
if (!bFound || sizeToCopy > wbuffer.getSizeInBytes())
|
||||
{
|
||||
wbuffer[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(wbuffer.getPtr(), editorExe.c_str(), sizeToCopy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSettingsManagerTools::CallEditor(void** pEditorWindow, [[maybe_unused]] void* hParent, const char* pWindowName, const char* pFlag)
|
||||
{
|
||||
#if !defined(AZ_PLATFORM_WINDOWS)
|
||||
AZ_Assert(false, "CSettingsManagerTools::CallEditor is not supported on this platform!");
|
||||
return false;
|
||||
#else
|
||||
HWND window = ::FindWindowA(NULL, pWindowName);
|
||||
if (window)
|
||||
{
|
||||
*pEditorWindow = window;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pEditorWindow = 0;
|
||||
|
||||
wchar_t buffer[512] = { L'\0' };
|
||||
GetEditorExecutable(SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
|
||||
|
||||
SettingsManagerHelpers::CFixedString<wchar_t, 256> wFlags;
|
||||
SettingsManagerHelpers::ConvertUtf8ToUtf16(pFlag, wFlags.getBuffer());
|
||||
wFlags.setLength(wcslen(wFlags.c_str()));
|
||||
|
||||
if (buffer[0] != '\0')
|
||||
{
|
||||
INT_PTR hIns = (INT_PTR)ShellExecuteW(NULL, L"open", buffer, wFlags.c_str(), NULL, SW_SHOWNORMAL);
|
||||
if (hIns > 32)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxA(0, "Editor.exe was not found.\n\nPlease verify CryENGINE root path.", "Error", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Modified version of
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139(v=vs.85).aspx
|
||||
bool CSettingsManagerTools::Is64bitWindows()
|
||||
{
|
||||
#if defined(_WIN64)
|
||||
// 64-bit programs run only on 64-bit Windows
|
||||
return true;
|
||||
#elif !defined(AZ_PLATFORM_WINDOWS)
|
||||
return false;
|
||||
#else
|
||||
// 32-bit programs run on both 32-bit and 64-bit Windows
|
||||
static bool bWin64 = false;
|
||||
static bool bOnce = true;
|
||||
if (bOnce)
|
||||
{
|
||||
typedef BOOL (WINAPI * LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
|
||||
if (fnIsWow64Process != NULL)
|
||||
{
|
||||
BOOL itIsWow64Process = FALSE;
|
||||
if (fnIsWow64Process(GetCurrentProcess(), &itIsWow64Process))
|
||||
{
|
||||
bWin64 = (itIsWow64Process == TRUE);
|
||||
}
|
||||
}
|
||||
bOnce = false;
|
||||
}
|
||||
return bWin64;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // #if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
// eof
|
||||
@@ -1,491 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_SETTINGSMANAGERHELPERS_H
|
||||
#define CRYINCLUDE_CRYCOMMON_SETTINGSMANAGERHELPERS_H
|
||||
#pragma once
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
#include <string.h> // memcpy
|
||||
#include <algorithm> // std::min
|
||||
|
||||
|
||||
namespace SettingsManagerHelpers
|
||||
{
|
||||
namespace Utils
|
||||
{
|
||||
inline size_t strlen(const char* p)
|
||||
{
|
||||
return p ? ::strlen(p) : 0;
|
||||
}
|
||||
|
||||
inline size_t strcmp(const char* p0, const char* p1)
|
||||
{
|
||||
return ::strcmp(p0, p1);
|
||||
}
|
||||
|
||||
|
||||
inline size_t strlen(const wchar_t* p)
|
||||
{
|
||||
return p ? ::wcslen(p) : 0;
|
||||
}
|
||||
|
||||
inline size_t strcmp(const wchar_t* p0, const wchar_t* p1)
|
||||
{
|
||||
return ::wcscmp(p0, p1);
|
||||
}
|
||||
}
|
||||
|
||||
// The function copies characters from src to dst one by one until any of
|
||||
// the following conditions is met:
|
||||
// 1) the end of the destination buffer (minus one character) is reached
|
||||
// 2) the end of the source buffer is reached
|
||||
// 3) zero character is found in the source buffer
|
||||
//
|
||||
// When any of 1), 2), 3) happens, the function writes the terminating zero
|
||||
// character to the destination buffer and return.
|
||||
//
|
||||
// The function guarantees writing the terminating zero character to the
|
||||
// destination buffer (if the buffer can fit at least one character).
|
||||
//
|
||||
// The function returns false when a null pointer is passed or when
|
||||
// clamping happened (i.e. when the end of the destination buffer is
|
||||
// reached but the source has some characters left).
|
||||
inline bool strcpy_with_clamp(char* const dst, size_t const dst_size_in_bytes, const char* const src, size_t const src_size_in_bytes = (size_t)-1)
|
||||
{
|
||||
if (!dst || dst_size_in_bytes < sizeof(char))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src || src_size_in_bytes < sizeof(char))
|
||||
{
|
||||
dst[0] = 0;
|
||||
return src != 0; // we return true for non-null src without characters
|
||||
}
|
||||
|
||||
const size_t src_n = src_size_in_bytes;
|
||||
const size_t n = (std::min)(dst_size_in_bytes - 1, src_n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
if (!src[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
dst[n] = 0;
|
||||
return n >= src_n || src[n] == 0;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
class CBuffer
|
||||
{
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
private:
|
||||
element_type* m_ptr;
|
||||
size_t m_sizeInBytes;
|
||||
|
||||
public:
|
||||
CBuffer(element_type* ptr, size_t sizeInBytes)
|
||||
: m_ptr(ptr)
|
||||
, m_sizeInBytes(ptr ? sizeInBytes : 0)
|
||||
{
|
||||
}
|
||||
|
||||
const element_type* getPtr() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
element_type* getPtr()
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
size_t getSizeInElements() const
|
||||
{
|
||||
return m_sizeInBytes / sizeof(element_type);
|
||||
}
|
||||
|
||||
size_t getSizeInBytes() const
|
||||
{
|
||||
return m_sizeInBytes;
|
||||
}
|
||||
|
||||
const element_type& operator[](size_t pos) const
|
||||
{
|
||||
return m_ptr[pos];
|
||||
}
|
||||
|
||||
element_type& operator[](size_t pos)
|
||||
{
|
||||
return m_ptr[pos];
|
||||
}
|
||||
};
|
||||
|
||||
typedef CBuffer<char> CCharBuffer;
|
||||
typedef CBuffer<wchar_t> CWCharBuffer;
|
||||
|
||||
|
||||
template<class T, size_t CAPACITY>
|
||||
class CFixedString
|
||||
{
|
||||
public:
|
||||
typedef T char_type;
|
||||
static const size_t npos = ~size_t(0);
|
||||
private:
|
||||
size_t m_count; // # chars (not counting trailing zero)
|
||||
char_type m_buffer[CAPACITY + 1]; // '+ 1' is for trailing zero
|
||||
|
||||
public:
|
||||
CFixedString()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
CFixedString(const char_type* p)
|
||||
{
|
||||
set(p);
|
||||
}
|
||||
|
||||
CFixedString& operator=(const char_type* p)
|
||||
{
|
||||
set(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFixedString& operator=(const CFixedString& s)
|
||||
{
|
||||
if (&s != this)
|
||||
{
|
||||
set(s.m_buffer, s.m_count);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBuffer<char_type> getBuffer()
|
||||
{
|
||||
return CBuffer<char_type>(m_buffer, (CAPACITY + 1) * sizeof(char_type));
|
||||
}
|
||||
|
||||
char_type operator[](const size_t i) const
|
||||
{
|
||||
return m_buffer[i];
|
||||
}
|
||||
|
||||
const char_type* c_str() const
|
||||
{
|
||||
return &m_buffer[0];
|
||||
}
|
||||
|
||||
const size_t length() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_count = 0;
|
||||
m_buffer[m_count] = 0;
|
||||
}
|
||||
|
||||
void setLength(size_t n)
|
||||
{
|
||||
m_count = (n <= CAPACITY) ? n : CAPACITY;
|
||||
m_buffer[m_count] = 0;
|
||||
}
|
||||
|
||||
char_type* ptr()
|
||||
{
|
||||
return &m_buffer[0];
|
||||
}
|
||||
|
||||
CFixedString substr(size_t pos = 0, size_t n = npos) const
|
||||
{
|
||||
CFixedString s;
|
||||
if (pos < m_count && n > 0)
|
||||
{
|
||||
if (n > m_count || pos + n > m_count)
|
||||
{
|
||||
n = m_count - pos;
|
||||
}
|
||||
s.set(&m_buffer[pos], n);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void set(const char_type* p, size_t n)
|
||||
{
|
||||
if (p == 0 || n <= 0)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_count = (n > CAPACITY) ? CAPACITY : n;
|
||||
// memmove() is used because p may point to m_buffer
|
||||
memmove(m_buffer, p, m_count * sizeof(*p));
|
||||
}
|
||||
m_buffer[m_count] = 0;
|
||||
}
|
||||
|
||||
void set(const char_type* p)
|
||||
{
|
||||
if (p && p[0])
|
||||
{
|
||||
set(p, Utils::strlen(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
void append(const char_type* p, size_t n)
|
||||
{
|
||||
if (p && n > 0)
|
||||
{
|
||||
if (n > CAPACITY || m_count + n > CAPACITY)
|
||||
{
|
||||
// assert(0);
|
||||
n = CAPACITY - m_count;
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
memcpy(&m_buffer[m_count], p, n * sizeof(*p));
|
||||
m_count += n;
|
||||
m_buffer[m_count] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void append(const char_type* p)
|
||||
{
|
||||
if (p && p[0])
|
||||
{
|
||||
append(p, Utils::strlen(p));
|
||||
}
|
||||
}
|
||||
|
||||
void appendAscii(const char* p, size_t n)
|
||||
{
|
||||
if (p && n > 0)
|
||||
{
|
||||
if (n > CAPACITY || m_count + n > CAPACITY)
|
||||
{
|
||||
// assert(0);
|
||||
n = CAPACITY - m_count;
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
m_buffer[m_count + i] = p[i];
|
||||
}
|
||||
m_count += n;
|
||||
m_buffer[m_count] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appendAscii(const char* p)
|
||||
{
|
||||
if (p && p[0])
|
||||
{
|
||||
appendAscii(p, Utils::strlen(p));
|
||||
}
|
||||
}
|
||||
|
||||
bool equals(const char_type* p) const
|
||||
{
|
||||
return (p == 0 || p[0] == 0)
|
||||
? (m_count == 0)
|
||||
: (Utils::strcmp(m_buffer, p) == 0);
|
||||
}
|
||||
|
||||
void trim()
|
||||
{
|
||||
size_t begin = 0;
|
||||
while (begin < m_count && (m_buffer[begin] == ' ' || m_buffer[begin] == '\r' || m_buffer[begin] == '\t' || m_buffer[begin] == '\n'))
|
||||
{
|
||||
++begin;
|
||||
}
|
||||
|
||||
if (begin >= m_count)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t end = m_count - 1;
|
||||
while (end > begin && (m_buffer[begin] == ' ' || m_buffer[begin] == '\r' || m_buffer[begin] == '\t' || m_buffer[begin] == '\n'))
|
||||
{
|
||||
--end;
|
||||
}
|
||||
|
||||
m_count = end + 1;
|
||||
m_buffer[m_count] = 0;
|
||||
|
||||
if (begin > 0)
|
||||
{
|
||||
set(&m_buffer[begin], m_count - begin);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SKeyValue
|
||||
{
|
||||
CFixedString<char, 256> key;
|
||||
CFixedString<wchar_t, 256> value;
|
||||
};
|
||||
|
||||
|
||||
template<size_t CAPACITY>
|
||||
class CKeyValueArray
|
||||
{
|
||||
private:
|
||||
size_t count;
|
||||
SKeyValue data[CAPACITY];
|
||||
|
||||
public:
|
||||
CKeyValueArray()
|
||||
: count(0)
|
||||
{
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
const SKeyValue& operator[](size_t i) const
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
const SKeyValue* find(const char* key) const
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (data[i].key.equals(key))
|
||||
{
|
||||
return &data[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SKeyValue* find(const char* key)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (data[i].key.equals(key))
|
||||
{
|
||||
return &data[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SKeyValue* set(const char* key, const wchar_t* value)
|
||||
{
|
||||
SKeyValue* p = find(key);
|
||||
if (!p)
|
||||
{
|
||||
if (count >= CAPACITY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
p = &data[count++];
|
||||
p->key = key;
|
||||
}
|
||||
p->value = value;
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
bool Utf16ContainsAsciiOnly(const wchar_t* wstr);
|
||||
|
||||
void ConvertUtf16ToUtf8(const wchar_t* src, CCharBuffer dst);
|
||||
|
||||
void ConvertUtf8ToUtf16(const char* src, CWCharBuffer dst);
|
||||
|
||||
template <size_t CAPACITY>
|
||||
void AddPathSeparator(CFixedString<wchar_t, CAPACITY>& wstr)
|
||||
{
|
||||
if (wstr.length() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wstr[wstr.length() - 1] == L'/' || wstr[wstr.length() - 1] == L'\\')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wstr.appendAscii("/");
|
||||
}
|
||||
|
||||
void GetAsciiFilename(const wchar_t* wfilename, CCharBuffer buffer);
|
||||
|
||||
#endif // #if defined(CRY_ENABLE_RC_HELPER)
|
||||
} // namespace SettingsManagerHelpers
|
||||
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Provides settings and functions to make calls to RC.
|
||||
class CEngineSettingsManager;
|
||||
class CSettingsManagerTools
|
||||
{
|
||||
public:
|
||||
CSettingsManagerTools(const wchar_t* szModuleName = 0);
|
||||
~CSettingsManagerTools();
|
||||
|
||||
private:
|
||||
CEngineSettingsManager* m_pSettingsManager;
|
||||
|
||||
public:
|
||||
CEngineSettingsManager* GetEngineSettingsManager()
|
||||
{
|
||||
return m_pSettingsManager;
|
||||
}
|
||||
|
||||
bool GetInstalledBuildPathUtf16(const int index, SettingsManagerHelpers::CWCharBuffer name, SettingsManagerHelpers::CWCharBuffer path);
|
||||
bool GetInstalledBuildPathAscii(const int index, SettingsManagerHelpers::CCharBuffer name, SettingsManagerHelpers::CCharBuffer path);
|
||||
|
||||
void GetEditorExecutable(SettingsManagerHelpers::CWCharBuffer wbuffer);
|
||||
bool CallEditor(void** pEditorWindow, void* hParent, const char* pWndName, const char* pFlag);
|
||||
|
||||
static bool Is64bitWindows();
|
||||
};
|
||||
|
||||
#endif // #if defined(CRY_ENABLE_RC_HELPER)
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_SETTINGSMANAGERHELPERS_H
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
# For complete copyright and license terms please see the LICENSE at the root of this
|
||||
# distribution (the "License"). All use of this software is governed by the License,
|
||||
# or, if provided, by the license below or the license accompanying this file. Do not
|
||||
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectDefines.h
|
||||
SettingsManagerHelpers.cpp
|
||||
SettingsManagerHelpers.h
|
||||
EngineSettingsManager.cpp
|
||||
EngineSettingsManager.h
|
||||
EngineSettingsBackend.cpp
|
||||
EngineSettingsBackend.h
|
||||
ResourceCompilerHelper.cpp
|
||||
ResourceCompilerHelper.h
|
||||
)
|
||||
|
||||
# Remove files that cause #define collisions on Mac due to multiple inclusions of 'AppleSpecific.h' and include orders
|
||||
set(SKIP_UNITY_BUILD_INCLUSION_FILES
|
||||
SettingsManagerHelpers.cpp
|
||||
)
|
||||
@@ -22,7 +22,6 @@ set(FILES
|
||||
IConsole.h
|
||||
IEntityRenderState.h
|
||||
IEntityRenderState_info.cpp
|
||||
IFlares.h
|
||||
IFont.h
|
||||
IFunctorBase.h
|
||||
IFuncVariable.h
|
||||
@@ -40,12 +39,10 @@ set(FILES
|
||||
ILog.h
|
||||
ILZ4Decompressor.h
|
||||
IMaterial.h
|
||||
IMaterialEffects.h
|
||||
IMemory.h
|
||||
IMeshBaking.h
|
||||
IMiniLog.h
|
||||
IMovieSystem.h
|
||||
INotificationNetwork.h
|
||||
IPhysics.h
|
||||
IPhysicsDebugRenderer.h
|
||||
IPostEffectGroup.h
|
||||
@@ -55,12 +52,10 @@ set(FILES
|
||||
IRenderer.h
|
||||
IRenderMesh.h
|
||||
IResourceCollector.h
|
||||
IResourceCompilerHelper.h
|
||||
IResourceManager.h
|
||||
ISerialize.h
|
||||
IShader.h
|
||||
IShader_info.h
|
||||
ISoftCodeMgr.h
|
||||
ISplines.h
|
||||
IStatObj.h
|
||||
StatObjBus.h
|
||||
@@ -69,11 +64,8 @@ set(FILES
|
||||
IStreamEngineDefs.h
|
||||
ISurfaceType.h
|
||||
ISystem.h
|
||||
ISystemScheduler.h
|
||||
ITextModeConsole.h
|
||||
ITexture.h
|
||||
IThreadManager.h
|
||||
IThreadTask.h
|
||||
ITimer.h
|
||||
IValidator.h
|
||||
IVideoRenderer.h
|
||||
@@ -108,7 +100,6 @@ set(FILES
|
||||
MaterialUtils.h
|
||||
MTPseudoRandom.cpp
|
||||
CryTypeInfo.cpp
|
||||
IResourceCompilerHelper.cpp
|
||||
BaseTypes.h
|
||||
CompileTimeAssert.h
|
||||
CryThreadSafeWorkerContainer.h
|
||||
@@ -170,7 +161,6 @@ set(FILES
|
||||
PoolAllocator.h
|
||||
primitives.h
|
||||
primitives_info.h
|
||||
ProfileLog.h
|
||||
ProjectDefines.h
|
||||
Range.h
|
||||
RenderContextConfig.h
|
||||
|
||||
@@ -3244,7 +3244,6 @@ struct PhysicsVars
|
||||
int nBodiesLargeGroup;
|
||||
int bBreakOnValidation;
|
||||
int bLogActiveObjects;
|
||||
int bMultiplayer;
|
||||
int bProfileEntities;
|
||||
int bProfileFunx;
|
||||
int bProfileGroups;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define PLATFORM_IMPL_H_SECTION_VIRTUAL_ALLOCATORS 7
|
||||
#endif
|
||||
|
||||
SC_API struct SSystemGlobalEnvironment* gEnv = nullptr;
|
||||
struct SSystemGlobalEnvironment* gEnv = nullptr;
|
||||
|
||||
// Traits
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
@@ -147,7 +147,6 @@ void* GetDetachEnvironmentSymbol()
|
||||
#endif // !defined(SOFTCODE)
|
||||
|
||||
bool g_bProfilerEnabled = false;
|
||||
int g_iTraceAllocations = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// global random number generator used by cry_random functions
|
||||
|
||||
@@ -1044,11 +1044,9 @@ void CSystem::AutoDetectSpec(const bool detectResolution)
|
||||
unsigned int numSysCores(1), numProcCores(1);
|
||||
Win32SysInspect::GetNumCPUCores(numSysCores, numProcCores);
|
||||
CryLogAlways("--- Number of available cores: %d (out of %d)", numProcCores, numSysCores);
|
||||
const int numLogicalProcs = gEnv->pi.numLogicalProcessors;
|
||||
CryLogAlways("--- Number of logical processors: %d", numLogicalProcs);
|
||||
|
||||
// get CPU rating
|
||||
const int cpuRating = numLogicalProcs >= 8 ? 3 : (numLogicalProcs >= 6 ? 2 : 1);
|
||||
const int cpuRating = numProcCores >= 4 ? 3 : (numProcCores >= 3 ? 2 : 1);
|
||||
|
||||
// get GPU info
|
||||
unsigned int gpuVendorId(0), gpuDeviceId(0), totVidMem(0);
|
||||
|
||||
@@ -89,7 +89,6 @@ ly_add_target(
|
||||
Legacy::CrySystem.Static
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::CryCommon.EngineSettings.Static
|
||||
)
|
||||
|
||||
################################################################################
|
||||
@@ -109,7 +108,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
PRIVATE
|
||||
AZ::AzTest
|
||||
Legacy::CryCommon
|
||||
Legacy::CryCommon.EngineSettings.Static
|
||||
Legacy::CrySystem.Static
|
||||
AZ::AzFramework
|
||||
)
|
||||
|
||||
@@ -87,14 +87,6 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename)
|
||||
filename = PathUtil::ReplaceExtension(filename, "cfg");
|
||||
}
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool ignoreWhitelist = true;
|
||||
if (_stricmp(sFilename, "autoexec.cfg") == 0)
|
||||
{
|
||||
ignoreWhitelist = false;
|
||||
}
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CCryFile file;
|
||||
|
||||
@@ -179,18 +171,9 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename)
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
if (ignoreWhitelist || (gEnv->pSystem->GetCVarsWhiteList() && gEnv->pSystem->GetCVarsWhiteList()->IsWhiteListed(strLine, false)))
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
m_pConsole->ExecuteString(strLine);
|
||||
}
|
||||
#if defined(CVARS_WHITELIST)
|
||||
else if (gEnv->IsDedicated())
|
||||
{
|
||||
gEnv->pSystem->GetILog()->LogError("Failed to execute command: '%s' as it is not whitelisted\n", strLine.c_str());
|
||||
}
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
}
|
||||
// See above
|
||||
// ((CXConsole*)m_pConsole)->SetStatus(bConsoleStatus);
|
||||
|
||||
@@ -117,7 +117,6 @@ struct IRenderer;
|
||||
struct ISystem;
|
||||
struct ITimer;
|
||||
struct IFFont;
|
||||
struct IKeyboard;
|
||||
struct ICVar;
|
||||
struct IConsole;
|
||||
struct IProcess;
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: INTERNAL HEADER NOT FOR PUBLIC USE
|
||||
// This header should only be include by SystemThreading.cpp only
|
||||
// It provides an interface for PThread intrinsics
|
||||
// It's only client should be CThreadManager which should manage all thread interaction
|
||||
#if !defined(INCLUDED_FROM_SYSTEM_THREADING_CPP)
|
||||
# error "CRYTEK INTERNAL HEADER. ONLY INCLUDE FROM SYSTEMTHRADING.CPP."
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEFAULT_THREAD_STACK_SIZE_KB 0
|
||||
#define CRY_PTHREAD_THREAD_NAME_MAX 16
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// THREAD CREATION AND MANAGMENT
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace CryThreadUtil
|
||||
{
|
||||
// Define type for platform specific thread handle
|
||||
typedef pthread_t TThreadHandle;
|
||||
|
||||
struct SThreadCreationDesc
|
||||
{
|
||||
// Define platform specific thread entry function functor type
|
||||
typedef void* (* EntryFunc)(void*);
|
||||
|
||||
const char* szThreadName;
|
||||
EntryFunc fpEntryFunc;
|
||||
void* pArgList;
|
||||
uint32 nStackSizeInBytes;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
TThreadHandle CryGetCurrentThreadHandle()
|
||||
{
|
||||
return (TThreadHandle)pthread_self();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Note: Handle must be closed lated via CryCloseThreadHandle()
|
||||
TThreadHandle CryDuplicateThreadHandle(const TThreadHandle& hThreadHandle)
|
||||
{
|
||||
// Do not do anything
|
||||
// If you add a new platform which duplicates handles make sure to mirror the change in CryCloseThreadHandle(..)
|
||||
return hThreadHandle;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CryCloseThreadHandle(TThreadHandle& hThreadHandle)
|
||||
{
|
||||
pthread_detach(hThreadHandle);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CryGetCurrentThreadId()
|
||||
{
|
||||
return threadID(pthread_self());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CryGetThreadId(TThreadHandle hThreadHandle)
|
||||
{
|
||||
return threadID(hThreadHandle);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Note: On OSX the thread name can only be set by the thread itself.
|
||||
void CrySetThreadName(TThreadHandle pThreadHandle, const char* sThreadName)
|
||||
{
|
||||
char threadName[CRY_PTHREAD_THREAD_NAME_MAX];
|
||||
if (!cry_strcpy(threadName, sThreadName))
|
||||
{
|
||||
CryLog("<ThreadInfo> CrySetThreadName: input thread name '%s' truncated to '%s'", sThreadName, threadName);
|
||||
}
|
||||
#if AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
// On OSX the thread name can only be set by the thread itself.
|
||||
assert(pthread_equal(pthread_self(), (pthread_t )pThreadHandle));
|
||||
|
||||
if (pthread_setname_np(threadName) != 0)
|
||||
#else
|
||||
if (pthread_setname_np(pThreadHandle, threadName) != 0)
|
||||
#endif
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case ERANGE:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadName: Unable to rename thread \"%s\". Error Msg: \"Name to long. Exceeds %d bytes.\"", sThreadName, CRY_PTHREAD_THREAD_NAME_MAX);
|
||||
break;
|
||||
default:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadName: Unsupported error code: %i", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadAffinityMask(TThreadHandle pThreadHandle, DWORD dwAffinityMask)
|
||||
{
|
||||
#if defined(AZ_PLATFORM_ANDROID)
|
||||
// Not supported on ANDROID
|
||||
// Alternative solution
|
||||
// Watch out that android will clear the mask after a core has been switched off hence loosing the affinity mask setting!
|
||||
// http://stackoverflow.com/questions/16319725/android-set-thread-affinity
|
||||
#elif AZ_TRAIT_OS_PLATFORM_APPLE
|
||||
# pragma message "Warning: <ThreadInfo> CrySetThreadAffinityMask not implemented for platform"
|
||||
// Implementation details can be found here
|
||||
// https://developer.apple.com/library/mac/releasenotes/Performance/RN-AffinityAPI/
|
||||
#else
|
||||
cpu_set_t cpu_mask;
|
||||
CPU_ZERO(&cpu_mask);
|
||||
for (int cpu = 0; cpu < sizeof(cpu_mask) * 8; ++cpu)
|
||||
{
|
||||
if (dwAffinityMask & (1 << cpu))
|
||||
{
|
||||
CPU_SET(cpu, &cpu_mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (sched_setaffinity(0, sizeof(cpu_mask), &cpu_mask) != 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EFAULT:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadAffinityMask: Supplied memory address was invalid.");
|
||||
break;
|
||||
case EINVAL:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadAffinityMask: The affinity bit mask [%u] contains no processors that are currently physically on the system and permitted to the process .", dwAffinityMask);
|
||||
break;
|
||||
case EPERM:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadAffinityMask: The calling process does not have appropriate privileges. Mask [%u].", dwAffinityMask);
|
||||
break;
|
||||
case ESRCH:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadAffinityMask: The process whose ID is pid could not be found.");
|
||||
break;
|
||||
default:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> CrySetThreadAffinityMask: Unsupported error code: %i", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadPriority(TThreadHandle pThreadHandle, DWORD dwPriority)
|
||||
{
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
|
||||
pthread_getschedparam(pThreadHandle, &policy, ¶m);
|
||||
param.sched_priority = sched_get_priority_max(dwPriority);
|
||||
pthread_setschedparam(pThreadHandle, policy, ¶m);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadPriorityBoost(TThreadHandle pThreadHandle, bool bEnabled)
|
||||
{
|
||||
// Not supported
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CryCreateThread(TThreadHandle* pThreadHandle, const SThreadCreationDesc& threadDesc)
|
||||
{
|
||||
uint32 nStackSize = threadDesc.nStackSizeInBytes != 0 ? threadDesc.nStackSizeInBytes : DEFAULT_THREAD_STACK_SIZE_KB * 1024;
|
||||
|
||||
assert(pThreadHandle != reinterpret_cast<TThreadHandle*>(THREADID_NULL));
|
||||
pthread_attr_t threadAttr;
|
||||
sched_param schedParam;
|
||||
pthread_attr_init(&threadAttr);
|
||||
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE);
|
||||
pthread_attr_setstacksize(&threadAttr, nStackSize);
|
||||
|
||||
const int err = pthread_create(
|
||||
pThreadHandle,
|
||||
&threadAttr,
|
||||
threadDesc.fpEntryFunc,
|
||||
threadDesc.pArgList);
|
||||
|
||||
// Handle error on thread creation
|
||||
switch (err)
|
||||
{
|
||||
case 0:
|
||||
// No error
|
||||
break;
|
||||
case EAGAIN:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to create thread \"%s\". Error Msg: \"Insufficient resources to create another thread, or a system-imposed limit on the number of threads was encountered.\"", threadDesc.szThreadName);
|
||||
return false;
|
||||
case EINVAL:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to create thread \"%s\". Error Msg: \"Invalid attribute setting for thread creation.\"", threadDesc.szThreadName);
|
||||
return false;
|
||||
case EPERM:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to create thread \"%s\". Error Msg: \"No permission to set the scheduling policy and parameters specified in attribute setting\"", threadDesc.szThreadName);
|
||||
return false;
|
||||
default:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to create thread \"%s\". Unknown error message. Error code %i", threadDesc.szThreadName, err);
|
||||
break;
|
||||
}
|
||||
|
||||
// Print info to log
|
||||
CryComment("<ThreadInfo>: New thread \"%s\" | StackSize: %u(KB)", threadDesc.szThreadName, threadDesc.nStackSizeInBytes / 1024);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CryThreadExitCall()
|
||||
{
|
||||
// Notes on: pthread_exit
|
||||
// A thread that was create with pthread_create implicitly calls pthread_exit when the thread returns from its start routine (the function that was first called after a thread was created).
|
||||
// pthread_exit(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FLOATING POINT EXCEPTIONS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace CryThreadUtil
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
void EnableFloatExceptions(EFPE_Severity eFPESeverity)
|
||||
{
|
||||
// TODO:
|
||||
// Not implemented
|
||||
// for potential implementation see http://linux.die.net/man/3/feenableexcept
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void EnableFloatExceptions(threadID nThreadId, EFPE_Severity eFPESeverity)
|
||||
{
|
||||
// TODO:
|
||||
// Not implemented
|
||||
// for potential implementation see http://linux.die.net/man/3/feenableexcept
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint GetFloatingPointExceptionMask()
|
||||
{
|
||||
// Not implemented
|
||||
return ~0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetFloatingPointExceptionMask(uint nMask)
|
||||
{
|
||||
// Not implemented
|
||||
}
|
||||
}
|
||||
@@ -1,432 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: INTERNAL HEADER NOT FOR PUBLIC USE
|
||||
// This header should only be include by SystemThreading.cpp only
|
||||
// It provides an interface for WinApi intrinsics
|
||||
// It's only client should be CThreadManager which should manage all thread interaction
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
#define CRYTHREADUTIL_WIN32_THREAD_H_SECTION_1 1
|
||||
#define CRYTHREADUTIL_WIN32_THREAD_H_SECTION_2 2
|
||||
#endif
|
||||
|
||||
#if !defined(INCLUDED_FROM_SYSTEM_THREADING_CPP)
|
||||
# error "CRYTEK INTERNAL HEADER. ONLY INCLUDE FROM SYSTEMTHRADING.CPP."
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEFAULT_THREAD_STACK_SIZE_KB 0
|
||||
|
||||
// Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
||||
static string GetLastErrorAsString()
|
||||
{
|
||||
// Get the error message, if any.
|
||||
DWORD errorMessageID = GetLastError();
|
||||
if (errorMessageID == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION CRYTHREADUTIL_WIN32_THREAD_H_SECTION_1
|
||||
#include AZ_RESTRICTED_FILE(CryThreadUtil_win32_thread_h)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
LPSTR messageBuffer = nullptr;
|
||||
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), messageBuffer, 0, NULL);
|
||||
|
||||
string message(messageBuffer, size);
|
||||
|
||||
// Free the buffer.
|
||||
LocalFree(messageBuffer);
|
||||
|
||||
return message;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// THREAD CREATION AND MANAGMENT
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace CryThreadUtil
|
||||
{
|
||||
// Define type for platform specific thread handle
|
||||
typedef THREAD_HANDLE TThreadHandle;
|
||||
|
||||
struct SThreadCreationDesc
|
||||
{
|
||||
// Define platform specific thread entry function functor type
|
||||
typedef unsigned int(_stdcall * EntryFunc)(void*);
|
||||
|
||||
const char* szThreadName;
|
||||
EntryFunc fpEntryFunc;
|
||||
void* pArgList;
|
||||
uint32 nStackSizeInBytes;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
TThreadHandle CryGetCurrentThreadHandle()
|
||||
{
|
||||
return GetCurrentThread(); // most likely returns pseudo handle (0xfffffffe)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Note: Handle must be closed lated via CryCloseThreadHandle()
|
||||
TThreadHandle CryDuplicateThreadHandle(const TThreadHandle& hThreadHandle)
|
||||
{
|
||||
// NOTES:
|
||||
// GetCurrentThread() may return a psydo handle to the current thread
|
||||
// to avoid going into the slower kernel mode.
|
||||
// Hence the handle is useless when being used from an other thread.
|
||||
// - GetCurrentThread() -> 0xfffffffe
|
||||
// - GetCurrentProcess() -> 0xffffffff
|
||||
|
||||
HANDLE hRealHandle = 0;
|
||||
DuplicateHandle(GetCurrentProcess(), // Source Process Handle.
|
||||
hThreadHandle, // Source Handle to dup.
|
||||
GetCurrentProcess(), // Target Process Handle.
|
||||
&hRealHandle, // Target Handle pointer.
|
||||
0, // Options flag.
|
||||
TRUE, // Inheritable flag
|
||||
DUPLICATE_SAME_ACCESS); // Options
|
||||
|
||||
return (TThreadHandle)hRealHandle;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CryCloseThreadHandle(TThreadHandle& hThreadHandle)
|
||||
{
|
||||
if (hThreadHandle)
|
||||
{
|
||||
CloseHandle(hThreadHandle);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CryGetCurrentThreadId()
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CryGetThreadId(TThreadHandle hThreadHandle)
|
||||
{
|
||||
return GetThreadId(hThreadHandle);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadName(TThreadHandle pThreadHandle, const char* sThreadName)
|
||||
{
|
||||
const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
|
||||
struct SThreadNameDesc
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
};
|
||||
|
||||
SThreadNameDesc info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = sThreadName;
|
||||
info.dwThreadID = GetThreadId(pThreadHandle);
|
||||
info.dwFlags = 0;
|
||||
AZ_PUSH_DISABLE_WARNING(6312 6322, "-Wunknown-warning-option")
|
||||
// warning C6312: Possible infinite loop: use of the constant EXCEPTION_CONTINUE_EXECUTION in the exception-filter expression of a try-except
|
||||
// warning C6322: empty _except block
|
||||
__try
|
||||
{
|
||||
// Raise exception to set thread name for attached debugger
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except (GetExceptionCode() == MS_VC_EXCEPTION ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadAffinityMask(TThreadHandle pThreadHandle, DWORD dwAffinityMask)
|
||||
{
|
||||
SetThreadAffinityMask(pThreadHandle, dwAffinityMask);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadPriority(TThreadHandle pThreadHandle, DWORD dwPriority)
|
||||
{
|
||||
if (!SetThreadPriority(pThreadHandle, dwPriority))
|
||||
{
|
||||
string errMsg = GetLastErrorAsString();
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to set thread priority. System Error Msg: \"%s\"", errMsg.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CrySetThreadPriorityBoost(TThreadHandle pThreadHandle, bool bEnabled)
|
||||
{
|
||||
SetThreadPriorityBoost(pThreadHandle, !bEnabled);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CryCreateThread(TThreadHandle* pThreadHandle, const SThreadCreationDesc& threadDesc)
|
||||
{
|
||||
const uint32 nStackSize = threadDesc.nStackSizeInBytes != 0 ? threadDesc.nStackSizeInBytes : DEFAULT_THREAD_STACK_SIZE_KB * 1024;
|
||||
|
||||
// Create thread
|
||||
unsigned int threadId = 0;
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION CRYTHREADUTIL_WIN32_THREAD_H_SECTION_2
|
||||
#include AZ_RESTRICTED_FILE(CryThreadUtil_win32_thread_h)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
*pThreadHandle = (void*)_beginthreadex(NULL, nStackSize, threadDesc.fpEntryFunc, threadDesc.pArgList, CREATE_SUSPENDED, &threadId);
|
||||
#endif
|
||||
|
||||
if (!(*pThreadHandle))
|
||||
{
|
||||
string errMsg = GetLastErrorAsString();
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Unable to create thread \"%s\". System Error Msg: \"%s\"", threadDesc.szThreadName, errMsg.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start thread
|
||||
ResumeThread(*pThreadHandle);
|
||||
|
||||
// Print info to log
|
||||
CryComment("<ThreadInfo>: New thread \"%s\" | StackSize: %u(KB)", threadDesc.szThreadName, threadDesc.nStackSizeInBytes / 1024);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CryThreadExitCall()
|
||||
{
|
||||
// Note on: ExitThread() (from MSDN)
|
||||
// ExitThread is the preferred method of exiting a thread in C code.
|
||||
// However, in C++ code, the thread is exited before any destructor can be called or any other automatic cleanup can be performed.
|
||||
// Therefore, in C++ code, you should return from your thread function.
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FLOATING POINT EXCEPTIONS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace CryThreadUtil
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
void EnableFloatExceptions([[maybe_unused]] EFPE_Severity eFPESeverity)
|
||||
{
|
||||
AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
|
||||
|
||||
// Optimization
|
||||
// Enable DAZ/FZ
|
||||
// Denormals Are Zeros
|
||||
// Flush-to-Zero
|
||||
_controlfp(_DN_FLUSH, _MCW_DN);
|
||||
_mm_setcsr(_mm_getcsr() | _MM_FLUSH_ZERO_ON);
|
||||
|
||||
#ifndef _RELEASE
|
||||
if (eFPESeverity == eFPE_None)
|
||||
{
|
||||
// mask all floating exceptions off.
|
||||
_controlfp(_MCW_EM, _MCW_EM);
|
||||
_mm_setcsr(_mm_getcsr() | _MM_MASK_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear pending exceptions
|
||||
_fpreset();
|
||||
|
||||
if (eFPESeverity == eFPE_Basic)
|
||||
{
|
||||
// Enable:
|
||||
// - _EM_ZERODIVIDE
|
||||
// - _EM_INVALID
|
||||
//
|
||||
// Disable:
|
||||
// - _EM_DENORMAL
|
||||
// - _EM_OVERFLOW
|
||||
// - _EM_UNDERFLOW
|
||||
// - _EM_INEXACT
|
||||
|
||||
_controlfp(_EM_INEXACT | _EM_DENORMAL | _EM_UNDERFLOW | _EM_OVERFLOW, _MCW_EM);
|
||||
_mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | (_MM_MASK_DENORM | _MM_MASK_INEXACT | _MM_MASK_UNDERFLOW | _MM_MASK_OVERFLOW));
|
||||
|
||||
//_mm_setcsr(_mm_getcsr() & ~0x280);
|
||||
}
|
||||
|
||||
if (eFPESeverity == eFPE_All)
|
||||
{
|
||||
// Enable:
|
||||
// - _EM_ZERODIVIDE
|
||||
// - _EM_INVALID
|
||||
// - _EM_UNDERFLOW
|
||||
// - _EM_OVERFLOW
|
||||
//
|
||||
// Disable:
|
||||
// - _EM_INEXACT
|
||||
// - _EM_DENORMAL
|
||||
|
||||
_controlfp(_EM_INEXACT | _EM_DENORMAL, _MCW_EM);
|
||||
_mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | (_MM_MASK_INEXACT | _MM_MASK_DENORM));
|
||||
}
|
||||
}
|
||||
#endif // _RELEASE
|
||||
|
||||
AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void EnableFloatExceptions(threadID nThreadId, EFPE_Severity eFPESeverity)
|
||||
{
|
||||
if (eFPESeverity >= eFPE_LastEntry)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Floating Point Exception (FPE) severity is out of range. (%i)", eFPESeverity);
|
||||
}
|
||||
|
||||
// Check if the thread ID matches the current thread
|
||||
if (nThreadId == 0 || nThreadId == CryGetCurrentThreadId())
|
||||
{
|
||||
EnableFloatExceptions(eFPESeverity);
|
||||
return;
|
||||
}
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, true, nThreadId);
|
||||
|
||||
if (hThread == 0)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Unable to open thread. %p", hThread);
|
||||
return;
|
||||
}
|
||||
|
||||
SuspendThread(hThread);
|
||||
|
||||
CONTEXT ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
if (GetThreadContext(hThread, &ctx) == 0)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Unable to get thread context");
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_64BIT
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Note:
|
||||
// DO NOT USE ctx.FltSave.MxCsr ... SetThreadContext() will copy the value of ctx.MxCsr into it
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
DWORD& floatMxCsr = ctx.MxCsr; // Hold FPE Mask and Status for MMX (SSE) floating point registers
|
||||
WORD& floatControlWord = ctx.FltSave.ControlWord; // Hold FPE Mask for floating point registers
|
||||
#ifndef _RELEASE
|
||||
WORD& floatStatuslWord = ctx.FltSave.StatusWord; // Holds FPE Status for floating point registers
|
||||
#endif
|
||||
#else
|
||||
DWORD& floatMxCsr = *(DWORD*)(&ctx.ExtendedRegisters[24]); // Hold FPE Mask and Status for MMX (SSE) floating point registers
|
||||
DWORD& floatControlWord = ctx.FloatSave.ControlWord; // Hold FPE Mask for floating point registers
|
||||
DWORD& floatStatuslWord = ctx.FloatSave.StatusWord; // Holds FPE Status for floating point registers
|
||||
#endif
|
||||
|
||||
// Flush-To-Zero Mode
|
||||
// Two conditions must be met for FTZ processing to occur:
|
||||
// - The FTZ bit (bit 15) in the MXCSR register must be masked (value = 1).
|
||||
// - The underflow exception (bit 11) needs to be masked (value = 1).
|
||||
|
||||
// Set flush mode to zero mode
|
||||
floatControlWord = (floatControlWord & ~_MCW_DN) | _DN_FLUSH;
|
||||
floatMxCsr = (floatMxCsr & ~_MM_FLUSH_ZERO_MASK) | (_MM_FLUSH_ZERO_ON);
|
||||
|
||||
#ifndef _RELEASE
|
||||
|
||||
// Reset FPE bits
|
||||
floatControlWord = floatControlWord | _MCW_EM;
|
||||
floatMxCsr = floatMxCsr | _MM_MASK_MASK;
|
||||
|
||||
// Clear pending exceptions
|
||||
floatStatuslWord = floatStatuslWord & ~(_SW_INEXACT | _SW_UNDERFLOW | _SW_OVERFLOW | _SW_ZERODIVIDE | _SW_INVALID | _SW_DENORMAL);
|
||||
floatMxCsr = floatMxCsr & ~(_MM_EXCEPT_INEXACT | _MM_EXCEPT_UNDERFLOW | _MM_EXCEPT_OVERFLOW | _MM_EXCEPT_DIV_ZERO | _MM_EXCEPT_INVALID | _MM_EXCEPT_DENORM);
|
||||
|
||||
if (eFPESeverity == eFPE_Basic)
|
||||
{
|
||||
// Enable:
|
||||
// - _EM_ZERODIVIDE
|
||||
// - _EM_INVALID
|
||||
//
|
||||
// Disable:
|
||||
// - _EM_DENORMAL
|
||||
// - _EM_OVERFLOW
|
||||
// - _EM_UNDERFLOW
|
||||
// - _EM_INEXACT
|
||||
|
||||
floatControlWord = (floatControlWord & ~_MCW_EM) | (_EM_DENORMAL | _EM_INEXACT | EM_UNDERFLOW | _EM_OVERFLOW);
|
||||
floatMxCsr = (floatMxCsr & ~_MM_MASK_MASK) | (_MM_MASK_DENORM | _MM_MASK_INEXACT | _MM_MASK_UNDERFLOW | _MM_MASK_OVERFLOW);
|
||||
}
|
||||
|
||||
if (eFPESeverity == eFPE_All)
|
||||
{
|
||||
// Enable:
|
||||
// - _EM_ZERODIVIDE
|
||||
// - _EM_INVALID
|
||||
// - _EM_UNDERFLOW
|
||||
// - _EM_OVERFLOW
|
||||
//
|
||||
// Disable:
|
||||
// - _EM_INEXACT
|
||||
// - _EM_DENORMAL
|
||||
|
||||
floatControlWord = (floatControlWord & ~_MCW_EM) | (_EM_INEXACT | _EM_DENORMAL);
|
||||
floatMxCsr = (floatMxCsr & ~_MM_MASK_MASK) | (_MM_MASK_INEXACT | _MM_MASK_DENORM);
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
if (SetThreadContext(hThread, &ctx) == 0)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Error setting ThreadContext for ThreadID: %u", nThreadId);
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
return;
|
||||
}
|
||||
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint GetFloatingPointExceptionMask()
|
||||
{
|
||||
uint nMask = 0;
|
||||
_clearfp();
|
||||
_controlfp_s(&nMask, 0, 0);
|
||||
return nMask;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetFloatingPointExceptionMask(uint nMask)
|
||||
{
|
||||
uint temp = 0;
|
||||
_clearfp();
|
||||
const unsigned int kAllowedBits = _MCW_DN | _MCW_EM | _MCW_RC;
|
||||
_controlfp_s(&temp, nMask, kAllowedBits);
|
||||
}
|
||||
}
|
||||
@@ -1,926 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "DebugCallStack.h"
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
|
||||
#include <IConsole.h>
|
||||
#include <CryPath.h>
|
||||
#include <Pak/CryPakUtils.h>
|
||||
#include "System.h"
|
||||
|
||||
#include <AzCore/Debug/StackTracer.h>
|
||||
#include <AzCore/Debug/EventTraceDrillerBus.h>
|
||||
|
||||
#include "resource.h"
|
||||
__pragma(comment(lib, "version.lib"))
|
||||
|
||||
//! Needs one external of DLL handle.
|
||||
extern HMODULE gDLLHandle;
|
||||
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#define MAX_PATH_LENGTH 1024
|
||||
#define MAX_SYMBOL_LENGTH 512
|
||||
|
||||
static HWND hwndException = 0;
|
||||
static bool g_bUserDialog = true; // true=on crash show dialog box, false=supress user interaction
|
||||
|
||||
static int PrintException(EXCEPTION_POINTERS* pex);
|
||||
|
||||
static bool IsFloatingPointException(EXCEPTION_POINTERS* pex);
|
||||
|
||||
extern LONG WINAPI CryEngineExceptionFilterWER(struct _EXCEPTION_POINTERS* pExceptionPointers);
|
||||
extern LONG WINAPI CryEngineExceptionFilterMiniDump(struct _EXCEPTION_POINTERS* pExceptionPointers, const char* szDumpPath, MINIDUMP_TYPE mdumpValue);
|
||||
|
||||
//=============================================================================
|
||||
CONTEXT CaptureCurrentContext()
|
||||
{
|
||||
CONTEXT context;
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
RtlCaptureContext(&context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
LONG __stdcall CryUnhandledExceptionHandler(EXCEPTION_POINTERS* pex)
|
||||
{
|
||||
return DebugCallStack::instance()->handleException(pex);
|
||||
}
|
||||
|
||||
|
||||
BOOL CALLBACK EnumModules(
|
||||
PCSTR ModuleName,
|
||||
DWORD64 BaseOfDll,
|
||||
PVOID UserContext)
|
||||
{
|
||||
DebugCallStack::TModules& modules = *static_cast<DebugCallStack::TModules*>(UserContext);
|
||||
modules[(void*)BaseOfDll] = ModuleName;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
//=============================================================================
|
||||
// Class Statics
|
||||
//=============================================================================
|
||||
|
||||
// Return single instance of class.
|
||||
IDebugCallStack* IDebugCallStack::instance()
|
||||
{
|
||||
static DebugCallStack sInstance;
|
||||
return &sInstance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Sets up the symbols for functions in the debug file.
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
DebugCallStack::DebugCallStack()
|
||||
: prevExceptionHandler(0)
|
||||
, m_pSystem(0)
|
||||
, m_nSkipNumFunctions(0)
|
||||
, m_bCrash(false)
|
||||
, m_szBugMessage(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
DebugCallStack::~DebugCallStack()
|
||||
{
|
||||
}
|
||||
|
||||
void DebugCallStack::RemoveOldFiles()
|
||||
{
|
||||
RemoveFile("error.log");
|
||||
RemoveFile("error.bmp");
|
||||
RemoveFile("error.dmp");
|
||||
}
|
||||
|
||||
void DebugCallStack::RemoveFile(const char* szFileName)
|
||||
{
|
||||
FILE* pFile = nullptr;
|
||||
azfopen(&pFile, szFileName, "r");
|
||||
const bool bFileExists = (pFile != NULL);
|
||||
|
||||
if (bFileExists)
|
||||
{
|
||||
fclose(pFile);
|
||||
|
||||
WriteLineToLog("Removing file \"%s\"...", szFileName);
|
||||
if (remove(szFileName) == 0)
|
||||
{
|
||||
WriteLineToLog("File successfully removed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLineToLog("Couldn't remove file!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugCallStack::installErrorHandler(ISystem* pSystem)
|
||||
{
|
||||
m_pSystem = pSystem;
|
||||
prevExceptionHandler = (void*)SetUnhandledExceptionFilter(CryUnhandledExceptionHandler);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void DebugCallStack::SetUserDialogEnable(const bool bUserDialogEnable)
|
||||
{
|
||||
g_bUserDialog = bUserDialogEnable;
|
||||
}
|
||||
|
||||
|
||||
DWORD g_idDebugThreads[10];
|
||||
const char* g_nameDebugThreads[10];
|
||||
int g_nDebugThreads = 0;
|
||||
volatile int g_lockThreadDumpList = 0;
|
||||
|
||||
void MarkThisThreadForDebugging(const char* name)
|
||||
{
|
||||
EBUS_EVENT(AZ::Debug::EventTraceDrillerSetupBus, SetThreadName, AZStd::this_thread::get_id(), name);
|
||||
|
||||
WriteLock lock(g_lockThreadDumpList);
|
||||
DWORD id = GetCurrentThreadId();
|
||||
if (g_nDebugThreads == sizeof(g_idDebugThreads) / sizeof(g_idDebugThreads[0]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < g_nDebugThreads; i++)
|
||||
{
|
||||
if (g_idDebugThreads[i] == id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_nameDebugThreads[g_nDebugThreads] = name;
|
||||
g_idDebugThreads[g_nDebugThreads++] = id;
|
||||
((CSystem*)gEnv->pSystem)->EnableFloatExceptions(g_cvars.sys_float_exceptions);
|
||||
}
|
||||
|
||||
void UnmarkThisThreadFromDebugging()
|
||||
{
|
||||
WriteLock lock(g_lockThreadDumpList);
|
||||
DWORD id = GetCurrentThreadId();
|
||||
for (int i = g_nDebugThreads - 1; i >= 0; i--)
|
||||
{
|
||||
if (g_idDebugThreads[i] == id)
|
||||
{
|
||||
memmove(g_idDebugThreads + i, g_idDebugThreads + i + 1, (g_nDebugThreads - 1 - i) * sizeof(g_idDebugThreads[0]));
|
||||
memmove(g_nameDebugThreads + i, g_nameDebugThreads + i + 1, (g_nDebugThreads - 1 - i) * sizeof(g_nameDebugThreads[0]));
|
||||
--g_nDebugThreads;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern int prev_sys_float_exceptions;
|
||||
void UpdateFPExceptionsMaskForThreads()
|
||||
{
|
||||
int mask = -iszero(g_cvars.sys_float_exceptions);
|
||||
CONTEXT ctx;
|
||||
for (int i = 0; i < g_nDebugThreads; i++)
|
||||
{
|
||||
if (g_idDebugThreads[i] != GetCurrentThreadId())
|
||||
{
|
||||
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, TRUE, g_idDebugThreads[i]);
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
SuspendThread(hThread);
|
||||
GetThreadContext(hThread, &ctx);
|
||||
#ifndef WIN64
|
||||
(ctx.FloatSave.ControlWord |= 7) &= ~5 | mask;
|
||||
(*(WORD*)(ctx.ExtendedRegisters + 24) |= 0x280) &= ~0x280 | mask;
|
||||
#else
|
||||
(ctx.FltSave.ControlWord |= 7) &= ~5 | mask;
|
||||
(ctx.FltSave.MxCsr |= 0x280) &= ~0x280 | mask;
|
||||
#endif
|
||||
SetThreadContext(hThread, &ctx);
|
||||
ResumeThread(hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int DebugCallStack::handleException(EXCEPTION_POINTERS* exception_pointer)
|
||||
{
|
||||
if (gEnv == NULL)
|
||||
{
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
ResetFPU(exception_pointer);
|
||||
|
||||
prev_sys_float_exceptions = 0;
|
||||
const int cached_sys_float_exceptions = g_cvars.sys_float_exceptions;
|
||||
|
||||
((CSystem*)gEnv->pSystem)->EnableFloatExceptions(0);
|
||||
|
||||
if (g_cvars.sys_WER)
|
||||
{
|
||||
gEnv->pLog->FlushAndClose();
|
||||
return CryEngineExceptionFilterWER(exception_pointer);
|
||||
}
|
||||
|
||||
if (g_cvars.sys_no_crash_dialog)
|
||||
{
|
||||
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
|
||||
}
|
||||
|
||||
m_bCrash = true;
|
||||
|
||||
if (g_cvars.sys_no_crash_dialog)
|
||||
{
|
||||
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
|
||||
}
|
||||
|
||||
static bool firstTime = true;
|
||||
|
||||
if (g_cvars.sys_dump_aux_threads)
|
||||
{
|
||||
for (int i = 0; i < g_nDebugThreads; i++)
|
||||
{
|
||||
if (g_idDebugThreads[i] != GetCurrentThreadId())
|
||||
{
|
||||
SuspendThread(OpenThread(THREAD_ALL_ACCESS, TRUE, g_idDebugThreads[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// uninstall our exception handler.
|
||||
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)prevExceptionHandler);
|
||||
|
||||
if (!firstTime)
|
||||
{
|
||||
WriteLineToLog("Critical Exception! Called Multiple Times!");
|
||||
gEnv->pLog->FlushAndClose();
|
||||
// Exception called more then once.
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
// Print exception info:
|
||||
{
|
||||
char excCode[80];
|
||||
char excAddr[80];
|
||||
WriteLineToLog("<CRITICAL EXCEPTION>");
|
||||
sprintf_s(excAddr, "0x%04X:0x%p", exception_pointer->ContextRecord->SegCs, exception_pointer->ExceptionRecord->ExceptionAddress);
|
||||
sprintf_s(excCode, "0x%08X", exception_pointer->ExceptionRecord->ExceptionCode);
|
||||
WriteLineToLog("Exception: %s, at Address: %s", excCode, excAddr);
|
||||
|
||||
{
|
||||
IMemoryManager::SProcessMemInfo memInfo;
|
||||
if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
|
||||
{
|
||||
uint32 nMemUsage = (uint32)(memInfo.PagefileUsage / (1024 * 1024));
|
||||
WriteLineToLog("Virtual memory usage: %dMb", nMemUsage);
|
||||
}
|
||||
gEnv->szDebugStatus[SSystemGlobalEnvironment::MAX_DEBUG_STRING_LENGTH - 1] = '\0';
|
||||
WriteLineToLog("Debug Status: %s", gEnv->szDebugStatus);
|
||||
}
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
|
||||
const int ret = SubmitBug(exception_pointer);
|
||||
|
||||
if (ret != IDB_IGNORE)
|
||||
{
|
||||
CryEngineExceptionFilterWER(exception_pointer);
|
||||
}
|
||||
|
||||
gEnv->pLog->FlushAndClose();
|
||||
|
||||
if (exception_pointer->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
|
||||
{
|
||||
// This is non continuable exception. abort application now.
|
||||
exit(exception_pointer->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
|
||||
//typedef long (__stdcall *ExceptionFunc)(EXCEPTION_POINTERS*);
|
||||
//ExceptionFunc prevFunc = (ExceptionFunc)prevExceptionHandler;
|
||||
//return prevFunc( (EXCEPTION_POINTERS*)exception_pointer );
|
||||
if (ret == IDB_EXIT)
|
||||
{
|
||||
// Immediate exit.
|
||||
// on windows, exit() and _exit() do all sorts of things, unfortuantely
|
||||
// TerminateProcess is the only way to die.
|
||||
TerminateProcess(GetCurrentProcess(), exception_pointer->ExceptionRecord->ExceptionCode); // we crashed, so don't return a zero exit code!
|
||||
// on linux based systems, _exit will not call ATEXIT and other things, which makes it more suitable for termination in an emergency such
|
||||
// as an unhandled exception.
|
||||
// however, this function is a windows exception handler.
|
||||
}
|
||||
else if (ret == IDB_IGNORE)
|
||||
{
|
||||
#ifndef WIN64
|
||||
exception_pointer->ContextRecord->FloatSave.StatusWord &= ~31;
|
||||
exception_pointer->ContextRecord->FloatSave.ControlWord |= 7;
|
||||
(*(WORD*)(exception_pointer->ContextRecord->ExtendedRegisters + 24) &= 31) |= 0x1F80;
|
||||
#else
|
||||
exception_pointer->ContextRecord->FltSave.StatusWord &= ~31;
|
||||
exception_pointer->ContextRecord->FltSave.ControlWord |= 7;
|
||||
(exception_pointer->ContextRecord->FltSave.MxCsr &= 31) |= 0x1F80;
|
||||
#endif
|
||||
firstTime = true;
|
||||
prevExceptionHandler = (void*)SetUnhandledExceptionFilter(CryUnhandledExceptionHandler);
|
||||
g_cvars.sys_float_exceptions = cached_sys_float_exceptions;
|
||||
((CSystem*)gEnv->pSystem)->EnableFloatExceptions(g_cvars.sys_float_exceptions);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
// Continue;
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void DebugCallStack::ReportBug(const char* szErrorMessage)
|
||||
{
|
||||
WriteLineToLog("Reporting bug: %s", szErrorMessage);
|
||||
|
||||
m_szBugMessage = szErrorMessage;
|
||||
m_context = CaptureCurrentContext();
|
||||
SubmitBug(NULL);
|
||||
m_szBugMessage = NULL;
|
||||
}
|
||||
|
||||
void DebugCallStack::dumpCallStack(std::vector<string>& funcs)
|
||||
{
|
||||
WriteLineToLog("=============================================================================");
|
||||
int len = (int)funcs.size();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
const char* str = funcs[i].c_str();
|
||||
WriteLineToLog("%2d) %s", len - i, str);
|
||||
}
|
||||
WriteLineToLog("=============================================================================");
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void DebugCallStack::LogExceptionInfo(EXCEPTION_POINTERS* pex)
|
||||
{
|
||||
string path("");
|
||||
if ((gEnv) && (gEnv->pFileIO))
|
||||
{
|
||||
const char* logAlias = gEnv->pFileIO->GetAlias("@log@");
|
||||
if (!logAlias)
|
||||
{
|
||||
logAlias = gEnv->pFileIO->GetAlias("@root@");
|
||||
}
|
||||
if (logAlias)
|
||||
{
|
||||
path = logAlias;
|
||||
path += "/";
|
||||
}
|
||||
}
|
||||
|
||||
string fileName = path;
|
||||
fileName += "error.log";
|
||||
|
||||
struct stat fileInfo;
|
||||
string timeStamp;
|
||||
string backupPath;
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
backupPath = PathUtil::ToUnixPath(PathUtil::AddSlash(path + "DumpBackups"));
|
||||
gEnv->pFileIO->CreatePath(backupPath.c_str());
|
||||
|
||||
if (stat(fileName.c_str(), &fileInfo) == 0)
|
||||
{
|
||||
// Backup log
|
||||
tm creationTime;
|
||||
localtime_s(&creationTime, &fileInfo.st_mtime);
|
||||
char tempBuffer[32];
|
||||
strftime(tempBuffer, sizeof(tempBuffer), "%d %b %Y (%H %M %S)", &creationTime);
|
||||
timeStamp = tempBuffer;
|
||||
|
||||
string backupFileName = backupPath + timeStamp + " error.log";
|
||||
CopyFile(fileName.c_str(), backupFileName.c_str(), true);
|
||||
}
|
||||
}
|
||||
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, fileName.c_str(), "wt");
|
||||
|
||||
CDebugAllowFileAccess ignoreInvalidFileAccess;
|
||||
|
||||
static char errorString[s_iCallStackSize];
|
||||
errorString[0] = 0;
|
||||
|
||||
// Time and Version.
|
||||
char versionbuf[1024];
|
||||
azstrcpy(versionbuf, AZ_ARRAY_SIZE(versionbuf), "");
|
||||
PutVersion(versionbuf, AZ_ARRAY_SIZE(versionbuf));
|
||||
cry_strcat(errorString, versionbuf);
|
||||
cry_strcat(errorString, "\n");
|
||||
|
||||
char excCode[MAX_WARNING_LENGTH];
|
||||
char excAddr[80];
|
||||
char desc[1024];
|
||||
char excDesc[MAX_WARNING_LENGTH];
|
||||
|
||||
// make sure the mouse cursor is visible
|
||||
ShowCursor(TRUE);
|
||||
|
||||
const char* excName;
|
||||
if (m_bIsFatalError || !pex)
|
||||
{
|
||||
const char* const szMessage = m_bIsFatalError ? s_szFatalErrorCode : m_szBugMessage;
|
||||
excName = szMessage;
|
||||
cry_strcpy(excCode, szMessage);
|
||||
cry_strcpy(excAddr, "");
|
||||
cry_strcpy(desc, "");
|
||||
cry_strcpy(m_excModule, "");
|
||||
cry_strcpy(excDesc, szMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(excAddr, "0x%04X:0x%p", pex->ContextRecord->SegCs, pex->ExceptionRecord->ExceptionAddress);
|
||||
sprintf_s(excCode, "0x%08X", pex->ExceptionRecord->ExceptionCode);
|
||||
excName = TranslateExceptionCode(pex->ExceptionRecord->ExceptionCode);
|
||||
cry_strcpy(desc, "");
|
||||
sprintf_s(excDesc, "%s\r\n%s", excName, desc);
|
||||
|
||||
|
||||
if (pex->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
|
||||
{
|
||||
if (pex->ExceptionRecord->NumberParameters > 1)
|
||||
{
|
||||
ULONG_PTR iswrite = pex->ExceptionRecord->ExceptionInformation[0];
|
||||
DWORD64 accessAddr = pex->ExceptionRecord->ExceptionInformation[1];
|
||||
if (iswrite)
|
||||
{
|
||||
sprintf_s(desc, "Attempt to write data to address 0x%08llu\r\nThe memory could not be \"written\"", accessAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(desc, "Attempt to read from address 0x%08llu\r\nThe memory could not be \"read\"", accessAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WriteLineToLog("Exception Code: %s", excCode);
|
||||
WriteLineToLog("Exception Addr: %s", excAddr);
|
||||
WriteLineToLog("Exception Module: %s", m_excModule);
|
||||
WriteLineToLog("Exception Name : %s", excName);
|
||||
WriteLineToLog("Exception Description: %s", desc);
|
||||
|
||||
|
||||
cry_strcpy(m_excDesc, excDesc);
|
||||
cry_strcpy(m_excAddr, excAddr);
|
||||
cry_strcpy(m_excCode, excCode);
|
||||
|
||||
|
||||
char errs[32768];
|
||||
sprintf_s(errs, "Exception Code: %s\nException Addr: %s\nException Module: %s\nException Description: %s, %s\n",
|
||||
excCode, excAddr, m_excModule, excName, desc);
|
||||
|
||||
|
||||
IMemoryManager::SProcessMemInfo memInfo;
|
||||
if (gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memInfo))
|
||||
{
|
||||
char memoryString[256];
|
||||
double MB = 1024 * 1024;
|
||||
sprintf_s(memoryString, "Memory in use: %3.1fMB\n", (double)(memInfo.PagefileUsage) / MB);
|
||||
cry_strcat(errs, memoryString);
|
||||
}
|
||||
{
|
||||
const int tempStringSize = 256;
|
||||
char tempString[tempStringSize];
|
||||
|
||||
gEnv->szDebugStatus[SSystemGlobalEnvironment::MAX_DEBUG_STRING_LENGTH - 1] = '\0';
|
||||
sprintf_s(tempString, tempStringSize, "Debug Status: %s\n", gEnv->szDebugStatus);
|
||||
cry_strcat(errs, tempString);
|
||||
|
||||
sprintf_s(tempString, tempStringSize, "Out of Memory: %d\n", gEnv->bIsOutOfMemory);
|
||||
cry_strcat(errs, tempString);
|
||||
}
|
||||
cry_strcat(errs, "\nCall Stack Trace:\n");
|
||||
|
||||
std::vector<string> funcs;
|
||||
if (gEnv->bIsOutOfMemory)
|
||||
{
|
||||
cry_strcat(errs, "1) OUT_OF_MEMORY()\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::Debug::StackFrame frames[25];
|
||||
AZ::Debug::SymbolStorage::StackLine lines[AZ_ARRAY_SIZE(frames)];
|
||||
unsigned int numFrames = AZ::Debug::StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), 3);
|
||||
if (numFrames)
|
||||
{
|
||||
AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
|
||||
for (unsigned int i = 0; i < numFrames; i++)
|
||||
{
|
||||
funcs.push_back(lines[i]);
|
||||
}
|
||||
}
|
||||
dumpCallStack(funcs);
|
||||
// Fill call stack.
|
||||
char str[s_iCallStackSize];
|
||||
cry_strcpy(str, "");
|
||||
for (unsigned int i = 0; i < funcs.size(); i++)
|
||||
{
|
||||
char temp[s_iCallStackSize];
|
||||
sprintf_s(temp, "%2zd) %s", funcs.size() - i, (const char*)funcs[i].c_str());
|
||||
cry_strcat(str, temp);
|
||||
cry_strcat(str, "\r\n");
|
||||
cry_strcat(errs, temp);
|
||||
cry_strcat(errs, "\n");
|
||||
}
|
||||
cry_strcpy(m_excCallstack, str);
|
||||
}
|
||||
|
||||
cry_strcat(errorString, errs);
|
||||
|
||||
if (f)
|
||||
{
|
||||
fwrite(errorString, strlen(errorString), 1, f);
|
||||
if (!gEnv->bIsOutOfMemory)
|
||||
{
|
||||
if (g_cvars.sys_dump_aux_threads)
|
||||
{
|
||||
for (int i = 0; i < g_nDebugThreads; i++)
|
||||
{
|
||||
if (g_idDebugThreads[i] != GetCurrentThreadId())
|
||||
{
|
||||
fprintf(f, "\n\nSuspended thread (%s):\n", g_nameDebugThreads[i]);
|
||||
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, TRUE, g_idDebugThreads[i]);
|
||||
|
||||
// mirrors the AZ::Debug::Trace::PrintCallstack() functionality, but prints to a file
|
||||
{
|
||||
AZ::Debug::StackFrame frames[10];
|
||||
|
||||
// Without StackFrame explicit alignment frames array is aligned to 4 bytes
|
||||
// which causes the stack tracing to fail.
|
||||
AZ::Debug::SymbolStorage::StackLine lines[AZ_ARRAY_SIZE(frames)];
|
||||
|
||||
unsigned int numFrames = AZ::Debug::StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), 0, hThread);
|
||||
if (numFrames)
|
||||
{
|
||||
AZ::Debug::SymbolStorage::DecodeFrames(frames, numFrames, lines);
|
||||
for (unsigned int i2 = 0; i2 < numFrames; ++i2)
|
||||
{
|
||||
fprintf(f, "%2d) %s\n", numFrames - i2, lines[i2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResumeThread(hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (pex)
|
||||
{
|
||||
MINIDUMP_TYPE mdumpValue;
|
||||
bool bDump = true;
|
||||
switch (g_cvars.sys_dump_type)
|
||||
{
|
||||
case 0:
|
||||
bDump = false;
|
||||
break;
|
||||
case 1:
|
||||
mdumpValue = MiniDumpNormal;
|
||||
break;
|
||||
case 2:
|
||||
mdumpValue = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithDataSegs);
|
||||
break;
|
||||
case 3:
|
||||
mdumpValue = MiniDumpWithFullMemory;
|
||||
break;
|
||||
default:
|
||||
mdumpValue = (MINIDUMP_TYPE)g_cvars.sys_dump_type;
|
||||
break;
|
||||
}
|
||||
if (bDump)
|
||||
{
|
||||
fileName = path + "error.dmp";
|
||||
|
||||
if (gEnv->IsDedicated() && stat(fileName.c_str(), &fileInfo) == 0)
|
||||
{
|
||||
// Backup dump (use timestamp from error.log if available)
|
||||
if (timeStamp.empty())
|
||||
{
|
||||
tm creationTime;
|
||||
localtime_s(&creationTime, &fileInfo.st_mtime);
|
||||
char tempBuffer[32];
|
||||
strftime(tempBuffer, sizeof(tempBuffer), "%d %b %Y (%H %M %S)", &creationTime);
|
||||
timeStamp = tempBuffer;
|
||||
}
|
||||
|
||||
string backupFileName = backupPath + timeStamp + " error.dmp";
|
||||
CopyFile(fileName.c_str(), backupFileName.c_str(), true);
|
||||
}
|
||||
|
||||
CryEngineExceptionFilterMiniDump(pex, fileName.c_str(), mdumpValue);
|
||||
}
|
||||
}
|
||||
|
||||
//if no crash dialog don't even submit the bug
|
||||
if (m_postBackupProcess && g_cvars.sys_no_crash_dialog == 0 && g_bUserDialog)
|
||||
{
|
||||
m_postBackupProcess();
|
||||
}
|
||||
else
|
||||
{
|
||||
// lawsonn: Disabling the JIRA-based crash reporter for now
|
||||
// we'll need to deal with it our own way, pending QA.
|
||||
// if you're customizing the engine this is also your opportunity to deal with it.
|
||||
if (g_cvars.sys_no_crash_dialog != 0 || !g_bUserDialog)
|
||||
{
|
||||
// ------------ place custom crash handler here ---------------------
|
||||
// it should launch an executable!
|
||||
/// by this time, error.bmp will be in the engine root folder
|
||||
// error.log and error.dmp will also be present in the engine root folder
|
||||
// if your error dumper wants those, it should zip them up and send them or offer to do so.
|
||||
// ------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
const bool bQuitting = !gEnv || !gEnv->pSystem || gEnv->pSystem->IsQuitting();
|
||||
|
||||
//[AlexMcC|16.04.10] When the engine is shutting down, MessageBox doesn't display a box
|
||||
// and immediately returns IDYES. Avoid this by just not trying to save if we're quitting.
|
||||
// Don't ask to save if this isn't a real crash (a real crash has exception pointers)
|
||||
if (g_cvars.sys_no_crash_dialog == 0 && g_bUserDialog && gEnv->IsEditor() && !bQuitting && pex)
|
||||
{
|
||||
BackupCurrentLevel();
|
||||
|
||||
const INT_PTR res = DialogBoxParam(gDLLHandle, MAKEINTRESOURCE(IDD_CONFIRM_SAVE_LEVEL), NULL, DebugCallStack::ConfirmSaveDialogProc, NULL);
|
||||
if (res == IDB_CONFIRM_SAVE)
|
||||
{
|
||||
if (SaveCurrentLevel())
|
||||
{
|
||||
MessageBox(NULL, "Level has been successfully saved!\r\nPress Ok to terminate Editor.", "Save", MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox(NULL, "Error saving level.\r\nPress Ok to terminate Editor.", "Save", MB_OK | MB_ICONWARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cvars.sys_no_crash_dialog != 0 || !g_bUserDialog)
|
||||
{
|
||||
// terminate immediately - since we're in a crash, there is no point unwinding stack, we've already done access violation or worse.
|
||||
// calling exit will only cause further death down the line...
|
||||
TerminateProcess(GetCurrentProcess(), pex->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INT_PTR CALLBACK DebugCallStack::ExceptionDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static EXCEPTION_POINTERS* pex;
|
||||
|
||||
static char errorString[32768] = "";
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
pex = (EXCEPTION_POINTERS*)lParam;
|
||||
HWND h;
|
||||
|
||||
if (pex->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
|
||||
{
|
||||
// Disable continue button for non continuable exceptions.
|
||||
//h = GetDlgItem( hwndDlg,IDB_CONTINUE );
|
||||
//if (h) EnableWindow( h,FALSE );
|
||||
}
|
||||
|
||||
DebugCallStack* pDCS = static_cast<DebugCallStack*>(DebugCallStack::instance());
|
||||
|
||||
h = GetDlgItem(hwndDlg, IDC_EXCEPTION_DESC);
|
||||
if (h)
|
||||
{
|
||||
SendMessage(h, EM_REPLACESEL, FALSE, (LONG_PTR)pDCS->m_excDesc);
|
||||
}
|
||||
|
||||
h = GetDlgItem(hwndDlg, IDC_EXCEPTION_CODE);
|
||||
if (h)
|
||||
{
|
||||
SendMessage(h, EM_REPLACESEL, FALSE, (LONG_PTR)pDCS->m_excCode);
|
||||
}
|
||||
|
||||
h = GetDlgItem(hwndDlg, IDC_EXCEPTION_MODULE);
|
||||
if (h)
|
||||
{
|
||||
SendMessage(h, EM_REPLACESEL, FALSE, (LONG_PTR)pDCS->m_excModule);
|
||||
}
|
||||
|
||||
h = GetDlgItem(hwndDlg, IDC_EXCEPTION_ADDRESS);
|
||||
if (h)
|
||||
{
|
||||
SendMessage(h, EM_REPLACESEL, FALSE, (LONG_PTR)pDCS->m_excAddr);
|
||||
}
|
||||
|
||||
// Fill call stack.
|
||||
HWND callStack = GetDlgItem(hwndDlg, IDC_CALLSTACK);
|
||||
if (callStack)
|
||||
{
|
||||
SendMessage(callStack, WM_SETTEXT, FALSE, (LPARAM)pDCS->m_excCallstack);
|
||||
}
|
||||
|
||||
if (hwndException)
|
||||
{
|
||||
DestroyWindow(hwndException);
|
||||
hwndException = 0;
|
||||
}
|
||||
|
||||
if (IsFloatingPointException(pex))
|
||||
{
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDB_IGNORE), TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDB_EXIT:
|
||||
case IDB_IGNORE:
|
||||
// Fall through.
|
||||
|
||||
EndDialog(hwndDlg, wParam);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK DebugCallStack::ConfirmSaveDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, [[maybe_unused]] LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
// The user might be holding down the spacebar while the engine crashes.
|
||||
// If we don't remove keyboard focus from this dialog, the keypress will
|
||||
// press the default button before the dialog actually appears, even if
|
||||
// the user has already released the key, which is bad.
|
||||
SetFocus(NULL);
|
||||
} break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDB_CONFIRM_SAVE: // Fall through
|
||||
case IDB_DONT_SAVE:
|
||||
{
|
||||
EndDialog(hwndDlg, wParam);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool DebugCallStack::BackupCurrentLevel()
|
||||
{
|
||||
CSystem* pSystem = static_cast<CSystem*>(m_pSystem);
|
||||
if (pSystem && pSystem->GetUserCallback())
|
||||
{
|
||||
return pSystem->GetUserCallback()->OnBackupDocument();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DebugCallStack::SaveCurrentLevel()
|
||||
{
|
||||
CSystem* pSystem = static_cast<CSystem*>(m_pSystem);
|
||||
if (pSystem && pSystem->GetUserCallback())
|
||||
{
|
||||
return pSystem->GetUserCallback()->OnSaveDocument();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int DebugCallStack::SubmitBug(EXCEPTION_POINTERS* exception_pointer)
|
||||
{
|
||||
int ret = IDB_EXIT;
|
||||
|
||||
assert(!hwndException);
|
||||
|
||||
RemoveOldFiles();
|
||||
|
||||
AZ::Debug::Trace::PrintCallstack("", 2);
|
||||
|
||||
LogExceptionInfo(exception_pointer);
|
||||
|
||||
if (IsFloatingPointException(exception_pointer))
|
||||
{
|
||||
//! Print exception dialog.
|
||||
ret = PrintException(exception_pointer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DebugCallStack::ResetFPU(EXCEPTION_POINTERS* pex)
|
||||
{
|
||||
if (IsFloatingPointException(pex))
|
||||
{
|
||||
// How to reset FPU: http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_10310953.html
|
||||
_clearfp();
|
||||
#ifndef WIN64
|
||||
pex->ContextRecord->FloatSave.ControlWord |= 0x2F;
|
||||
pex->ContextRecord->FloatSave.StatusWord &= ~0x8080;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
string DebugCallStack::GetModuleNameForAddr(void* addr)
|
||||
{
|
||||
if (m_modules.empty())
|
||||
{
|
||||
return "[unknown]";
|
||||
}
|
||||
|
||||
if (addr < m_modules.begin()->first)
|
||||
{
|
||||
return "[unknown]";
|
||||
}
|
||||
|
||||
TModules::const_iterator it = m_modules.begin();
|
||||
TModules::const_iterator end = m_modules.end();
|
||||
for (; ++it != end; )
|
||||
{
|
||||
if (addr < it->first)
|
||||
{
|
||||
return (--it)->second;
|
||||
}
|
||||
}
|
||||
|
||||
//if address is higher than the last module, we simply assume it is in the last module.
|
||||
return m_modules.rbegin()->second;
|
||||
}
|
||||
|
||||
void DebugCallStack::GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line)
|
||||
{
|
||||
AZ::Debug::SymbolStorage::StackLine func, file, module;
|
||||
AZ::Debug::SymbolStorage::FindFunctionFromIP(addr, &func, &file, &module, line, baseAddr);
|
||||
procName = func;
|
||||
filename = file;
|
||||
}
|
||||
|
||||
string DebugCallStack::GetCurrentFilename()
|
||||
{
|
||||
char fullpath[MAX_PATH_LENGTH + 1];
|
||||
GetModuleFileName(NULL, fullpath, MAX_PATH_LENGTH);
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
static bool IsFloatingPointException(EXCEPTION_POINTERS* pex)
|
||||
{
|
||||
if (!pex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD exceptionCode = pex->ExceptionRecord->ExceptionCode;
|
||||
switch (exceptionCode)
|
||||
{
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
case STATUS_FLOAT_MULTIPLE_FAULTS:
|
||||
case STATUS_FLOAT_MULTIPLE_TRAPS:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int DebugCallStack::PrintException(EXCEPTION_POINTERS* exception_pointer)
|
||||
{
|
||||
return (int)DialogBoxParam(gDLLHandle, MAKEINTRESOURCE(IDD_CRITICAL_ERROR), NULL, DebugCallStack::ExceptionDialogProc, (LPARAM)exception_pointer);
|
||||
}
|
||||
|
||||
#else
|
||||
void MarkThisThreadForDebugging(const char*) {}
|
||||
void UnmarkThisThreadFromDebugging() {}
|
||||
void UpdateFPExceptionsMaskForThreads() {}
|
||||
#endif //WIN32
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_DEBUGCALLSTACK_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_DEBUGCALLSTACK_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "IDebugCallStack.h"
|
||||
|
||||
#if defined (WIN32) || defined (WIN64)
|
||||
|
||||
//! Limits the maximal number of functions in call stack.
|
||||
const int MAX_DEBUG_STACK_ENTRIES_FILE_DUMP = 12;
|
||||
|
||||
struct ISystem;
|
||||
|
||||
//!============================================================================
|
||||
//!
|
||||
//! DebugCallStack class, capture call stack information from symbol files.
|
||||
//!
|
||||
//!============================================================================
|
||||
class DebugCallStack
|
||||
: public IDebugCallStack
|
||||
{
|
||||
public:
|
||||
DebugCallStack();
|
||||
virtual ~DebugCallStack();
|
||||
|
||||
ISystem* GetSystem() { return m_pSystem; };
|
||||
|
||||
virtual string GetModuleNameForAddr(void* addr);
|
||||
virtual void GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line);
|
||||
virtual string GetCurrentFilename();
|
||||
|
||||
void installErrorHandler(ISystem* pSystem);
|
||||
virtual int handleException(EXCEPTION_POINTERS* exception_pointer);
|
||||
|
||||
virtual void ReportBug(const char*);
|
||||
|
||||
void dumpCallStack(std::vector<string>& functions);
|
||||
|
||||
void SetUserDialogEnable(const bool bUserDialogEnable);
|
||||
|
||||
typedef std::map<void*, string> TModules;
|
||||
protected:
|
||||
static void RemoveOldFiles();
|
||||
static void RemoveFile(const char* szFileName);
|
||||
|
||||
static int PrintException(EXCEPTION_POINTERS* exception_pointer);
|
||||
static INT_PTR CALLBACK ExceptionDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
static INT_PTR CALLBACK ConfirmSaveDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void LogExceptionInfo(EXCEPTION_POINTERS* exception_pointer);
|
||||
bool BackupCurrentLevel();
|
||||
bool SaveCurrentLevel();
|
||||
int SubmitBug(EXCEPTION_POINTERS* exception_pointer);
|
||||
void ResetFPU(EXCEPTION_POINTERS* pex);
|
||||
|
||||
static const int s_iCallStackSize = 32768;
|
||||
|
||||
char m_excLine[256];
|
||||
char m_excModule[128];
|
||||
|
||||
char m_excDesc[MAX_WARNING_LENGTH];
|
||||
char m_excCode[MAX_WARNING_LENGTH];
|
||||
char m_excAddr[80];
|
||||
char m_excCallstack[s_iCallStackSize];
|
||||
|
||||
void* prevExceptionHandler;
|
||||
|
||||
bool m_bCrash;
|
||||
const char* m_szBugMessage;
|
||||
|
||||
ISystem* m_pSystem;
|
||||
|
||||
int m_nSkipNumFunctions;
|
||||
CONTEXT m_context;
|
||||
|
||||
TModules m_modules;
|
||||
};
|
||||
|
||||
#endif //WIN32
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_DEBUGCALLSTACK_H
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "System.h"
|
||||
#include <AZCrySystemInitLogSink.h>
|
||||
#include "DebugCallStack.h"
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
@@ -72,10 +71,6 @@ public:
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESYSTEM_EVENT_LEVEL_UNLOAD:
|
||||
gEnv->pSystem->SetThreadState(ESubsys_Physics, false);
|
||||
break;
|
||||
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_START:
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_END:
|
||||
{
|
||||
@@ -87,7 +82,6 @@ public:
|
||||
{
|
||||
CryCleanup();
|
||||
STLALLOCATOR_CLEANUP;
|
||||
gEnv->pSystem->SetThreadState(ESubsys_Physics, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,21 +129,6 @@ CRYSYSTEM_API ISystem* CreateSystemInterface(const SSystemInitParams& startupPar
|
||||
startupParams.pUserCallback->OnSystemConnect(pSystem);
|
||||
}
|
||||
|
||||
// Environment Variable to signal we don't want to override our exception handler - our crash report system will set this
|
||||
auto envVar = AZ::Environment::FindVariable<bool>("ExceptionHandlerIsSet");
|
||||
bool handlerIsSet = (envVar && *envVar);
|
||||
|
||||
if (!startupParams.bMinimal && !handlerIsSet) // in minimal mode, we want to crash when we crash!
|
||||
{
|
||||
#if defined(WIN32)
|
||||
// Install exception handler in Release modes.
|
||||
((DebugCallStack*)IDebugCallStack::instance())->installErrorHandler(pSystem);
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION DLLMAIN_CPP_SECTION_3
|
||||
#include AZ_RESTRICTED_FILE(DllMain_cpp)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool retVal = false;
|
||||
{
|
||||
AZ::Debug::StartupLogSinkReporter<AZ::Debug::CrySystemInitLogSink> initLogSink;
|
||||
@@ -171,20 +150,5 @@ CRYSYSTEM_API ISystem* CreateSystemInterface(const SSystemInitParams& startupPar
|
||||
|
||||
return pSystem;
|
||||
}
|
||||
|
||||
CRYSYSTEM_API void WINAPI CryInstallUnhandledExceptionHandler()
|
||||
{
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION DLLMAIN_CPP_SECTION_4
|
||||
#include AZ_RESTRICTED_FILE(DllMain_cpp)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ENABLE_PROFILING_CODE) && !defined(LINUX) && !defined(APPLE)
|
||||
CRYSYSTEM_API void CryInstallPostExceptionHandler(void (* PostExceptionHandlerCallback)())
|
||||
{
|
||||
return IDebugCallStack::instance()->FileCreationCallback(PostExceptionHandlerCallback);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : A multiplatform base class for handling errors and collecting call stacks
|
||||
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "IDebugCallStack.h"
|
||||
#include <Pak/CryPakUtils.h>
|
||||
#include "System.h"
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
//#if !defined(LINUX)
|
||||
|
||||
#include <ISystem.h>
|
||||
|
||||
const char* const IDebugCallStack::s_szFatalErrorCode = "FATAL_ERROR";
|
||||
|
||||
IDebugCallStack::IDebugCallStack()
|
||||
: m_bIsFatalError(false)
|
||||
, m_postBackupProcess(0)
|
||||
, m_memAllocFileHandle(AZ::IO::InvalidHandle)
|
||||
{
|
||||
}
|
||||
|
||||
IDebugCallStack::~IDebugCallStack()
|
||||
{
|
||||
StopMemLog();
|
||||
}
|
||||
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_SINGLETON
|
||||
IDebugCallStack* IDebugCallStack::instance()
|
||||
{
|
||||
static IDebugCallStack sInstance;
|
||||
return &sInstance;
|
||||
}
|
||||
#endif
|
||||
|
||||
void IDebugCallStack::FileCreationCallback(void (* postBackupProcess)())
|
||||
{
|
||||
m_postBackupProcess = postBackupProcess;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void IDebugCallStack::LogCallstack()
|
||||
{
|
||||
AZ::Debug::Trace::PrintCallstack("", 2);
|
||||
}
|
||||
|
||||
const char* IDebugCallStack::TranslateExceptionCode(DWORD dwExcept)
|
||||
{
|
||||
switch (dwExcept)
|
||||
{
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_TRANSLATE
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
return "EXCEPTION_ACCESS_VIOLATION";
|
||||
break;
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
return "EXCEPTION_DATATYPE_MISALIGNMENT";
|
||||
break;
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
return "EXCEPTION_BREAKPOINT";
|
||||
break;
|
||||
case EXCEPTION_SINGLE_STEP:
|
||||
return "EXCEPTION_SINGLE_STEP";
|
||||
break;
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
|
||||
break;
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
return "EXCEPTION_FLT_DENORMAL_OPERAND";
|
||||
break;
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
|
||||
break;
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
return "EXCEPTION_FLT_INEXACT_RESULT";
|
||||
break;
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
return "EXCEPTION_FLT_INVALID_OPERATION";
|
||||
break;
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
return "EXCEPTION_FLT_OVERFLOW";
|
||||
break;
|
||||
case EXCEPTION_FLT_STACK_CHECK:
|
||||
return "EXCEPTION_FLT_STACK_CHECK";
|
||||
break;
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
return "EXCEPTION_FLT_UNDERFLOW";
|
||||
break;
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
return "EXCEPTION_INT_DIVIDE_BY_ZERO";
|
||||
break;
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
return "EXCEPTION_INT_OVERFLOW";
|
||||
break;
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
return "EXCEPTION_PRIV_INSTRUCTION";
|
||||
break;
|
||||
case EXCEPTION_IN_PAGE_ERROR:
|
||||
return "EXCEPTION_IN_PAGE_ERROR";
|
||||
break;
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
return "EXCEPTION_ILLEGAL_INSTRUCTION";
|
||||
break;
|
||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||
return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
return "EXCEPTION_STACK_OVERFLOW";
|
||||
break;
|
||||
case EXCEPTION_INVALID_DISPOSITION:
|
||||
return "EXCEPTION_INVALID_DISPOSITION";
|
||||
break;
|
||||
case EXCEPTION_GUARD_PAGE:
|
||||
return "EXCEPTION_GUARD_PAGE";
|
||||
break;
|
||||
case EXCEPTION_INVALID_HANDLE:
|
||||
return "EXCEPTION_INVALID_HANDLE";
|
||||
break;
|
||||
//case EXCEPTION_POSSIBLE_DEADLOCK: return "EXCEPTION_POSSIBLE_DEADLOCK"; break ;
|
||||
|
||||
case STATUS_FLOAT_MULTIPLE_FAULTS:
|
||||
return "STATUS_FLOAT_MULTIPLE_FAULTS";
|
||||
break;
|
||||
case STATUS_FLOAT_MULTIPLE_TRAPS:
|
||||
return "STATUS_FLOAT_MULTIPLE_TRAPS";
|
||||
break;
|
||||
|
||||
|
||||
#endif
|
||||
default:
|
||||
return "Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void IDebugCallStack::PutVersion(char* str, size_t length)
|
||||
{
|
||||
AZ_PUSH_DISABLE_WARNING(4996, "-Wunknown-warning-option")
|
||||
|
||||
if (!gEnv || !gEnv->pSystem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char sFileVersion[128];
|
||||
gEnv->pSystem->GetFileVersion().ToString(sFileVersion, sizeof(sFileVersion));
|
||||
|
||||
char sProductVersion[128];
|
||||
gEnv->pSystem->GetProductVersion().ToString(sProductVersion, sizeof(sFileVersion));
|
||||
|
||||
|
||||
//! Get time.
|
||||
time_t ltime;
|
||||
time(<ime);
|
||||
tm* today = localtime(<ime);
|
||||
|
||||
char s[1024];
|
||||
//! Use strftime to build a customized time string.
|
||||
strftime(s, 128, "Logged at %#c\n", today);
|
||||
azstrcat(str, length, s);
|
||||
sprintf_s(s, "FileVersion: %s\n", sFileVersion);
|
||||
azstrcat(str, length, s);
|
||||
sprintf_s(s, "ProductVersion: %s\n", sProductVersion);
|
||||
azstrcat(str, length, s);
|
||||
|
||||
if (gEnv->pLog)
|
||||
{
|
||||
const char* logfile = gEnv->pLog->GetFileName();
|
||||
if (logfile)
|
||||
{
|
||||
sprintf (s, "LogFile: %s\n", logfile);
|
||||
azstrcat(str, length, s);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
azstrcat(str, length, "ProjectDir: ");
|
||||
azstrcat(str, length, projectPath.c_str());
|
||||
azstrcat(str, length, "\n");
|
||||
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_DEBUGCALLSTACK_APPEND_MODULENAME
|
||||
GetModuleFileNameA(NULL, s, sizeof(s));
|
||||
|
||||
// Log EXE filename only if possible (not full EXE path which could contain sensitive info)
|
||||
AZStd::string exeName;
|
||||
if (AZ::StringFunc::Path::GetFullFileName(s, exeName))
|
||||
{
|
||||
azstrcat(str, length, "Executable: ");
|
||||
azstrcat(str, length, exeName.c_str());
|
||||
|
||||
# ifdef AZ_DEBUG_BUILD
|
||||
azstrcat(str, length, " (debug: yes");
|
||||
# else
|
||||
azstrcat(str, length, " (debug: no");
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
|
||||
|
||||
//Crash the application, in this way the debug callstack routine will be called and it will create all the necessary files (error.log, dump, and eventually screenshot)
|
||||
void IDebugCallStack::FatalError(const char* description)
|
||||
{
|
||||
m_bIsFatalError = true;
|
||||
WriteLineToLog(description);
|
||||
|
||||
#ifndef _RELEASE
|
||||
bool bShowDebugScreen = g_cvars.sys_no_crash_dialog == 0;
|
||||
// showing the debug screen is not safe when not called from mainthread
|
||||
// it normally leads to a infinity recursion followed by a stack overflow, preventing
|
||||
// useful call stacks, thus they are disabled
|
||||
bShowDebugScreen = bShowDebugScreen && gEnv->mMainThreadId == CryGetCurrentThreadId();
|
||||
if (bShowDebugScreen)
|
||||
{
|
||||
EBUS_EVENT(AZ::NativeUI::NativeUIRequestBus, DisplayOkDialog, "Open 3D Engine Fatal Error", description, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || !defined(_RELEASE)
|
||||
int* p = 0x0;
|
||||
PREFAST_SUPPRESS_WARNING(6011) * p = 1; // we're intentionally crashing here
|
||||
#endif
|
||||
}
|
||||
|
||||
void IDebugCallStack::WriteLineToLog(const char* format, ...)
|
||||
{
|
||||
CDebugAllowFileAccess allowFileAccess;
|
||||
|
||||
va_list ArgList;
|
||||
char szBuffer[MAX_WARNING_LENGTH];
|
||||
va_start(ArgList, format);
|
||||
vsnprintf_s(szBuffer, sizeof(szBuffer), sizeof(szBuffer) - 1, format, ArgList);
|
||||
cry_strcat(szBuffer, "\n");
|
||||
szBuffer[sizeof(szBuffer) - 1] = '\0';
|
||||
va_end(ArgList);
|
||||
|
||||
AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@Log@\\error.log", AZ::IO::GetOpenModeFromStringMode("a+t"), fileHandle);
|
||||
if (fileHandle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Write(fileHandle, szBuffer, strlen(szBuffer));
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Flush(fileHandle);
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Close(fileHandle);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void IDebugCallStack::StartMemLog()
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open("@Log@\\memallocfile.log", AZ::IO::OpenMode::ModeWrite, m_memAllocFileHandle);
|
||||
|
||||
assert(m_memAllocFileHandle != AZ::IO::InvalidHandle);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void IDebugCallStack::StopMemLog()
|
||||
{
|
||||
if (m_memAllocFileHandle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Close(m_memAllocFileHandle);
|
||||
m_memAllocFileHandle = AZ::IO::InvalidHandle;
|
||||
}
|
||||
}
|
||||
//#endif //!defined(LINUX)
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : A multiplatform base class for handling errors and collecting call stacks
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_IDEBUGCALLSTACK_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_IDEBUGCALLSTACK_H
|
||||
#pragma once
|
||||
|
||||
#include "System.h"
|
||||
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_FORWARD_EXCEPTION_POINTERS
|
||||
struct EXCEPTION_POINTERS;
|
||||
#endif
|
||||
//! Limits the maximal number of functions in call stack.
|
||||
enum
|
||||
{
|
||||
MAX_DEBUG_STACK_ENTRIES = 80
|
||||
};
|
||||
|
||||
class IDebugCallStack
|
||||
{
|
||||
public:
|
||||
// Returns single instance of DebugStack
|
||||
static IDebugCallStack* instance();
|
||||
|
||||
virtual int handleException([[maybe_unused]] EXCEPTION_POINTERS* exception_pointer){return 0; }
|
||||
|
||||
// returns the module name of a given address
|
||||
virtual string GetModuleNameForAddr([[maybe_unused]] void* addr) { return "[unknown]"; }
|
||||
|
||||
// returns the function name of a given address together with source file and line number (if available) of a given address
|
||||
virtual void GetProcNameForAddr(void* addr, string& procName, void*& baseAddr, string& filename, int& line)
|
||||
{
|
||||
filename = "[unknown]";
|
||||
line = 0;
|
||||
baseAddr = addr;
|
||||
#if defined(PLATFORM_64BIT)
|
||||
procName.Format("[%016llX]", addr);
|
||||
#else
|
||||
procName.Format("[%08X]", addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns current filename
|
||||
virtual string GetCurrentFilename() { return "[unknown]"; }
|
||||
|
||||
//! Dumps Current Call Stack to log.
|
||||
virtual void LogCallstack();
|
||||
//triggers a fatal error, so the DebugCallstack can create the error.log and terminate the application
|
||||
void FatalError(const char*);
|
||||
|
||||
//Reports a bug and continues execution
|
||||
virtual void ReportBug(const char*) {}
|
||||
|
||||
virtual void FileCreationCallback(void (* postBackupProcess)());
|
||||
|
||||
static void WriteLineToLog(const char* format, ...);
|
||||
|
||||
virtual void StartMemLog();
|
||||
virtual void StopMemLog();
|
||||
|
||||
protected:
|
||||
IDebugCallStack();
|
||||
virtual ~IDebugCallStack();
|
||||
|
||||
static const char* TranslateExceptionCode(DWORD dwExcept);
|
||||
static void PutVersion(char* str, size_t length);
|
||||
|
||||
bool m_bIsFatalError;
|
||||
static const char* const s_szFatalErrorCode;
|
||||
|
||||
void (* m_postBackupProcess)();
|
||||
|
||||
AZ::IO::HandleType m_memAllocFileHandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_IDEBUGCALLSTACK_H
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
|
||||
struct SThreadConfig
|
||||
{
|
||||
enum eThreadParamFlag
|
||||
{
|
||||
eThreadParamFlag_ThreadName = BIT(0),
|
||||
eThreadParamFlag_StackSize = BIT(1),
|
||||
eThreadParamFlag_Affinity = BIT(2),
|
||||
eThreadParamFlag_Priority = BIT(3),
|
||||
eThreadParamFlag_PriorityBoost = BIT(4),
|
||||
};
|
||||
|
||||
typedef uint32 TThreadParamFlag;
|
||||
|
||||
const char* szThreadName;
|
||||
uint32 stackSizeBytes;
|
||||
uint32 affinityFlag;
|
||||
int32 priority;
|
||||
bool bDisablePriorityBoost;
|
||||
|
||||
TThreadParamFlag paramActivityFlag;
|
||||
};
|
||||
|
||||
class IThreadConfigManager
|
||||
{
|
||||
public:
|
||||
virtual ~IThreadConfigManager()
|
||||
{
|
||||
}
|
||||
|
||||
//! Called once during System startup.
|
||||
//! Loads the thread configuration for the executing platform from file.
|
||||
virtual bool LoadConfig(const char* pcPath) = 0;
|
||||
|
||||
//! Returns true if a config has been loaded.
|
||||
virtual bool ConfigLoaded() const = 0;
|
||||
|
||||
//! Gets the thread configuration for the specified thread on the active platform.
|
||||
//! If no matching config is found a default configuration is returned (which does not have the same name as the search string).
|
||||
virtual const SThreadConfig* GetThreadConfig(const char* sThreadName, ...) = 0;
|
||||
virtual const SThreadConfig* GetDefaultThreadConfig() const = 0;
|
||||
|
||||
//! Dump a detailed description of the thread startup configurations for this platform to the log file.
|
||||
virtual void DumpThreadConfigurationsToLog() = 0;
|
||||
};
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "LevelSystem.h"
|
||||
#include <IAudioSystem.h>
|
||||
#include "IMovieSystem.h"
|
||||
#include "IMaterialEffects.h"
|
||||
#include <IResourceManager.h>
|
||||
#include <ILocalizationManager.h>
|
||||
#include "CryPath.h"
|
||||
@@ -648,20 +647,6 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName)
|
||||
|
||||
AZStd::string levelPath(pLevelInfo->GetPath());
|
||||
|
||||
/*
|
||||
ICVar *pFileCache = gEnv->pConsole->GetCVar("sys_FileCache"); CRY_ASSERT(pFileCache);
|
||||
|
||||
if(pFileCache->GetIVal())
|
||||
{
|
||||
if(pPak->OpenPack("",pLevelInfo->GetPath()+string("/FileCache.dat")))
|
||||
gEnv->pLog->Log("FileCache.dat loaded");
|
||||
else
|
||||
gEnv->pLog->Log("FileCache.dat not loaded");
|
||||
}
|
||||
*/
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
ICVar* pSpamDelay = gEnv->pConsole->GetCVar("log_SpamDelay");
|
||||
float spamDelay = 0.0f;
|
||||
if (pSpamDelay)
|
||||
@@ -768,8 +753,6 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName)
|
||||
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_START, 0, 0);
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, true);
|
||||
|
||||
return m_pCurrentLevel;
|
||||
}
|
||||
|
||||
|
||||
@@ -247,8 +247,6 @@ namespace LegacyLevelSystem
|
||||
|
||||
auto pPak = gEnv->pCryPak;
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, false);
|
||||
|
||||
ICVar* pSpamDelay = gEnv->pConsole->GetCVar("log_SpamDelay");
|
||||
float spamDelay = 0.0f;
|
||||
if (pSpamDelay)
|
||||
@@ -343,8 +341,6 @@ namespace LegacyLevelSystem
|
||||
|
||||
gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_LEVEL_PRECACHE_START, 0, 0);
|
||||
|
||||
m_pSystem->SetThreadState(ESubsys_Physics, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -920,13 +920,7 @@ bool CLog::LogToMainThread(const char* szString, ELogType logType, bool bAdd, SL
|
||||
msg.bAdd = bAdd;
|
||||
msg.destination = destination;
|
||||
msg.logType = logType;
|
||||
// don't try to store the log message for later in case of out of memory, since then its very likely that this allocation
|
||||
// also fails and results in a stack overflow. This way we should at least get a out of memory on-screen message instead of
|
||||
// a not obvious crash
|
||||
if ((gEnv) && (gEnv->bIsOutOfMemory == false))
|
||||
{
|
||||
m_threadSafeMsgQueue.push(msg);
|
||||
}
|
||||
m_threadSafeMsgQueue.push(msg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1448,8 +1442,6 @@ void CLog::UpdateLoadingScreen(const char* szFormat, ...)
|
||||
|
||||
if (CryGetCurrentThreadId() == m_nMainThreadId)
|
||||
{
|
||||
((CSystem*)m_pSystem)->UpdateLoadingScreen();
|
||||
|
||||
#ifndef LINUX
|
||||
// Take this opportunity to update streaming engine.
|
||||
if (IStreamEngine* pStreamEngine = GetISystem()->GetStreamEngine())
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IConsole.h>
|
||||
#include <INotificationNetwork.h>
|
||||
#include <CryThread.h>
|
||||
|
||||
#include <AzCore/Socket/AzSocket_fwd.h>
|
||||
|
||||
class CNotificationNetwork;
|
||||
namespace NotificationNetwork {
|
||||
// Constants
|
||||
|
||||
static const uint32 NN_PACKET_HEADER_LENGTH = 2 * sizeof(uint32) + NN_CHANNEL_NAME_LENGTH_MAX;
|
||||
|
||||
static const uint32 NN_PACKET_HEADER_OFFSET_MESSAGE = 0;
|
||||
static const uint32 NN_PACKET_HEADER_OFFSET_DATA_LENGTH = sizeof(uint32);
|
||||
static const uint32 NN_PACKET_HEADER_OFFSET_CHANNEL = sizeof(uint32) + sizeof(uint32);
|
||||
|
||||
static const char* NN_THREAD_NAME = "NotificationNetwork";
|
||||
|
||||
enum EMessage
|
||||
{
|
||||
eMessage_DataTransfer = 0xbada2217,
|
||||
|
||||
eMessage_ChannelRegister = 0xab4eda30,
|
||||
eMessage_ChannelUnregister = 0xfa4e3423,
|
||||
};
|
||||
|
||||
// Classes
|
||||
|
||||
struct CChannel
|
||||
{
|
||||
public:
|
||||
static bool IsNameValid(const char* name);
|
||||
|
||||
public:
|
||||
CChannel();
|
||||
CChannel(const char* name);
|
||||
~CChannel();
|
||||
|
||||
public:
|
||||
void WriteToPacketHeader(void* pPacket) const;
|
||||
void ReadFromPacketHeader(void* pPacket);
|
||||
|
||||
public:
|
||||
bool operator ==(const CChannel& channel) const;
|
||||
bool operator !=(const CChannel& channel) const;
|
||||
|
||||
private:
|
||||
char m_name[NN_CHANNEL_NAME_LENGTH_MAX];
|
||||
};
|
||||
|
||||
// TEMP
|
||||
struct SBuffer
|
||||
{
|
||||
uint8* pData;
|
||||
uint32 length;
|
||||
CChannel channel;
|
||||
};
|
||||
|
||||
class CListeners
|
||||
{
|
||||
public:
|
||||
CListeners();
|
||||
~CListeners();
|
||||
|
||||
public:
|
||||
size_t Count() { return m_listeners.size(); }
|
||||
size_t Count(const CChannel& channel);
|
||||
|
||||
CChannel& Channel(size_t index) { return m_listeners[index].second; }
|
||||
CChannel* Channel(INotificationNetworkListener* pListener);
|
||||
|
||||
bool Bind(const CChannel& channel, INotificationNetworkListener* pListener);
|
||||
bool Remove(INotificationNetworkListener* pListener);
|
||||
|
||||
void NotificationPush(const SBuffer& buffer);
|
||||
void NotificationsProcess();
|
||||
|
||||
private:
|
||||
std::vector< std::pair<INotificationNetworkListener*, CChannel> > m_listeners;
|
||||
|
||||
std::queue<SBuffer> m_notifications[2];
|
||||
std::queue<SBuffer>* m_pNotificationWrite;
|
||||
std::queue<SBuffer>* m_pNotificationRead;
|
||||
CryCriticalSection m_notificationCriticalSection;
|
||||
};
|
||||
|
||||
class CConnectionBase
|
||||
{
|
||||
public:
|
||||
CConnectionBase(CNotificationNetwork* pNotificationNetwork);
|
||||
virtual ~CConnectionBase();
|
||||
|
||||
public:
|
||||
AZSOCKET CreateSocket();
|
||||
|
||||
bool Connect(const char* address, uint16 port);
|
||||
|
||||
AZSOCKET GetSocket() { return m_socket; }
|
||||
|
||||
bool Validate();
|
||||
|
||||
bool SendNotification(const CChannel& channel, const void* pBuffer, size_t length);
|
||||
|
||||
bool Receive(CListeners& listeners);
|
||||
|
||||
bool GetIsConnectedFlag();
|
||||
bool GetIsFailedToConnectFlag() const;
|
||||
|
||||
protected:
|
||||
CNotificationNetwork* GetNotificationNetwork() { return m_pNotificationNetwork; }
|
||||
|
||||
void SetAddress(const char* address, uint16 port);
|
||||
void SetSocket(AZSOCKET sock) { m_socket = sock; }
|
||||
|
||||
bool Send(const void* pBuffer, size_t length);
|
||||
bool SendMessage(EMessage eMessage, const CChannel& channel, uint32 data);
|
||||
|
||||
bool Select_Internal();
|
||||
void CloseSocket_Internal();
|
||||
|
||||
virtual bool OnConnect([[maybe_unused]] bool bConnectionResult) { return true; }
|
||||
virtual bool OnDisconnect() {return true; }
|
||||
virtual bool OnMessage([[maybe_unused]] EMessage eMessage, [[maybe_unused]] const CChannel& channel) { return false; }
|
||||
|
||||
private:
|
||||
bool ReceiveMessage(CListeners& listeners);
|
||||
bool ReceiveNotification(CListeners& listeners);
|
||||
|
||||
protected:
|
||||
CNotificationNetwork* m_pNotificationNetwork;
|
||||
|
||||
char m_address[16];
|
||||
uint16 m_port;
|
||||
|
||||
AZSOCKET m_socket;
|
||||
|
||||
uint8 m_bufferHeader[NN_PACKET_HEADER_LENGTH];
|
||||
SBuffer m_buffer;
|
||||
uint32 m_dataLeft;
|
||||
|
||||
volatile bool m_boIsConnected;
|
||||
volatile bool m_boIsFailedToConnect;
|
||||
};
|
||||
|
||||
class CClient
|
||||
: public CConnectionBase
|
||||
, public INotificationNetworkClient
|
||||
{
|
||||
public:
|
||||
typedef std::vector<INotificationNetworkConnectionCallback*> TDNotificationNetworkConnectionCallbacks;
|
||||
|
||||
static CClient* Create(CNotificationNetwork* pNotificationNetwork, const char* address, uint16 port);
|
||||
static CClient* Create(CNotificationNetwork* pNotificationNetwork);
|
||||
|
||||
private:
|
||||
CClient(CNotificationNetwork* pNotificationNetwork);
|
||||
~CClient();
|
||||
|
||||
public:
|
||||
bool Receive() { return CConnectionBase::Receive(m_listeners); }
|
||||
|
||||
void Update();
|
||||
|
||||
// CConnectionBase
|
||||
public:
|
||||
virtual bool OnConnect(bool bConnectionResult);
|
||||
virtual bool OnDisconnect();
|
||||
virtual bool OnMessage(EMessage eMessage, const CChannel& channel);
|
||||
|
||||
// INotificationNetworkClient
|
||||
public:
|
||||
bool Connect(const char* address, uint16 port);
|
||||
|
||||
void Release() { delete this; }
|
||||
|
||||
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener);
|
||||
virtual bool ListenerRemove(INotificationNetworkListener* pListener);
|
||||
|
||||
virtual bool Send(const char* channelName, const void* pBuffer, size_t length);
|
||||
|
||||
virtual bool IsConnected() {return CConnectionBase::GetIsConnectedFlag(); }
|
||||
virtual bool IsFailedToConnect() const{return CConnectionBase::GetIsFailedToConnectFlag(); }
|
||||
|
||||
virtual bool RegisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback);
|
||||
virtual bool UnregisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback);
|
||||
private:
|
||||
CListeners m_listeners;
|
||||
|
||||
TDNotificationNetworkConnectionCallbacks m_cNotificationNetworkConnectionCallbacks;
|
||||
CryCriticalSection m_stConnectionCallbacksLock;
|
||||
};
|
||||
} // namespace NotificationNetwork
|
||||
class CNotificationNetwork
|
||||
: public INotificationNetwork
|
||||
{
|
||||
private:
|
||||
class CConnection
|
||||
: public NotificationNetwork::CConnectionBase
|
||||
{
|
||||
public:
|
||||
CConnection(CNotificationNetwork* pNotificationNetwork, AZSOCKET sock);
|
||||
virtual ~CConnection();
|
||||
|
||||
public:
|
||||
bool IsListening(const NotificationNetwork::CChannel& channel);
|
||||
|
||||
// CConnectionBase
|
||||
protected:
|
||||
virtual bool OnMessage(NotificationNetwork::EMessage eMessage, const NotificationNetwork::CChannel& channel);
|
||||
|
||||
private:
|
||||
std::vector<NotificationNetwork::CChannel> m_listeningChannels;
|
||||
};
|
||||
|
||||
class CThread
|
||||
: public CryThread<CThread>
|
||||
{
|
||||
public:
|
||||
CThread();
|
||||
~CThread();
|
||||
|
||||
public:
|
||||
bool Begin(CNotificationNetwork* pNotificationNetwork);
|
||||
void End();
|
||||
|
||||
// CryRunnable
|
||||
public:
|
||||
virtual void Run();
|
||||
|
||||
private:
|
||||
CNotificationNetwork* m_pNotificationNetwork;
|
||||
bool m_bRun;
|
||||
} m_thread;
|
||||
|
||||
public:
|
||||
static CNotificationNetwork* Create();
|
||||
|
||||
public:
|
||||
CNotificationNetwork();
|
||||
~CNotificationNetwork();
|
||||
|
||||
public:
|
||||
void ReleaseClients(NotificationNetwork::CClient* pClient);
|
||||
|
||||
private:
|
||||
void ProcessSockets();
|
||||
|
||||
// INotificationNetwork
|
||||
public:
|
||||
virtual void Release() { delete this; }
|
||||
|
||||
virtual INotificationNetworkClient* CreateClient();
|
||||
|
||||
virtual INotificationNetworkClient* Connect(const char* address, uint16 port);
|
||||
|
||||
virtual size_t GetConnectionCount(const char* channelName);
|
||||
|
||||
virtual void Update();
|
||||
|
||||
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener);
|
||||
virtual bool ListenerRemove(INotificationNetworkListener* pListener);
|
||||
|
||||
virtual uint32 Send(const char* channelName, const void* pBuffer, size_t length);
|
||||
|
||||
private:
|
||||
AZSOCKET m_socket;
|
||||
|
||||
std::vector<CConnection*> m_connections;
|
||||
std::vector<NotificationNetwork::CClient*> m_clients;
|
||||
NotificationNetwork::CListeners m_listeners;
|
||||
|
||||
CryCriticalSection m_clientsCriticalSection;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "ProfileLogSystem.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class CLogElement
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CLogElement::CLogElement()
|
||||
: m_pParent (NULL)
|
||||
, m_time (0)
|
||||
{
|
||||
}
|
||||
|
||||
CLogElement::CLogElement(CLogElement* pParent)
|
||||
: m_pParent (pParent)
|
||||
, m_time (0)
|
||||
{
|
||||
}
|
||||
|
||||
CLogElement::CLogElement(CLogElement* pParent, const char* name, const char* message)
|
||||
: m_pParent (pParent)
|
||||
, m_strName (name)
|
||||
, m_strMessage(message)
|
||||
, m_time (0)
|
||||
{
|
||||
}
|
||||
|
||||
void CLogElement::Flush(stack_string& indent)
|
||||
{
|
||||
if (m_logElements.empty())
|
||||
{
|
||||
CryLog("%s%s [%.3f ms] %s", indent.c_str(), m_strName.c_str(), m_time, m_strMessage.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
CryLog("%s+%s [%.3f ms] %s", indent.c_str(), m_strName.c_str(), m_time, m_strMessage.c_str());
|
||||
|
||||
indent += " ";
|
||||
for (std::list<CLogElement>::iterator it = m_logElements.begin(); it != m_logElements.end(); ++it)
|
||||
{
|
||||
(*it).Flush(indent);
|
||||
}
|
||||
indent.erase(0, 2);
|
||||
|
||||
CryLog("%s-%s", indent.c_str(), m_strName.c_str());
|
||||
}
|
||||
|
||||
ILogElement* CLogElement::Log(const char* name, const char* message)
|
||||
{
|
||||
m_logElements.push_back(CLogElement(this));
|
||||
m_logElements.back().m_strName = name;
|
||||
m_logElements.back().m_strMessage = message;
|
||||
|
||||
return &m_logElements.back();
|
||||
}
|
||||
|
||||
ILogElement* CLogElement::SetTime(float time)
|
||||
{
|
||||
m_time = time;
|
||||
|
||||
return m_pParent;
|
||||
}
|
||||
|
||||
void CLogElement::Clear()
|
||||
{
|
||||
m_logElements.resize(0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// class CProfileLogSystem
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CProfileLogSystem::CProfileLogSystem()
|
||||
: m_rootElelent(NULL)
|
||||
, m_pLastElelent(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CProfileLogSystem::~CProfileLogSystem()
|
||||
{
|
||||
}
|
||||
|
||||
ILogElement* CProfileLogSystem::Log(const char* name, const char* message)
|
||||
{
|
||||
if (m_pLastElelent)
|
||||
{
|
||||
m_pLastElelent = m_pLastElelent->Log(name, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rootElelent.Clear();
|
||||
m_rootElelent.SetName(name);
|
||||
m_rootElelent.SetMessage(message);
|
||||
m_pLastElelent = &m_rootElelent;
|
||||
}
|
||||
|
||||
return m_pLastElelent;
|
||||
}
|
||||
|
||||
void CProfileLogSystem::SetTime(ILogElement* pElement, float time)
|
||||
{
|
||||
if (pElement == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_pLastElelent = pElement->SetTime(time);
|
||||
if (m_pLastElelent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stack_string indent;
|
||||
m_rootElelent.Flush(indent);
|
||||
m_rootElelent.Clear();
|
||||
}
|
||||
|
||||
void CProfileLogSystem::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Implementation of the IProfileLogSystem interface, which is used to
|
||||
// save hierarchical log with SHierProfileLogItem
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_PROFILELOGSYSTEM_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_PROFILELOGSYSTEM_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ProfileLog.h"
|
||||
|
||||
class CLogElement
|
||||
: public ILogElement
|
||||
{
|
||||
public:
|
||||
CLogElement();
|
||||
CLogElement(CLogElement* pParent);
|
||||
CLogElement(CLogElement* pParent, const char* name, const char* message);
|
||||
|
||||
virtual ILogElement* Log (const char* name, const char* message);
|
||||
virtual ILogElement* SetTime (float time);
|
||||
virtual void Flush (stack_string& indent);
|
||||
|
||||
void Clear ();
|
||||
|
||||
inline void SetName(const char* name)
|
||||
{
|
||||
m_strName = name;
|
||||
}
|
||||
|
||||
inline void SetMessage(const char* message)
|
||||
{
|
||||
m_strMessage = message;
|
||||
}
|
||||
|
||||
private:
|
||||
string m_strName;
|
||||
string m_strMessage;
|
||||
float m_time; // milliSeconds
|
||||
|
||||
CLogElement* m_pParent;
|
||||
std::list<CLogElement> m_logElements;
|
||||
};
|
||||
|
||||
class CProfileLogSystem
|
||||
: public IProfileLogSystem
|
||||
{
|
||||
public:
|
||||
CProfileLogSystem();
|
||||
~CProfileLogSystem();
|
||||
|
||||
virtual ILogElement* Log (const char* name, const char* message);
|
||||
virtual void SetTime (ILogElement* pElement, float time);
|
||||
virtual void Release ();
|
||||
|
||||
private:
|
||||
CLogElement m_rootElelent;
|
||||
ILogElement* m_pLastElelent;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_PROFILELOGSYSTEM_H
|
||||
@@ -699,7 +699,7 @@ void CResourceManager::OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_P
|
||||
if (g_cvars.archiveVars.nLoadCache)
|
||||
{
|
||||
//Load the frontend common mode switch pak, this can considerably reduce the time spent switching especially from disc
|
||||
if (!gEnv->bMultiplayer && LoadMenuCommonPak(FRONTEND_COMMON_PAK_FILENAME_SP) == false)
|
||||
if (LoadMenuCommonPak(FRONTEND_COMMON_PAK_FILENAME_SP) == false)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "Could not load %s during init. This file can significantly reduce frontend loading times.\n", FRONTEND_COMMON_PAK_FILENAME_SP);
|
||||
}
|
||||
@@ -710,14 +710,7 @@ void CResourceManager::OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_P
|
||||
|
||||
case ESYSTEM_EVENT_LEVEL_LOAD_PREPARE:
|
||||
{
|
||||
if (!gEnv->bMultiplayer)
|
||||
{
|
||||
UnloadMenuCommonPak(FRONTEND_COMMON_PAK_FILENAME_SP, FRONTEND_COMMON_LIST_FILENAME "_sp");
|
||||
}
|
||||
else
|
||||
{
|
||||
UnloadMenuCommonPak(FRONTEND_COMMON_PAK_FILENAME_MP, FRONTEND_COMMON_LIST_FILENAME "_mp");
|
||||
}
|
||||
UnloadMenuCommonPak(FRONTEND_COMMON_PAK_FILENAME_SP, FRONTEND_COMMON_LIST_FILENAME "_sp");
|
||||
|
||||
m_bLevelTransitioning = !m_sLevelName.empty();
|
||||
|
||||
|
||||
@@ -1,787 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
|
||||
#ifdef SOFTCODE_SYSTEM_ENABLED
|
||||
|
||||
#ifndef SOFTCODE_ENABLED
|
||||
// Even if this module isn't built with SC enabled, if the SC system is enabled we define
|
||||
// it for this compilation unit to ensure we use the correct versions of the IType* interfaces.
|
||||
#define SOFTCODE_ENABLED
|
||||
#endif
|
||||
|
||||
#include "SoftCodeMgr.h"
|
||||
#include <IConsole.h>
|
||||
#include <CryLibrary.h>
|
||||
#include <CryPath.h>
|
||||
#include <AzCore/std/functional.h> // for function<> in find files
|
||||
|
||||
// This should resolve to "GetTypeLibrary" but we export by ordinal to avoid overheads on 360
|
||||
// and keep everything consistent.
|
||||
static const char* DLL_GETTYPELIBRARY = (LPCSTR)1;
|
||||
|
||||
struct CInstanceData
|
||||
{
|
||||
CInstanceData(void* pInstance, size_t memberCount)
|
||||
: m_pOldInstance(pInstance)
|
||||
, m_pNewInstance()
|
||||
{
|
||||
m_members.resize(memberCount);
|
||||
}
|
||||
|
||||
~CInstanceData()
|
||||
{
|
||||
// Delete all members
|
||||
for (TMemberVec::iterator iter(m_members.begin());
|
||||
iter != m_members.end();
|
||||
++iter)
|
||||
{
|
||||
// TODO: Safe cross module? Same allocator? Use a Destroy() method?
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
void* Instance() { return m_pOldInstance; }
|
||||
|
||||
void AddMember(size_t index, IExchangeValue& value)
|
||||
{
|
||||
// TODO: Add support for members with same name at different hierarchy levels
|
||||
assert(m_members[index] == NULL);
|
||||
assert(index != ~0);
|
||||
|
||||
// Support expansion of m_members during while resolving members
|
||||
if (index >= m_members.size())
|
||||
{
|
||||
m_members.resize(index + 1);
|
||||
}
|
||||
|
||||
m_members[index] = value.Clone();
|
||||
}
|
||||
|
||||
IExchangeValue* GetMember(size_t index) const
|
||||
{
|
||||
assert(index < m_members.size());
|
||||
return m_members[index];
|
||||
}
|
||||
|
||||
void SetNewInstance(void* pNewInstance) { m_pNewInstance = pNewInstance; }
|
||||
|
||||
void* m_pOldInstance;
|
||||
void* m_pNewInstance;
|
||||
|
||||
typedef std::vector<IExchangeValue*> TMemberVec;
|
||||
TMemberVec m_members;
|
||||
};
|
||||
|
||||
|
||||
class CExchanger
|
||||
: public IExchanger
|
||||
{
|
||||
public:
|
||||
CExchanger()
|
||||
: m_pInstanceData()
|
||||
, m_instanceIndex(~0)
|
||||
, m_state(eState_ResolvingMembers)
|
||||
{}
|
||||
|
||||
virtual ~CExchanger()
|
||||
{
|
||||
DestroyInstanceData();
|
||||
}
|
||||
|
||||
virtual bool IsLoading() const { return m_state >= eState_WritingNewMembers; }
|
||||
virtual size_t InstanceCount() const { return m_instances.size(); }
|
||||
|
||||
virtual bool BeginInstance(void* pInstance)
|
||||
{
|
||||
if (IsLoading())
|
||||
{
|
||||
if (++m_instanceIndex < m_instances.size())
|
||||
{
|
||||
m_pInstanceData = m_instances[m_instanceIndex];
|
||||
m_pInstanceData->SetNewInstance(pInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pInstanceData = NULL;
|
||||
}
|
||||
}
|
||||
else // Reading/resolving members
|
||||
{
|
||||
m_instanceIndex = m_instances.size();
|
||||
m_pInstanceData = new CInstanceData(pInstance, m_memberMap.size());
|
||||
m_instances.push_back(m_pInstanceData);
|
||||
}
|
||||
|
||||
return m_pInstanceData != NULL;
|
||||
}
|
||||
|
||||
virtual bool SetValue(const char* name, IExchangeValue& value)
|
||||
{
|
||||
assert(!IsLoading());
|
||||
|
||||
const size_t index = FindMemberIndex(name);
|
||||
const bool consumingValue = index != ~0;
|
||||
|
||||
if (consumingValue)
|
||||
{
|
||||
m_pInstanceData->AddMember(index, value);
|
||||
}
|
||||
|
||||
return consumingValue;
|
||||
}
|
||||
|
||||
virtual IExchangeValue* GetValue(const char* name, void* pTarget, size_t targetSize)
|
||||
{
|
||||
assert(IsLoading());
|
||||
|
||||
const size_t index = FindMemberIndex(name);
|
||||
|
||||
// If member resolved (may not be if restoring to old instances)
|
||||
if (index != ~0)
|
||||
{
|
||||
// If member data available (may not be if member is new)
|
||||
if (IExchangeValue* pValue = m_pInstanceData->GetMember(index))
|
||||
{
|
||||
if (pValue->GetSizeOf() == targetSize)
|
||||
{
|
||||
return pValue;
|
||||
}
|
||||
else // Member size mismatch
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING,
|
||||
"SoftCode: Member %s of instance %p has changed size (old: %d new: %d), setting to default value.",
|
||||
name, m_pInstanceData->Instance(), (int)pValue->GetSizeOf(), (int)targetSize);
|
||||
}
|
||||
}
|
||||
else // Member unknown
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING,
|
||||
"SoftCode: Member %s (of instance %p) appears to be new.",
|
||||
name, m_pInstanceData->Instance());
|
||||
|
||||
// TODO: Could attempt to validate against a known wipe pattern ie. 0xfefefefe
|
||||
// This could catch most uninitialized variables...
|
||||
|
||||
if (targetSize <= sizeof(void*))
|
||||
{
|
||||
switch (targetSize)
|
||||
{
|
||||
case 1:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "\tLeaving as: %d", *reinterpret_cast<char*>(pTarget));
|
||||
break;
|
||||
case 2:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "\tLeaving as: %04x", *reinterpret_cast<short*>(pTarget));
|
||||
break;
|
||||
case 4:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "\tLeaving as: %08x", *reinterpret_cast<int*>(pTarget));
|
||||
break;
|
||||
case 8:
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "\tLeaving as: %llx", *reinterpret_cast<long long*>(pTarget));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate value should be default constructed
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Used once required members have been established, members not already
|
||||
// encountered will be ignored.
|
||||
void LockMemberSet()
|
||||
{
|
||||
assert(m_state == eState_ResolvingMembers);
|
||||
|
||||
DestroyInstanceData();
|
||||
m_state = eState_ReadingOldMembers;
|
||||
}
|
||||
|
||||
// Rewinds instance data and prepare for loading
|
||||
void RewindForLoading()
|
||||
{
|
||||
assert(m_state == eState_ReadingOldMembers);
|
||||
|
||||
m_pInstanceData = NULL;
|
||||
m_instanceIndex = ~0;
|
||||
m_state = eState_WritingNewMembers;
|
||||
}
|
||||
|
||||
// Rewinds instance data to prepare to restore old members (UNDO)
|
||||
void RewindForRestore()
|
||||
{
|
||||
assert(m_state == eState_WritingNewMembers);
|
||||
|
||||
m_pInstanceData = NULL;
|
||||
m_instanceIndex = ~0;
|
||||
m_state = eState_RestoringOldMembers;
|
||||
}
|
||||
|
||||
void NotifyListenerOfReplacements(ISoftCodeListener* pListener)
|
||||
{
|
||||
for (TInstanceVec::const_iterator iter(m_instances.begin()); iter != m_instances.end(); ++iter)
|
||||
{
|
||||
CInstanceData* pInstanceData = *iter;
|
||||
pListener->InstanceReplaced(pInstanceData->m_pOldInstance, pInstanceData->m_pNewInstance);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void DestroyInstanceData()
|
||||
{
|
||||
m_pInstanceData = NULL;
|
||||
m_instanceIndex = ~0;
|
||||
|
||||
for (TInstanceVec::iterator iter(m_instances.begin()); iter != m_instances.end(); ++iter)
|
||||
{
|
||||
delete *iter;
|
||||
}
|
||||
|
||||
m_instances.resize(0);
|
||||
}
|
||||
|
||||
inline size_t FindMemberIndex(const string& memberName)
|
||||
{
|
||||
size_t index = ~0;
|
||||
|
||||
// If needed members have been resolved
|
||||
if (m_state != eState_ResolvingMembers)
|
||||
{
|
||||
TMemberMap::const_iterator iter(m_memberMap.find(memberName));
|
||||
if (iter != m_memberMap.end())
|
||||
{
|
||||
index = iter->second;
|
||||
}
|
||||
}
|
||||
else // Add this member to the map with a new index
|
||||
{
|
||||
// Ensure there's no member name duplicates
|
||||
assert(m_memberMap.find(memberName) == m_memberMap.end());
|
||||
|
||||
// A new entry
|
||||
index = m_memberMap.size();
|
||||
size_t& newIndex = m_memberMap[memberName];
|
||||
newIndex = index;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private:
|
||||
CInstanceData* m_pInstanceData;
|
||||
size_t m_instanceIndex;
|
||||
|
||||
typedef std::vector<CInstanceData*> TInstanceVec;
|
||||
TInstanceVec m_instances;
|
||||
|
||||
// Maps instance members to offsets in instance member vectors
|
||||
typedef std::map<string, size_t> TMemberMap;
|
||||
TMemberMap m_memberMap;
|
||||
|
||||
enum EState
|
||||
{
|
||||
eState_ResolvingMembers = 0, // Record new member names as found
|
||||
eState_ReadingOldMembers, // Scrape requested member data from old instances
|
||||
eState_WritingNewMembers, // Write old member data to new instances
|
||||
eState_RestoringOldMembers, // Restore scraped values to old instances (UNDO)
|
||||
};
|
||||
|
||||
EState m_state;
|
||||
};
|
||||
|
||||
|
||||
// ----
|
||||
|
||||
DynamicTypeLibrary::DynamicTypeLibrary(const char* name)
|
||||
: m_name(name)
|
||||
, m_listeners(1)
|
||||
{}
|
||||
|
||||
const char* DynamicTypeLibrary::GetName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void* DynamicTypeLibrary::CreateInstanceVoid(const char* typeName)
|
||||
{
|
||||
TTypeMap::const_iterator typeIter(m_types.find(typeName));
|
||||
if (typeIter != m_types.end())
|
||||
{
|
||||
ITypeRegistrar* pRegistrar = typeIter->second;
|
||||
return pRegistrar->CreateInstance();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DynamicTypeLibrary::SetOverride(ITypeLibrary* /*pOverrideLib*/)
|
||||
{
|
||||
CryFatalError("Unsupported: Attempting to SetOverride on a DynamicTypeLibrary!");
|
||||
}
|
||||
|
||||
size_t DynamicTypeLibrary::GetTypes([[maybe_unused]] ITypeRegistrar** ppRegistrar, [[maybe_unused]] size_t& count) const
|
||||
{
|
||||
CryFatalError("Unsupported: Attempting to GetTypes on a DynamicTypeLibrary!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DynamicTypeLibrary::AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName)
|
||||
{
|
||||
// This DynamicTypeLibrary could have been created by this listener request
|
||||
// So ensure we have a name...!
|
||||
if (!m_name)
|
||||
{
|
||||
m_name = libraryName;
|
||||
}
|
||||
|
||||
m_listeners.Add(pListener, listenerName);
|
||||
}
|
||||
|
||||
void DynamicTypeLibrary::RemoveListener(ISoftCodeListener* pListener)
|
||||
{
|
||||
m_listeners.Remove(pListener);
|
||||
}
|
||||
|
||||
void DynamicTypeLibrary::IntegrateLibrary(ITypeLibrary* pLib, bool isDefault)
|
||||
{
|
||||
typedef std::vector<ITypeRegistrar*> TTypeVec;
|
||||
|
||||
// Resolve our name if we haven't already
|
||||
if (!m_name)
|
||||
{
|
||||
m_name = pLib->GetName();
|
||||
}
|
||||
|
||||
// Override the new lib immediately
|
||||
pLib->SetOverride(this);
|
||||
|
||||
// Query the new library for its types
|
||||
size_t typeCount = 0;
|
||||
pLib->GetTypes(NULL, typeCount);
|
||||
if (typeCount > 0)
|
||||
{
|
||||
TTypeVec typeVec;
|
||||
typeVec.resize(typeCount);
|
||||
pLib->GetTypes(&(typeVec.front()), typeCount);
|
||||
|
||||
if (!isDefault)
|
||||
{
|
||||
CryLogAlways("SoftCode: Integrating %d new types defined in %s...", (int)typeCount, m_name);
|
||||
}
|
||||
|
||||
// Attempt to integrate each type found
|
||||
for (TTypeVec::iterator typeIter(typeVec.begin()); typeIter != typeVec.end(); ++typeIter)
|
||||
{
|
||||
IntegrateType(*typeIter, isDefault);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "SoftCode: New %s library has no registered types. Nothing to integrate.", pLib->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
ITypeRegistrar* DynamicTypeLibrary::FindTypeForInstance(void* pInstance) const
|
||||
{
|
||||
for (TTypeMap::const_iterator iter(m_types.begin()); iter != m_types.end(); ++iter)
|
||||
{
|
||||
ITypeRegistrar* pType = iter->second;
|
||||
if (pType->HasInstance(pInstance))
|
||||
{
|
||||
return pType;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DynamicTypeLibrary::IntegrateType(ITypeRegistrar* pType, bool isDefault)
|
||||
{
|
||||
const char* typeName = pType->GetName();
|
||||
|
||||
// If there's an existing registrar
|
||||
ITypeRegistrar* pExistingType = m_types[typeName];
|
||||
assert(pExistingType != pType); // Sanity check
|
||||
|
||||
// If the new type is the default (built-in) type but it's already been overridden
|
||||
if (isDefault && pExistingType)
|
||||
{
|
||||
return; // Nothing to do
|
||||
}
|
||||
// TODO: Inform listeners that there's a new library available
|
||||
// and ask if we should use it immediately or defer
|
||||
|
||||
CExchanger exchanger;
|
||||
|
||||
// If the type can be safely created, visited and destroyed
|
||||
if (EvaluateType(pType, exchanger))
|
||||
{
|
||||
// Override the type
|
||||
m_types[typeName] = pType;
|
||||
|
||||
if (!isDefault)
|
||||
{
|
||||
CryLogAlways("SoftCode: Overridden %s in library %s", typeName, m_name);
|
||||
}
|
||||
|
||||
const size_t instanceCount = (pExistingType) ? pExistingType->InstanceCount() : 0;
|
||||
|
||||
// If there are any existing instances
|
||||
if (instanceCount > 0)
|
||||
{
|
||||
CryLogAlways("SoftCode: Attempting to exchange %d %s instances to the new version...", (int)instanceCount, typeName);
|
||||
|
||||
// Read instance members for type (removes data for resolved members)
|
||||
if (pExistingType->ExchangeInstances(exchanger))
|
||||
{
|
||||
exchanger.RewindForLoading();
|
||||
|
||||
// Write instance members for type
|
||||
if (pType->ExchangeInstances(exchanger))
|
||||
{
|
||||
// Success! Tell the listeners to fix up their pointers
|
||||
for (TListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
|
||||
{
|
||||
exchanger.NotifyListenerOfReplacements(*notifier);
|
||||
}
|
||||
|
||||
CryLogAlways("SoftCode: %d %s instances successfully overridden to latest!", (int)instanceCount, typeName);
|
||||
|
||||
// Clean up old instances
|
||||
if (!pExistingType->DestroyInstances())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "SoftCode: Failed to destroy old instances of type %s - leak probable.", typeName);
|
||||
}
|
||||
}
|
||||
else // Failed to create & write into new instances
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to create and write into new instances of %s. Attempting restore of old instances...", typeName);
|
||||
if (!pType->DestroyInstances())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "SoftCode: Failed to destroy new instances of type %s - leak probable.", typeName);
|
||||
}
|
||||
|
||||
// Restore the original type library as the active one
|
||||
m_types[typeName] = pExistingType;
|
||||
|
||||
// Attempt to restore the old instances with their original data
|
||||
exchanger.RewindForRestore();
|
||||
if (pExistingType->ExchangeInstances(exchanger))
|
||||
{
|
||||
CryLogAlways("SoftCode: Type %s in library %s successfully restored to previous revision!", typeName, m_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Restore of old %s instances failed. State now undefined!", typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to read members on %s", typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DynamicTypeLibrary::EvaluateType(ITypeRegistrar* pType, CExchanger& exchanger)
|
||||
{
|
||||
// Try a full object life-time with a single instance of the
|
||||
// new type before attempting a member exchange. This also allow the
|
||||
// exchanger to determine the required members to be removed from the
|
||||
// old instances.
|
||||
bool testPassed = false;
|
||||
|
||||
// Create a single test instance of the type
|
||||
if (pType->CreateInstance())
|
||||
{
|
||||
// Read the instance members (also prepares the exchanger member set)
|
||||
if (pType->ExchangeInstances(exchanger))
|
||||
{
|
||||
// Destroy the old instance
|
||||
if (pType->DestroyInstances())
|
||||
{
|
||||
// Indicate required members are now resolved
|
||||
exchanger.LockMemberSet();
|
||||
testPassed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to destroy test instance of type: %s. New type will be skipped.", pType->GetName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to read members in test instance of type: %s. New type will be skipped.", pType->GetName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to create test instance of type: %s. New type will be skipped.", pType->GetName());
|
||||
}
|
||||
|
||||
return testPassed;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
// The export we expect to find in the SoftCode modules
|
||||
typedef ITypeLibrary* (__stdcall * TGetTypeLibraryFcn)();
|
||||
|
||||
static void SoftCode_UpdateCmd([[maybe_unused]] IConsoleCmdArgs* pArgs)
|
||||
{
|
||||
gEnv->pSoftCodeMgr->LoadNewModules();
|
||||
}
|
||||
|
||||
static int g_autoUpdatePeriod = 0;
|
||||
|
||||
SoftCodeMgr::SoftCodeMgr()
|
||||
{
|
||||
REGISTER_CVAR2("sc_autoupdate", &g_autoUpdatePeriod, 5, VF_CHEAT, "Set the auto-update poll period for new SoftCode modules. Set to zero to disable");
|
||||
REGISTER_COMMAND("sc_update", reinterpret_cast<ConsoleCommandFunc>(&SoftCode_UpdateCmd), VF_CHEAT, "Loads any new SoftCode modules");
|
||||
|
||||
// Clear out any old modules
|
||||
{
|
||||
typedef std::vector<string> TStringVec;
|
||||
TStringVec filePaths;
|
||||
|
||||
if (FindSoftCodeFiles("*", filePaths) > 0)
|
||||
{
|
||||
for (TStringVec::const_iterator iter(filePaths.begin()); iter != filePaths.end(); ++iter)
|
||||
{
|
||||
if (!DeleteFile(iter->c_str()))
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "SoftCode: Failed to clean %s", iter->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoftCodeMgr::~SoftCodeMgr()
|
||||
{
|
||||
if (gEnv->pConsole)
|
||||
{
|
||||
gEnv->pConsole->RemoveCommand("sc_update");
|
||||
gEnv->pConsole->UnregisterVariable("sc_autoupdate");
|
||||
}
|
||||
}
|
||||
|
||||
// Used to register built-in libraries on first use
|
||||
void SoftCodeMgr::RegisterLibrary(ITypeLibrary* pDefaultLib)
|
||||
{
|
||||
DynamicTypeLibrary& typeLib = m_libraryMap[pDefaultLib->GetName()];
|
||||
typeLib.IntegrateLibrary(pDefaultLib, true);
|
||||
}
|
||||
|
||||
// Look for new SoftCode modules and load them, adding their types to the registry
|
||||
void SoftCodeMgr::LoadNewModules()
|
||||
{
|
||||
typedef std::vector<string> TStringVec;
|
||||
typedef TStringVec::const_iterator TModuleIter;
|
||||
TStringVec modulePaths;
|
||||
|
||||
// Find modules
|
||||
FindSoftCodeFiles("*.dll", modulePaths);
|
||||
|
||||
for (TModuleIter libIter(modulePaths.begin()); libIter != modulePaths.end(); ++libIter)
|
||||
{
|
||||
const char* moduleName = libIter->c_str();
|
||||
LoadModule(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftCodeMgr::AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName)
|
||||
{
|
||||
// Find an existing lib or create a new one to add the listener to
|
||||
DynamicTypeLibrary& lib = m_libraryMap[libraryName];
|
||||
lib.AddListener(libraryName, pListener, listenerName);
|
||||
}
|
||||
|
||||
void SoftCodeMgr::RemoveListener(const char* libraryName, ISoftCodeListener* pListener)
|
||||
{
|
||||
TLibMap::iterator iter(m_libraryMap.find(libraryName));
|
||||
|
||||
if (iter != m_libraryMap.end())
|
||||
{
|
||||
iter->second.RemoveListener(pListener);
|
||||
}
|
||||
}
|
||||
|
||||
// To be called regularly to poll for library updates
|
||||
void SoftCodeMgr::PollForNewModules()
|
||||
{
|
||||
if (g_autoUpdatePeriod > 0)
|
||||
{
|
||||
const CTimeValue frameStartTime(gEnv->pTimer->GetFrameStartTime(ITimer::ETIMER_UI));
|
||||
if (m_nextAutoCheckTime <= frameStartTime)
|
||||
{
|
||||
m_nextAutoCheckTime.SetSeconds((int64)g_autoUpdatePeriod);
|
||||
m_nextAutoCheckTime += frameStartTime;
|
||||
|
||||
// Attempt to find and load any new modules
|
||||
LoadNewModules();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Util
|
||||
class InstanceFixup
|
||||
: public ISoftCodeListener
|
||||
{
|
||||
public:
|
||||
InstanceFixup(void* pOldInstance)
|
||||
: m_pOldInstance(pOldInstance)
|
||||
, m_pNewInstance() {}
|
||||
|
||||
virtual void InstanceReplaced(void* pOldInstance, void* pNewInstance)
|
||||
{
|
||||
if (m_pOldInstance == pOldInstance)
|
||||
{
|
||||
m_pNewInstance = pNewInstance;
|
||||
}
|
||||
}
|
||||
|
||||
void* NewInstance() const { return m_pNewInstance; }
|
||||
|
||||
private:
|
||||
void* m_pOldInstance;
|
||||
void* m_pNewInstance;
|
||||
};
|
||||
}
|
||||
|
||||
// Stops thread execution until a new SoftCode module is available
|
||||
void* SoftCodeMgr::WaitForUpdate(void* pInstance)
|
||||
{
|
||||
DynamicTypeLibrary* pOwningLib = NULL;
|
||||
ITypeRegistrar* pOldType = NULL;
|
||||
|
||||
// Find existing instance
|
||||
for (TLibMap::iterator libIter(m_libraryMap.begin()); libIter != m_libraryMap.end(); ++libIter)
|
||||
{
|
||||
DynamicTypeLibrary& lib = libIter->second;
|
||||
if (ITypeRegistrar* pType = lib.FindTypeForInstance(pInstance))
|
||||
{
|
||||
pOwningLib = &lib;
|
||||
pOldType = pType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pOwningLib)
|
||||
{
|
||||
CryFatalError("SoftCode: Attempting to wait for update on an unknown instance!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InstanceFixup instanceFixup(pInstance);
|
||||
pOwningLib->AddListener(pOwningLib->GetName(), &instanceFixup, "InstanceFixup");
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Find and load new modules
|
||||
LoadNewModules();
|
||||
|
||||
// Got a new instance?
|
||||
if (instanceFixup.NewInstance())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for a new module
|
||||
CryLogAlways("SoftCode: Pausing execution until class %s in %s library is updated...", pOldType->GetName(), pOwningLib->GetName());
|
||||
__debugbreak(); // Stopped here? Check your log!
|
||||
}
|
||||
|
||||
pOwningLib->RemoveListener(&instanceFixup);
|
||||
|
||||
return instanceFixup.NewInstance();
|
||||
}
|
||||
|
||||
bool SoftCodeMgr::LoadModule(const char* moduleName)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// If module not yet loaded
|
||||
if (m_loadedSet.find(moduleName) == m_loadedSet.end())
|
||||
{
|
||||
m_loadedSet.insert(moduleName);
|
||||
|
||||
CryLogAlways("SoftCode: Found new module %s, attempting to load...", moduleName);
|
||||
|
||||
HMODULE hModule = CryLoadLibrary(moduleName);
|
||||
|
||||
if (hModule)
|
||||
{
|
||||
TGetTypeLibraryFcn pGetTypeLibraryFcn = reinterpret_cast<TGetTypeLibraryFcn>(GetProcAddress(hModule, DLL_GETTYPELIBRARY));
|
||||
if (pGetTypeLibraryFcn)
|
||||
{
|
||||
// Add to list of loaded libs & override any earlier TypeLibraries already registered
|
||||
ITypeLibrary* pTypeLibrary = pGetTypeLibraryFcn();
|
||||
if (pTypeLibrary)
|
||||
{
|
||||
const char* libraryName = pTypeLibrary->GetName();
|
||||
m_libraryMap[libraryName].IntegrateLibrary(pTypeLibrary, false);
|
||||
|
||||
CryLogAlways("SoftCode: Loaded new type library \"%s\" from module %s.", libraryName, moduleName);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Failed to resolve GetTypeLibrary() export in: %s (error: %x)", moduleName, GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "Failed to load: %s (error: %x)", moduleName, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
size_t SoftCodeMgr::FindSoftCodeFiles(const string& searchName, std::vector<string>& foundPaths) const
|
||||
{
|
||||
foundPaths.clear();
|
||||
|
||||
stack_string scSoftCodeDir;
|
||||
|
||||
TCHAR modulePath[MAX_PATH];
|
||||
GetModuleFileName(NULL, modulePath, sizeof(modulePath));
|
||||
scSoftCodeDir = PathUtil::GetParentDirectory(modulePath);
|
||||
scSoftCodeDir += "\\SoftCode\\";
|
||||
|
||||
|
||||
gEnv->pFileIO->FindFiles(scSoftCodeDir.c_str(), searchName, [&](const char* filePath) -> bool
|
||||
{
|
||||
if (!gEnv->pFileIO->IsDirectory(filePath) && !gEnv->pFileIO->IsReadOnly(filePath))
|
||||
{
|
||||
foundPaths.push_back(filePath);
|
||||
}
|
||||
|
||||
// Keep asking for more files, no early out
|
||||
return true;
|
||||
});
|
||||
|
||||
// Sort the paths into name order
|
||||
std::sort(foundPaths.begin(), foundPaths.end());
|
||||
|
||||
return foundPaths.size();
|
||||
}
|
||||
|
||||
#endif // SOFTCODE_ENABLED
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_SOFTCODE_SOFTCODEMGR_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_SOFTCODE_SOFTCODEMGR_H
|
||||
#pragma once
|
||||
|
||||
#include <CryListenerSet.h>
|
||||
|
||||
#include "ISoftCodeMgr.h"
|
||||
|
||||
struct ITypeLibrary;
|
||||
struct ITypeRegistrar;
|
||||
class CExchanger;
|
||||
|
||||
// Internal: Performs the dynamic type management needed for SoftCoding
|
||||
class DynamicTypeLibrary
|
||||
: public ITypeLibrary
|
||||
{
|
||||
public:
|
||||
DynamicTypeLibrary(const char* name = NULL);
|
||||
|
||||
// ITypeLibrary impl.
|
||||
virtual const char* GetName();
|
||||
virtual void* CreateInstanceVoid(const char* typeName);
|
||||
virtual void SetOverride(ITypeLibrary* pOverrideLib);
|
||||
virtual size_t GetTypes(ITypeRegistrar** ppRegistrar, size_t& count) const;
|
||||
|
||||
void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName);
|
||||
void RemoveListener(ISoftCodeListener* pListener);
|
||||
|
||||
// Attempts to add the library types the active set
|
||||
void IntegrateLibrary(ITypeLibrary* pLib, bool isDefault);
|
||||
|
||||
ITypeRegistrar* FindTypeForInstance(void* pInstance) const;
|
||||
|
||||
private:
|
||||
// Attempts to add the type the active set
|
||||
void IntegrateType(ITypeRegistrar* pType, bool isDefault);
|
||||
// Ensure the type can be safely created, visited, destroyed and prep exchanger
|
||||
bool EvaluateType(ITypeRegistrar* pType, CExchanger& exchanger);
|
||||
|
||||
private:
|
||||
typedef std::vector<ITypeLibrary*> TLibVec;
|
||||
typedef std::map<string, ITypeRegistrar*> TTypeMap;
|
||||
typedef CListenerSet<ISoftCodeListener*> TListeners;
|
||||
|
||||
// The current set of active types
|
||||
std::map<string, ITypeRegistrar*> m_types;
|
||||
// Current set of loaded libraries
|
||||
TLibVec m_history;
|
||||
// Set of listeners to SC changes
|
||||
TListeners m_listeners;
|
||||
|
||||
const char* m_name; // Supplied by the first real library that registers
|
||||
};
|
||||
|
||||
|
||||
// Implements the global singleton responsible for SoftCode management
|
||||
class SoftCodeMgr
|
||||
: public ISoftCodeMgr
|
||||
{
|
||||
public:
|
||||
SoftCodeMgr();
|
||||
virtual ~SoftCodeMgr();
|
||||
|
||||
// Used to register built-in libraries on first use
|
||||
virtual void RegisterLibrary(ITypeLibrary* pLib);
|
||||
|
||||
// Look for new SoftCode modules and load them, adding their types to the registry
|
||||
virtual void LoadNewModules();
|
||||
|
||||
virtual void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName);
|
||||
virtual void RemoveListener(const char* libraryName, ISoftCodeListener* pListener);
|
||||
|
||||
// To be called regularly to poll for library updates
|
||||
virtual void PollForNewModules();
|
||||
|
||||
// Stops thread execution until a new SoftCode module is available
|
||||
virtual void* WaitForUpdate(void* pInstance);
|
||||
|
||||
private:
|
||||
bool LoadModule(const char* moduleName);
|
||||
size_t FindSoftCodeFiles(const string& searchName, std::vector<string>& foundPaths) const;
|
||||
|
||||
private:
|
||||
typedef std::map<string, DynamicTypeLibrary> TLibMap;
|
||||
typedef std::set<string> TLoadedLibSet;
|
||||
|
||||
// Records the history for each TypeLibrary keyed by library name
|
||||
TLibMap m_libraryMap;
|
||||
|
||||
// Records the library files already loaded
|
||||
TLoadedLibSet m_loadedSet;
|
||||
|
||||
// Used to determine when the next auto-update will occur
|
||||
CTimeValue m_nextAutoCheckTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_SOFTCODE_SOFTCODEMGR_H
|
||||
@@ -124,8 +124,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include <ILog.h>
|
||||
#include <IAudioSystem.h>
|
||||
#include <IProcess.h>
|
||||
#include <INotificationNetwork.h>
|
||||
#include <ISoftCodeMgr.h>
|
||||
#include <LyShine/ILyShine.h>
|
||||
|
||||
#include <LoadScreenBus.h>
|
||||
@@ -133,8 +131,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
#include "XConsole.h"
|
||||
#include "Log.h"
|
||||
#include "NotificationNetwork.h"
|
||||
#include "ProfileLog.h"
|
||||
|
||||
#include "XML/xml.h"
|
||||
#include "XML/ReadWriteXMLSink.h"
|
||||
@@ -148,7 +144,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include "ServerThrottle.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "HMDBus.h"
|
||||
#include <IThreadManager.h>
|
||||
|
||||
#include "IZLibCompressor.h"
|
||||
#include "IZlibDecompressor.h"
|
||||
@@ -267,22 +262,6 @@ namespace
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
struct SCVarsWhitelistConfigSink
|
||||
: public ILoadConfigurationEntrySink
|
||||
{
|
||||
virtual void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup)
|
||||
{
|
||||
ICVarsWhitelist* pCVarsWhitelist = gEnv->pSystem->GetCVarsWhiteList();
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(szKey, false) : true;
|
||||
if (whitelisted)
|
||||
{
|
||||
gEnv->pConsole->LoadConfigVar(szKey, szValue);
|
||||
}
|
||||
}
|
||||
} g_CVarsWhitelistConfigSink;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// System Implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -322,27 +301,13 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_env.pSystem = this;
|
||||
m_env.pTimer = &m_Time;
|
||||
m_env.pNameTable = &m_nameTable;
|
||||
m_env.bServer = false;
|
||||
m_env.bMultiplayer = false;
|
||||
m_env.bHostMigrating = false;
|
||||
m_env.bIgnoreAllAsserts = false;
|
||||
m_env.bNoAssertDialog = false;
|
||||
m_env.bTesting = false;
|
||||
|
||||
m_env.pSharedEnvironment = pSharedEnvironment;
|
||||
|
||||
m_env.SetFMVIsPlaying(false);
|
||||
m_env.SetCutsceneIsPlaying(false);
|
||||
|
||||
m_env.szDebugStatus[0] = '\0';
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
m_env.SetIsClient(false);
|
||||
#endif
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
m_pStreamEngine = NULL;
|
||||
m_PhysThread = 0;
|
||||
|
||||
m_pIFont = NULL;
|
||||
m_pIFontUi = NULL;
|
||||
@@ -370,7 +335,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_pILZ4Decompressor = NULL;
|
||||
m_pIZStdDecompressor = nullptr;
|
||||
m_pLocalizationManager = NULL;
|
||||
m_sys_physics_CPU = 0;
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_2
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
@@ -378,15 +342,9 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_sys_min_step = 0;
|
||||
m_sys_max_step = 0;
|
||||
|
||||
m_pNotificationNetwork = NULL;
|
||||
|
||||
m_cvAIUpdate = NULL;
|
||||
|
||||
m_pUserCallback = NULL;
|
||||
#if defined(CVARS_WHITELIST)
|
||||
m_pCVarsWhitelist = NULL;
|
||||
m_pCVarsWhitelistConfigSink = &g_CVarsWhitelistConfigSink;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
m_sys_memory_debug = NULL;
|
||||
m_sysWarnings = NULL;
|
||||
m_sysKeyboard = NULL;
|
||||
@@ -409,13 +367,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_bNoCrashDialog = false;
|
||||
m_bNoErrorReportWindow = false;
|
||||
|
||||
#ifndef _RELEASE
|
||||
m_checkpointLoadCount = 0;
|
||||
m_loadOrigin = eLLO_Unknown;
|
||||
m_hasJustResumed = false;
|
||||
m_expectingMapCommand = false;
|
||||
#endif
|
||||
|
||||
m_pCVarQuit = NULL;
|
||||
|
||||
m_bForceNonDevMode = false;
|
||||
@@ -429,13 +380,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
m_nServerConfigSpec = CONFIG_VERYHIGH_SPEC;
|
||||
m_nMaxConfigSpec = CONFIG_VERYHIGH_SPEC;
|
||||
|
||||
//m_hPhysicsThread = INVALID_HANDLE_VALUE;
|
||||
//m_hPhysicsActive = INVALID_HANDLE_VALUE;
|
||||
//m_bStopPhysics = 0;
|
||||
//m_bPhysicsActive = 0;
|
||||
|
||||
m_pProgressListener = 0;
|
||||
|
||||
m_bPaused = false;
|
||||
m_bNoUpdate = false;
|
||||
m_nUpdateCounter = 0;
|
||||
@@ -444,12 +388,9 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
|
||||
m_pXMLUtils = new CXmlUtils(this);
|
||||
m_pMemoryManager = CryGetIMemoryManager();
|
||||
m_pThreadTaskManager = new CThreadTaskManager;
|
||||
m_pResourceManager = new CResourceManager;
|
||||
m_pTextModeConsole = NULL;
|
||||
|
||||
InitThreadSystem();
|
||||
|
||||
g_pPakHeap = new CMTSafeHeap;
|
||||
|
||||
if (!AZ::AllocatorInstance<AZ::OSAllocator>::IsReady())
|
||||
@@ -464,7 +405,6 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
AZ::Debug::Trace::Instance().Init();
|
||||
}
|
||||
|
||||
m_UpdateTimesIdx = 0U;
|
||||
m_bNeedDoWorkDuringOcclusionChecks = false;
|
||||
|
||||
m_eRuntimeState = ESYSTEM_EVENT_LEVEL_UNLOAD;
|
||||
@@ -478,15 +418,12 @@ CSystem::CSystem(SharedEnvironmentInstance* pSharedEnvironment)
|
||||
#endif
|
||||
|
||||
m_ConfigPlatform = CONFIG_INVALID_PLATFORM;
|
||||
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
CSystem::~CSystem()
|
||||
{
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect();
|
||||
ShutDown();
|
||||
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_USE_MESSAGE_HANDLER
|
||||
@@ -496,16 +433,8 @@ CSystem::~CSystem()
|
||||
CRY_ASSERT(m_windowMessageHandlers.empty() && "There exists a dangling window message handler somewhere");
|
||||
|
||||
SAFE_DELETE(m_pXMLUtils);
|
||||
SAFE_DELETE(m_pThreadTaskManager);
|
||||
SAFE_DELETE(m_pResourceManager);
|
||||
SAFE_DELETE(m_pSystemEventDispatcher);
|
||||
// SAFE_DELETE(m_pMemoryManager);
|
||||
|
||||
if (gEnv && gEnv->pThreadManager)
|
||||
{
|
||||
gEnv->pThreadManager->UnRegisterThirdPartyThread("Main");
|
||||
}
|
||||
ShutDownThreadSystem();
|
||||
|
||||
SAFE_DELETE(g_pPakHeap);
|
||||
|
||||
@@ -617,8 +546,6 @@ void CSystem::ShutDown()
|
||||
|
||||
SAFE_DELETE(m_pTextModeConsole);
|
||||
|
||||
KillPhysicsThread();
|
||||
|
||||
if (m_sys_firstlaunch)
|
||||
{
|
||||
m_sys_firstlaunch->Set("0");
|
||||
@@ -664,8 +591,6 @@ void CSystem::ShutDown()
|
||||
gEnv->pLyShine = nullptr;
|
||||
}
|
||||
|
||||
SAFE_DELETE(m_env.pResourceCompilerHelper);
|
||||
|
||||
SAFE_RELEASE(m_env.pMovieSystem);
|
||||
SAFE_RELEASE(m_env.pLyShine);
|
||||
SAFE_RELEASE(m_env.pCryFont);
|
||||
@@ -706,7 +631,6 @@ void CSystem::ShutDown()
|
||||
SAFE_RELEASE(m_sys_GraphicsQuality);
|
||||
SAFE_RELEASE(m_sys_firstlaunch);
|
||||
SAFE_RELEASE(m_sys_enable_budgetmonitoring);
|
||||
SAFE_RELEASE(m_sys_physics_CPU);
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_3
|
||||
@@ -716,9 +640,6 @@ void CSystem::ShutDown()
|
||||
SAFE_RELEASE(m_sys_min_step);
|
||||
SAFE_RELEASE(m_sys_max_step);
|
||||
|
||||
SAFE_RELEASE(m_pNotificationNetwork);
|
||||
|
||||
SAFE_DELETE(m_env.pSoftCodeMgr);
|
||||
SAFE_DELETE(m_pDefaultValidator);
|
||||
m_pValidator = nullptr;
|
||||
|
||||
@@ -743,7 +664,6 @@ void CSystem::ShutDown()
|
||||
SAFE_RELEASE(m_env.pConsole);
|
||||
|
||||
// Log must be last thing released.
|
||||
SAFE_RELEASE(m_env.pProfileLogSystem);
|
||||
if (m_env.pLog)
|
||||
{
|
||||
m_env.pLog->FlushAndClose();
|
||||
@@ -752,10 +672,6 @@ void CSystem::ShutDown()
|
||||
|
||||
ShutdownFileSystem();
|
||||
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
delete gEnv->pSystemScheduler;
|
||||
#endif // defined(MAP_LOADING_SLICING)
|
||||
|
||||
ShutdownModuleLibraries();
|
||||
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPostShutdown);
|
||||
@@ -841,273 +757,6 @@ ISystem* CSystem::GetCrySystem()
|
||||
return this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Physics thread task
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CPhysicsThreadTask
|
||||
: public IThreadTask
|
||||
{
|
||||
public:
|
||||
|
||||
CPhysicsThreadTask()
|
||||
{
|
||||
m_bStopRequested = 0;
|
||||
m_bIsActive = 0;
|
||||
m_stepRequested = 0;
|
||||
m_bProcessing = 0;
|
||||
m_doZeroStep = 0;
|
||||
m_lastStepTimeTaken = 0U;
|
||||
m_lastWaitTimeTaken = 0U;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IThreadTask implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void OnUpdate()
|
||||
{
|
||||
Run();
|
||||
// At the end.. delete the task
|
||||
delete this;
|
||||
}
|
||||
virtual void Stop()
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
virtual SThreadTaskInfo* GetTaskInfo() { return &m_TaskInfo; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void Run()
|
||||
{
|
||||
m_bStopRequested = 0;
|
||||
m_bIsActive = 1;
|
||||
|
||||
float step, timeTaken, kSlowdown = 1.0f;
|
||||
int nSlowFrames = 0;
|
||||
int64 timeStart;
|
||||
#ifdef ENABLE_LW_PROFILERS
|
||||
LARGE_INTEGER stepStart, stepEnd;
|
||||
#endif
|
||||
LARGE_INTEGER waitStart, waitEnd;
|
||||
MarkThisThreadForDebugging("Physics");
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_5
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
#endif
|
||||
while (true)
|
||||
{
|
||||
QueryPerformanceCounter(&waitStart);
|
||||
m_FrameEvent.Wait(); // Wait untill new frame
|
||||
QueryPerformanceCounter(&waitEnd);
|
||||
m_lastWaitTimeTaken = waitEnd.QuadPart - waitStart.QuadPart;
|
||||
|
||||
if (m_bStopRequested)
|
||||
{
|
||||
UnmarkThisThreadFromDebugging();
|
||||
return;
|
||||
}
|
||||
bool stepped = false;
|
||||
#ifdef ENABLE_LW_PROFILERS
|
||||
QueryPerformanceCounter(&stepStart);
|
||||
#endif
|
||||
while ((step = m_stepRequested) > 0 || m_doZeroStep)
|
||||
{
|
||||
stepped = true;
|
||||
m_stepRequested = 0;
|
||||
m_bProcessing = 1;
|
||||
m_doZeroStep = 0;
|
||||
|
||||
if (kSlowdown != 1.0f)
|
||||
{
|
||||
step = max(1, FtoI(step * kSlowdown * 50 - 0.5f)) * 0.02f;
|
||||
}
|
||||
timeStart = CryGetTicks();
|
||||
timeTaken = gEnv->pTimer->TicksToSeconds(CryGetTicks() - timeStart);
|
||||
if (timeTaken > step * 0.9f)
|
||||
{
|
||||
if (++nSlowFrames > 5)
|
||||
{
|
||||
kSlowdown = step * 0.9f / timeTaken;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kSlowdown = 1.0f, nSlowFrames = 0;
|
||||
}
|
||||
m_bProcessing = 0;
|
||||
//int timeSleep = (int)((m_timeTarget-gEnv->pTimer->GetAsyncTime()).GetMilliSeconds()*0.9f);
|
||||
//Sleep(max(0,timeSleep));
|
||||
}
|
||||
if (!stepped)
|
||||
{
|
||||
Sleep(0);
|
||||
}
|
||||
m_FrameDone.Set();
|
||||
#ifdef ENABLE_LW_PROFILERS
|
||||
QueryPerformanceCounter(&stepEnd);
|
||||
m_lastStepTimeTaken = stepEnd.QuadPart - stepStart.QuadPart;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
virtual void Cancel()
|
||||
{
|
||||
Pause();
|
||||
m_bStopRequested = 1;
|
||||
m_FrameEvent.Set();
|
||||
m_bIsActive = 0;
|
||||
}
|
||||
|
||||
int Pause()
|
||||
{
|
||||
if (m_bIsActive)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION_STALL(AZ::Debug::ProfileCategory::System);
|
||||
m_bIsActive = 0;
|
||||
while (m_bProcessing)
|
||||
{
|
||||
;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int Resume()
|
||||
{
|
||||
if (!m_bIsActive)
|
||||
{
|
||||
m_bIsActive = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int IsActive() { return m_bIsActive; }
|
||||
int RequestStep(float dt)
|
||||
{
|
||||
if (m_bIsActive && dt > FLT_EPSILON)
|
||||
{
|
||||
m_stepRequested += dt;
|
||||
if (dt <= 0.0f)
|
||||
{
|
||||
m_doZeroStep = 1;
|
||||
}
|
||||
m_FrameEvent.Set();
|
||||
}
|
||||
|
||||
return m_bProcessing;
|
||||
}
|
||||
float GetRequestedStep() { return m_stepRequested; }
|
||||
|
||||
uint64 LastStepTaken() const
|
||||
{
|
||||
return m_lastStepTimeTaken;
|
||||
}
|
||||
|
||||
uint64 LastWaitTime() const
|
||||
{
|
||||
return m_lastWaitTimeTaken;
|
||||
}
|
||||
|
||||
void EnsureStepDone()
|
||||
{
|
||||
FRAME_PROFILER("SysUpdate:PhysicsEnsureDone", gEnv->pSystem, PROFILE_SYSTEM);
|
||||
if (m_bIsActive)
|
||||
{
|
||||
while (m_stepRequested > 0.0f || m_bProcessing)
|
||||
{
|
||||
m_FrameDone.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
volatile int m_bStopRequested;
|
||||
volatile int m_bIsActive;
|
||||
volatile float m_stepRequested;
|
||||
volatile int m_bProcessing;
|
||||
volatile int m_doZeroStep;
|
||||
volatile uint64 m_lastStepTimeTaken;
|
||||
volatile uint64 m_lastWaitTimeTaken;
|
||||
|
||||
CryEvent m_FrameEvent;
|
||||
CryEvent m_FrameDone;
|
||||
|
||||
SThreadTaskInfo m_TaskInfo;
|
||||
};
|
||||
|
||||
void CSystem::CreatePhysicsThread()
|
||||
{
|
||||
if (!m_PhysThread)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SThreadTaskParams threadParams;
|
||||
threadParams.name = "Physics";
|
||||
threadParams.nFlags = THREAD_TASK_BLOCKING;
|
||||
threadParams.nStackSizeKB = PHYSICS_STACK_SIZE >> 10;
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_6
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
#endif
|
||||
|
||||
{
|
||||
m_PhysThread = new CPhysicsThreadTask;
|
||||
GetIThreadTaskManager()->RegisterTask(m_PhysThread, threadParams);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CSystem::KillPhysicsThread()
|
||||
{
|
||||
if (m_PhysThread)
|
||||
{
|
||||
GetIThreadTaskManager()->UnregisterTask(m_PhysThread);
|
||||
m_PhysThread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AzFramework::Terrain::TerrainDataNotificationBus START
|
||||
void CSystem::OnTerrainDataCreateBegin()
|
||||
{
|
||||
KillPhysicsThread();
|
||||
}
|
||||
|
||||
void CSystem::OnTerrainDataDestroyBegin()
|
||||
{
|
||||
OnTerrainDataCreateBegin();
|
||||
}
|
||||
|
||||
// AzFramework::Terrain::TerrainDataNotificationBus END
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CSystem::SetThreadState(ESubsystem subsys, bool bActive)
|
||||
{
|
||||
switch (subsys)
|
||||
{
|
||||
case ESubsys_Physics:
|
||||
{
|
||||
if (m_PhysThread)
|
||||
{
|
||||
return bActive ? ((CPhysicsThreadTask*)m_PhysThread)->Resume() : ((CPhysicsThreadTask*)m_PhysThread)->Pause();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::SleepIfInactive()
|
||||
{
|
||||
// ProcessSleep()
|
||||
if (m_bDedicatedServer || m_bEditor || gEnv->bMultiplayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::SleepIfNeeded()
|
||||
{
|
||||
@@ -1180,11 +829,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
// do the dedicated sleep earlier than the frame profiler to avoid having it counted
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
gEnv->pSystemScheduler->SchedulingSleepIfNeeded();
|
||||
#else
|
||||
SleepIfNeeded();
|
||||
#endif // defined(MAP_LOADING_SLICING)
|
||||
}
|
||||
#endif //EXCLUDE_UPDATE_ON_CONSOLE
|
||||
|
||||
@@ -1199,9 +844,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
|
||||
m_nUpdateCounter++;
|
||||
#ifndef EXCLUDE_UPDATE_ON_CONSOLE
|
||||
// Check if game needs to be sleeping when not active.
|
||||
SleepIfInactive();
|
||||
|
||||
if (m_pUserCallback)
|
||||
{
|
||||
m_pUserCallback->OnUpdate();
|
||||
@@ -1216,7 +858,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
prev_sys_float_exceptions = g_cvars.sys_float_exceptions;
|
||||
|
||||
EnableFloatExceptions(g_cvars.sys_float_exceptions);
|
||||
UpdateFPExceptionsMaskForThreads();
|
||||
}
|
||||
#endif //EXCLUDE_UPDATE_ON_CONSOLE
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1263,13 +904,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
}
|
||||
#endif //PROFILE_WITH_VTUNE
|
||||
|
||||
#ifdef SOFTCODE_SYSTEM_ENABLED
|
||||
if (m_env.pSoftCodeMgr)
|
||||
{
|
||||
m_env.pSoftCodeMgr->PollForNewModules();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_pStreamEngine)
|
||||
{
|
||||
FRAME_PROFILER("StreamEngine::Update()", this, PROFILE_SYSTEM);
|
||||
@@ -1290,7 +924,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
if (m_sysNoUpdate && m_sysNoUpdate->GetIVal())
|
||||
{
|
||||
bNoUpdate = true;
|
||||
updateFlags = ESYSUPDATE_IGNORE_PHYSICS;
|
||||
}
|
||||
|
||||
m_bNoUpdate = bNoUpdate;
|
||||
@@ -1373,16 +1006,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef EXCLUDE_UPDATE_ON_CONSOLE
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//update notification network system
|
||||
if (m_pNotificationNetwork)
|
||||
{
|
||||
FRAME_PROFILER("SysUpdate:NotificationNetwork", this, PROFILE_SYSTEM);
|
||||
m_pNotificationNetwork->Update();
|
||||
}
|
||||
#endif //EXCLUDE_UPDATE_ON_CONSOLE
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//update sound system Part 1 if in Editor / in Game Mode Viewsystem updates the Listeners
|
||||
if (!m_env.IsEditorGameMode())
|
||||
@@ -1401,15 +1024,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update Threads Task Manager.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (m_pThreadTaskManager)
|
||||
{
|
||||
FRAME_PROFILER("SysUpdate:ThreadTaskManager", this, PROFILE_SYSTEM);
|
||||
m_pThreadTaskManager->OnUpdate();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Update Resource Manager.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1418,77 +1032,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
m_pResourceManager->Update();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// update physic system
|
||||
//static float time_zero = 0;
|
||||
if (m_sys_physics_CPU->GetIVal() > 0 && !gEnv->IsDedicated())
|
||||
{
|
||||
CreatePhysicsThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
KillPhysicsThread();
|
||||
}
|
||||
|
||||
static int g_iPausedPhys = 0;
|
||||
|
||||
CPhysicsThreadTask* pPhysicsThreadTask = ((CPhysicsThreadTask*)m_PhysThread);
|
||||
if (!pPhysicsThreadTask)
|
||||
{
|
||||
FRAME_PROFILER_LEGACYONLY("SysUpdate:AllAIAndPhysics", this, PROFILE_SYSTEM);
|
||||
AZ_TRACE_METHOD_NAME("SysUpdate::AllAIAndPhysics");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// update entity system (a little bit) before physics
|
||||
if (nPauseMode != 1)
|
||||
{
|
||||
if (!bNoUpdate)
|
||||
{
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPrePhysicsUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// intermingle physics/AI updates so that if we get a big timestep (frame rate glitch etc) the
|
||||
// AI gets to steer entities before they travel over cliffs etc.
|
||||
const float maxTimeStep = 0.25f;
|
||||
int maxSteps = 1;
|
||||
//float fCurTime = m_Time.GetCurrTime();
|
||||
float timeToDo = m_Time.GetFrameTime();//fCurTime - fPrevTime;
|
||||
if (m_env.bMultiplayer)
|
||||
{
|
||||
timeToDo = m_Time.GetRealFrameTime();
|
||||
}
|
||||
|
||||
|
||||
|
||||
while (timeToDo > 0.0001f && maxSteps-- > 0)
|
||||
{
|
||||
float thisStep = min(maxTimeStep, timeToDo);
|
||||
timeToDo -= thisStep;
|
||||
|
||||
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPostPhysicsUpdate);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// In multithreaded physics mode, post physics fires after physics events are dispatched on the main thread.
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPostPhysicsUpdate);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// update entity system (a little bit) before physics
|
||||
if (nPauseMode != 1)
|
||||
{
|
||||
if (!bNoUpdate)
|
||||
{
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPrePhysicsUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Use UI timer for CryMovie, because it should not be affected by pausing game time
|
||||
const float fMovieFrameTime = m_Time.GetFrameTime(ITimer::ETIMER_UI);
|
||||
|
||||
@@ -1550,8 +1093,6 @@ bool CSystem::UpdatePostTickBus(int updateFlags, int /*nPauseMode*/)
|
||||
m_updateTimes.push_back(std::make_pair(cur_time, updateTime));
|
||||
}
|
||||
|
||||
UpdateUpdateTimes();
|
||||
|
||||
{
|
||||
FRAME_PROFILER("SysUpdate - SystemEventDispatcher::Update", this, PROFILE_SYSTEM);
|
||||
m_pSystemEventDispatcher->Update();
|
||||
@@ -1890,12 +1431,6 @@ ILocalizationManager* CSystem::GetLocalizationManager()
|
||||
return m_pLocalizationManager;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IThreadTaskManager* CSystem::GetIThreadTaskManager()
|
||||
{
|
||||
return m_pThreadTaskManager;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IResourceManager* CSystem::GetIResourceManager()
|
||||
{
|
||||
@@ -1960,10 +1495,6 @@ void CSystem::ExecuteCommandLine(bool deferred)
|
||||
if (pCmd->GetType() == eCLAT_Post)
|
||||
{
|
||||
string sLine = pCmd->GetName();
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
if (!GetCVarsWhiteList() || GetCVarsWhiteList()->IsWhiteListed(sLine, false))
|
||||
#endif
|
||||
{
|
||||
if (pCmd->GetValue())
|
||||
{
|
||||
@@ -1973,12 +1504,6 @@ void CSystem::ExecuteCommandLine(bool deferred)
|
||||
GetILog()->Log("Executing command from command line: \n%s\n", sLine.c_str()); // - the actual command might be executed much later (e.g. level load pause)
|
||||
GetIConsole()->ExecuteString(sLine.c_str(), false, deferred);
|
||||
}
|
||||
#if defined(CVARS_WHITELIST)
|
||||
else if (gEnv->IsDedicated())
|
||||
{
|
||||
GetILog()->LogError("Failed to execute command: '%s' as it is not whitelisted\n", sLine.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2078,93 +1603,6 @@ void CProfilingSystem::VTunePause()
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
sUpdateTimes& CSystem::GetCurrentUpdateTimeStats()
|
||||
{
|
||||
return m_UpdateTimes[m_UpdateTimesIdx];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const sUpdateTimes* CSystem::GetUpdateTimeStats(uint32& index, uint32& num)
|
||||
{
|
||||
index = m_UpdateTimesIdx;
|
||||
num = NUM_UPDATE_TIMES;
|
||||
return m_UpdateTimes;
|
||||
}
|
||||
|
||||
void CSystem::UpdateUpdateTimes()
|
||||
{
|
||||
sUpdateTimes& sample = m_UpdateTimes[m_UpdateTimesIdx];
|
||||
if (m_PhysThread)
|
||||
{
|
||||
static uint64 lastPhysTime = 0U;
|
||||
static uint64 lastMainTime = 0U;
|
||||
static uint64 lastYields = 0U;
|
||||
static uint64 lastPhysWait = 0U;
|
||||
uint64 physTime = 0, mainTime = 0;
|
||||
uint32 yields = 0;
|
||||
physTime = ((CPhysicsThreadTask*)m_PhysThread)->LastStepTaken();
|
||||
mainTime = CryGetTicks() - lastMainTime;
|
||||
lastMainTime = mainTime;
|
||||
lastPhysWait = ((CPhysicsThreadTask*)m_PhysThread)->LastWaitTime();
|
||||
sample.PhysStepTime = physTime;
|
||||
sample.SysUpdateTime = mainTime;
|
||||
sample.PhysYields = yields;
|
||||
sample.physWaitTime = lastPhysWait;
|
||||
}
|
||||
++m_UpdateTimesIdx;
|
||||
if (m_UpdateTimesIdx >= NUM_UPDATE_TIMES)
|
||||
{
|
||||
m_UpdateTimesIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef _RELEASE
|
||||
void CSystem::GetCheckpointData(ICheckpointData& data)
|
||||
{
|
||||
data.m_totalLoads = m_checkpointLoadCount;
|
||||
data.m_loadOrigin = m_loadOrigin;
|
||||
}
|
||||
|
||||
void CSystem::IncreaseCheckpointLoadCount()
|
||||
{
|
||||
if (!m_hasJustResumed)
|
||||
{
|
||||
++m_checkpointLoadCount;
|
||||
}
|
||||
|
||||
m_hasJustResumed = false;
|
||||
}
|
||||
|
||||
void CSystem::SetLoadOrigin(LevelLoadOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case eLLO_NewLevel: // Intentional fall through
|
||||
case eLLO_Level2Level:
|
||||
m_expectingMapCommand = true;
|
||||
break;
|
||||
|
||||
case eLLO_Resumed:
|
||||
m_hasJustResumed = true;
|
||||
break;
|
||||
|
||||
case eLLO_MapCmd:
|
||||
if (m_expectingMapCommand)
|
||||
{
|
||||
// We knew a map command was coming, so don't process this.
|
||||
m_expectingMapCommand = false;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_loadOrigin = origin;
|
||||
m_checkpointLoadCount = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CSystem::SteamInit()
|
||||
{
|
||||
#if USE_STEAM
|
||||
|
||||
@@ -26,14 +26,12 @@
|
||||
#include "MTSafeAllocator.h"
|
||||
#include "CPUDetect.h"
|
||||
#include <AzFramework/Archive/ArchiveVars.h>
|
||||
#include "ThreadTask.h"
|
||||
#include "RenderBus.h"
|
||||
|
||||
#include <LoadScreenBus.h>
|
||||
#include <ThermalInfo.h>
|
||||
|
||||
#include <AzCore/Module/DynamicModuleHandle.h>
|
||||
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
@@ -44,7 +42,6 @@ struct IConsoleCmdArgs;
|
||||
class CServerThrottle;
|
||||
struct IZLibCompressor;
|
||||
class CWatchdogThread;
|
||||
class CThreadManager;
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
@@ -183,8 +180,6 @@ class CThreadManager;
|
||||
#include "CryLibrary.h"
|
||||
#endif
|
||||
|
||||
#define NUM_UPDATE_TIMES (128U)
|
||||
|
||||
#ifdef WIN32
|
||||
typedef void* WIN_HMODULE;
|
||||
#else
|
||||
@@ -241,7 +236,6 @@ struct SSystemCVars
|
||||
int sys_WER;
|
||||
int sys_dump_type;
|
||||
int sys_ai;
|
||||
int sys_physics;
|
||||
int sys_entitysystem;
|
||||
int sys_trackview;
|
||||
int sys_vtune;
|
||||
@@ -342,7 +336,6 @@ class CSystem
|
||||
, public IWindowMessageHandler
|
||||
, public AZ::RenderNotificationsBus::Handler
|
||||
, public CrySystemRequestBus::Handler
|
||||
, private AzFramework::Terrain::TerrainDataNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -397,20 +390,8 @@ public:
|
||||
ISystem* GetCrySystem() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Update screen during loading.
|
||||
void UpdateLoadingScreen();
|
||||
|
||||
//! Update screen and call some important tick functions during loading.
|
||||
void SynchronousLoadingTick(const char* pFunc, int line);
|
||||
|
||||
uint32 GetUsedMemory();
|
||||
|
||||
#ifndef _RELEASE
|
||||
virtual void GetCheckpointData(ICheckpointData& data);
|
||||
virtual void IncreaseCheckpointLoadCount();
|
||||
virtual void SetLoadOrigin(LevelLoadOrigin origin);
|
||||
#endif
|
||||
|
||||
virtual bool SteamInit();
|
||||
|
||||
void Relaunch(bool bRelaunch);
|
||||
@@ -425,8 +406,6 @@ public:
|
||||
virtual const char* GetUserName();
|
||||
virtual int GetApplicationInstance();
|
||||
int GetApplicationLogInstance(const char* logFilePath) override;
|
||||
virtual sUpdateTimes& GetCurrentUpdateTimeStats();
|
||||
virtual const sUpdateTimes* GetUpdateTimeStats(uint32&, uint32&);
|
||||
|
||||
ITimer* GetITimer(){ return m_env.pTimer; }
|
||||
AZ::IO::IArchive* GetIPak() { return m_env.pCryPak; };
|
||||
@@ -434,7 +413,6 @@ public:
|
||||
IRemoteConsole* GetIRemoteConsole();
|
||||
IMovieSystem* GetIMovieSystem() { return m_env.pMovieSystem; };
|
||||
IMemoryManager* GetIMemoryManager(){ return m_pMemoryManager; }
|
||||
IThreadManager* GetIThreadManager() override {return m_env.pThreadManager; }
|
||||
ICryFont* GetICryFont(){ return m_env.pCryFont; }
|
||||
ILog* GetILog(){ return m_env.pLog; }
|
||||
ICmdLine* GetICmdLine(){ return m_pCmdLine; }
|
||||
@@ -444,11 +422,8 @@ public:
|
||||
IViewSystem* GetIViewSystem();
|
||||
ILevelSystem* GetILevelSystem();
|
||||
ISystemEventDispatcher* GetISystemEventDispatcher() { return m_pSystemEventDispatcher; }
|
||||
IThreadTaskManager* GetIThreadTaskManager();
|
||||
IResourceManager* GetIResourceManager();
|
||||
ITextModeConsole* GetITextModeConsole();
|
||||
IVisualLog* GetIVisualLog() { return m_env.pVisualLog; }
|
||||
INotificationNetwork* GetINotificationNetwork() { return m_pNotificationNetwork; }
|
||||
IProfilingSystem* GetIProfilingSystem() { return &m_ProfilingSystem; }
|
||||
IZLibCompressor* GetIZLibCompressor() { return m_pIZLibCompressor; }
|
||||
IZLibDecompressor* GetIZLibDecompressor() { return m_pIZLibDecompressor; }
|
||||
@@ -459,19 +434,6 @@ public:
|
||||
CPNoise3* GetNoiseGen();
|
||||
virtual uint64 GetUpdateCounter() { return m_nUpdateCounter; };
|
||||
|
||||
virtual void SetLoadingProgressListener(ILoadingProgressListener* pLoadingProgressListener)
|
||||
{
|
||||
m_pProgressListener = pLoadingProgressListener;
|
||||
};
|
||||
|
||||
virtual ILoadingProgressListener* GetLoadingProgressListener() const
|
||||
{
|
||||
return m_pProgressListener;
|
||||
};
|
||||
|
||||
void SetIMaterialEffects(IMaterialEffects* pMaterialEffects) { m_env.pMaterialEffects = pMaterialEffects; }
|
||||
void SetIOpticsManager(IOpticsManager* pOpticsManager) { m_env.pOpticsManager = pOpticsManager; }
|
||||
void SetIVisualLog(IVisualLog* pVisualLog) { m_env.pVisualLog = pVisualLog; }
|
||||
void DetectGameFolderAccessRights();
|
||||
|
||||
virtual void ExecuteCommandLine(bool deferred=true);
|
||||
@@ -554,12 +516,6 @@ public:
|
||||
|
||||
//! Return pointer to user defined callback.
|
||||
ISystemUserCallback* GetUserCallback() const { return m_pUserCallback; };
|
||||
#if defined(CVARS_WHITELIST)
|
||||
virtual ICVarsWhitelist* GetCVarsWhiteList() const { return m_pCVarsWhitelist; };
|
||||
virtual ILoadConfigurationEntrySink* GetCVarsWhiteListConfigSink() const { return m_pCVarsWhitelistConfigSink; }
|
||||
#else
|
||||
virtual ILoadConfigurationEntrySink* GetCVarsWhiteListConfigSink() const { return nullptr; }
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SaveConfiguration();
|
||||
@@ -571,7 +527,6 @@ public:
|
||||
virtual void SetConfigPlatform(ESystemConfigPlatform platform);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual int SetThreadState(ESubsystem subsys, bool bActive);
|
||||
virtual bool IsPaused() const { return m_bPaused; };
|
||||
|
||||
virtual ILocalizationManager* GetLocalizationManager();
|
||||
@@ -608,8 +563,6 @@ private:
|
||||
// Release all resources.
|
||||
void ShutDown();
|
||||
|
||||
void SleepIfInactive();
|
||||
|
||||
bool LoadEngineDLLs();
|
||||
|
||||
//! @name Initialization routines
|
||||
@@ -623,12 +576,6 @@ private:
|
||||
|
||||
//@}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Threading functions.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void InitThreadSystem();
|
||||
void ShutDownThreadSystem();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -645,9 +592,6 @@ private:
|
||||
void LogBuildInfo();
|
||||
void SetDevMode(bool bEnable);
|
||||
|
||||
void CreatePhysicsThread();
|
||||
void KillPhysicsThread();
|
||||
|
||||
#ifndef _RELEASE
|
||||
static void SystemVersionChanged(ICVar* pCVar);
|
||||
#endif // #ifndef _RELEASE
|
||||
@@ -676,7 +620,6 @@ public:
|
||||
virtual bool GetForceNonDevMode() const;
|
||||
virtual bool WasInDevMode() const { return m_bWasInDevMode; };
|
||||
virtual bool IsDevMode() const { return m_bInDevMode && !GetForceNonDevMode(); }
|
||||
virtual bool IsMinimalMode() const { return m_bMinimal; }
|
||||
virtual bool IsMODValid(const char* szMODName) const
|
||||
{
|
||||
if (!szMODName || strstr(szMODName, ".") || strstr(szMODName, "\\"))
|
||||
@@ -727,7 +670,6 @@ private: // ------------------------------------------------------
|
||||
bool m_bRelaunch; //!< relaunching the app or not (true beforerelaunch)
|
||||
int m_iLoadingMode; //!< Game is loading w/o changing context (0 not, 1 quickloading, 2 full loading)
|
||||
bool m_bTestMode; //!< If running in testing mode.
|
||||
bool m_bMinimal; //!< If running in 'minimal mode'.
|
||||
bool m_bEditor; //!< If running in Editor.
|
||||
bool m_bNoCrashDialog;
|
||||
bool m_bNoErrorReportWindow;
|
||||
@@ -742,16 +684,6 @@ private: // ------------------------------------------------------
|
||||
SDefaultValidator* m_pDefaultValidator; //!<
|
||||
CCpuFeatures* m_pCpu; //!< CPU features
|
||||
int m_ttMemStatSS; //!< Time to memstat screenshot
|
||||
string m_szCmdLine;
|
||||
|
||||
int m_iTraceAllocations;
|
||||
|
||||
#ifndef _RELEASE
|
||||
int m_checkpointLoadCount;// Total times game has loaded from a checkpoint
|
||||
LevelLoadOrigin m_loadOrigin; // Where the load was initiated from
|
||||
bool m_hasJustResumed; // Has resume game just been called
|
||||
bool m_expectingMapCommand;
|
||||
#endif
|
||||
bool m_bDrawConsole; //!< Set to true if OK to draw the console.
|
||||
bool m_bDrawUI; //!< Set to true if OK to draw UI.
|
||||
|
||||
@@ -867,8 +799,6 @@ private: // ------------------------------------------------------
|
||||
ICVar* m_sys_asset_processor;
|
||||
ICVar* m_sys_load_files_to_memory;
|
||||
|
||||
ICVar* m_sys_physics_CPU;
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_H_SECTION_4
|
||||
#include AZ_RESTRICTED_FILE(System_h)
|
||||
@@ -891,15 +821,6 @@ private: // ------------------------------------------------------
|
||||
//! User define callback for system events.
|
||||
ISystemUserCallback* m_pUserCallback;
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! User define callback for whitelisting cvars
|
||||
ICVarsWhitelist* m_pCVarsWhitelist;
|
||||
ILoadConfigurationEntrySink* m_pCVarsWhitelistConfigSink;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
//int m_nCurrentLogVerbosity;
|
||||
|
||||
SFileVersion m_fileVersion;
|
||||
SFileVersion m_productVersion;
|
||||
SFileVersion m_buildVersion;
|
||||
@@ -910,8 +831,6 @@ private: // ------------------------------------------------------
|
||||
// Name table.
|
||||
CNameTable m_nameTable;
|
||||
|
||||
IThreadTask* m_PhysThread;
|
||||
|
||||
ESystemConfigSpec m_nServerConfigSpec;
|
||||
ESystemConfigSpec m_nMaxConfigSpec;
|
||||
ESystemConfigPlatform m_ConfigPlatform;
|
||||
@@ -919,8 +838,6 @@ private: // ------------------------------------------------------
|
||||
std::unique_ptr<CServerThrottle> m_pServerThrottle;
|
||||
|
||||
CProfilingSystem m_ProfilingSystem;
|
||||
sUpdateTimes m_UpdateTimes[NUM_UPDATE_TIMES];
|
||||
uint32 m_UpdateTimesIdx;
|
||||
|
||||
// Pause mode.
|
||||
bool m_bPaused;
|
||||
@@ -991,26 +908,14 @@ private:
|
||||
ESystemGlobalState m_systemGlobalState;
|
||||
static const char* GetSystemGlobalStateName(const ESystemGlobalState systemGlobalState);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AzFramework::Terrain::TerrainDataNotificationBus START
|
||||
void OnTerrainDataCreateBegin() override;
|
||||
void OnTerrainDataDestroyBegin() override;
|
||||
// AzFramework::Terrain::TerrainDataNotificationBus END
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
void InitLocalization();
|
||||
void UpdateUpdateTimes();
|
||||
|
||||
protected: // -------------------------------------------------------------
|
||||
|
||||
ILoadingProgressListener* m_pProgressListener;
|
||||
CCmdLine* m_pCmdLine;
|
||||
CThreadManager* m_pThreadManager;
|
||||
CThreadTaskManager* m_pThreadTaskManager;
|
||||
class CResourceManager* m_pResourceManager;
|
||||
ITextModeConsole* m_pTextModeConsole;
|
||||
INotificationNetwork* m_pNotificationNetwork;
|
||||
|
||||
string m_currentLanguageAudio;
|
||||
string m_systemConfigName; // computed from system_(hardwareplatform)_(assetsPlatform) - eg, system_android_es3.cfg or system_android_opengl.cfg or system_windows_pc.cfg
|
||||
|
||||
@@ -35,13 +35,9 @@
|
||||
#define SYSTEMINIT_CPP_SECTION_17 17
|
||||
#endif
|
||||
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
#include "SystemScheduler.h"
|
||||
#endif // defined(MAP_LOADING_SLICING)
|
||||
#include "CryLibrary.h"
|
||||
#include "CryPath.h"
|
||||
#include <StringUtils.h>
|
||||
#include <IThreadManager.h>
|
||||
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
@@ -103,16 +99,12 @@
|
||||
#include "PhysRenderer.h"
|
||||
#include "LocalizedStringManager.h"
|
||||
#include "SystemEventDispatcher.h"
|
||||
#include "ThreadConfigManager.h"
|
||||
#include "Validator.h"
|
||||
#include "ServerThrottle.h"
|
||||
#include "SystemCFG.h"
|
||||
#include "AutoDetectSpec.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "MTSafeAllocator.h"
|
||||
#include "NotificationNetwork.h"
|
||||
#include "ProfileLogSystem.h"
|
||||
#include "SoftCode/SoftCodeMgr.h"
|
||||
#include "ZLibCompressor.h"
|
||||
#include "ZLibDecompressor.h"
|
||||
#include "ZStdDecompressor.h"
|
||||
@@ -146,8 +138,6 @@
|
||||
#include "MobileDetectSpec.h"
|
||||
#endif
|
||||
|
||||
#include "IDebugCallStack.h"
|
||||
|
||||
#include "WindowsConsole.h"
|
||||
|
||||
#if defined(EXTERNAL_CRASH_REPORTING)
|
||||
@@ -163,11 +153,6 @@
|
||||
# include <AzFramework/Network/AssetProcessorConnection.h>
|
||||
#endif
|
||||
|
||||
// if we enable the built-in local version instead of remote:
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
#include "ResourceCompilerHelper.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
extern LONG WINAPI CryEngineExceptionFilterWER(struct _EXCEPTION_POINTERS* pExceptionPointers);
|
||||
#endif
|
||||
@@ -400,26 +385,20 @@ struct SysSpecOverrideSink
|
||||
}
|
||||
else
|
||||
{
|
||||
// This could bypass the restricted/whitelisted cvar checks that exist elsewhere depending on
|
||||
// This could bypass the restricted cvar checks that exist elsewhere depending on
|
||||
// the calling code so we also need check here before setting.
|
||||
bool isConst = pCvar->IsConstCVar();
|
||||
bool isCheat = ((pCvar->GetFlags() & (VF_CHEAT | VF_CHEAT_NOCHECK | VF_CHEAT_ALWAYS_CHECK)) != 0);
|
||||
bool isReadOnly = ((pCvar->GetFlags() & VF_READONLY) != 0);
|
||||
bool isDeprecated = ((pCvar->GetFlags() & VF_DEPRECATED) != 0);
|
||||
bool allowApplyCvar = true;
|
||||
bool whitelisted = true;
|
||||
|
||||
#if defined CVARS_WHITELIST
|
||||
ICVarsWhitelist* cvarWhitelist = gEnv->pSystem->GetCVarsWhiteList();
|
||||
whitelisted = cvarWhitelist ? cvarWhitelist->IsWhiteListed(szKey, true) : true;
|
||||
#endif
|
||||
|
||||
if ((isConst || isCheat || isReadOnly) || isDeprecated)
|
||||
{
|
||||
allowApplyCvar = !isDeprecated && (gEnv->pSystem->IsDevMode()) || (gEnv->IsEditor());
|
||||
}
|
||||
|
||||
if ((allowApplyCvar && whitelisted) || ALLOW_CONST_CVAR_MODIFICATIONS)
|
||||
if ((allowApplyCvar) || ALLOW_CONST_CVAR_MODIFICATIONS)
|
||||
{
|
||||
applyCvar = true;
|
||||
}
|
||||
@@ -1028,7 +1007,6 @@ bool CSystem::InitFileSystem()
|
||||
|
||||
// get the DirectInstance FileIOBase which should be the AZ::LocalFileIO
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetDirectInstance();
|
||||
m_env.pResourceCompilerHelper = nullptr;
|
||||
|
||||
m_env.pCryPak = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
m_env.pFileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
@@ -1107,8 +1085,7 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams&)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
{
|
||||
ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
|
||||
LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
|
||||
LoadConfiguration(m_systemConfigName.c_str());
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Loading system configuration from %s...", m_systemConfigName.c_str());
|
||||
}
|
||||
|
||||
@@ -1118,13 +1095,6 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams&)
|
||||
|
||||
GetISystem()->SetConfigPlatform(GetDevicePlatform());
|
||||
|
||||
#if defined(CRY_ENABLE_RC_HELPER)
|
||||
if (!m_env.pResourceCompilerHelper)
|
||||
{
|
||||
m_env.pResourceCompilerHelper = new CResourceCompilerHelper();
|
||||
}
|
||||
#endif
|
||||
|
||||
auto projectPath = AZ::Utils::GetProjectPath();
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Path: %s\n", projectPath.empty() ? "None specified" : projectPath.c_str());
|
||||
|
||||
@@ -1179,7 +1149,6 @@ bool CSystem::InitAudioSystem(const SSystemInitParams& initParams)
|
||||
|
||||
bool useRealAudioSystem = false;
|
||||
if (!initParams.bPreview
|
||||
&& !initParams.bMinimal
|
||||
&& !m_bDedicatedServer
|
||||
&& m_sys_audio_disable->GetIVal() == 0)
|
||||
{
|
||||
@@ -1672,12 +1641,8 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
gEnv->mMainThreadId = GetCurrentThreadId(); //Set this ASAP on startup
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init start");
|
||||
m_szCmdLine = startupParams.szSystemCmdLine;
|
||||
|
||||
m_env.szCmdLine = m_szCmdLine.c_str();
|
||||
m_env.bTesting = startupParams.bTesting;
|
||||
m_env.bNoAssertDialog = startupParams.bTesting;
|
||||
m_env.bNoRandomSeed = startupParams.bNoRandom;
|
||||
m_env.bNoAssertDialog = false;
|
||||
|
||||
m_bNoCrashDialog = gEnv->IsDedicated();
|
||||
|
||||
@@ -1754,16 +1719,10 @@ AZ_POP_DISABLE_WARNING
|
||||
m_bPreviewMode = startupParams.bPreview;
|
||||
m_bTestMode = startupParams.bTestMode;
|
||||
m_pUserCallback = startupParams.pUserCallback;
|
||||
m_bMinimal = startupParams.bMinimal;
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
m_pCVarsWhitelist = startupParams.pCVarsWhitelist;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
m_bDedicatedServer = startupParams.bDedicatedServer;
|
||||
m_currentLanguageAudio = "";
|
||||
|
||||
memcpy(gEnv->pProtectedFunctions, startupParams.pProtectedFunctions, sizeof(startupParams.pProtectedFunctions));
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
m_env.SetIsEditor(m_bEditor);
|
||||
m_env.SetIsEditorGameMode(false);
|
||||
@@ -1771,7 +1730,6 @@ AZ_POP_DISABLE_WARNING
|
||||
#endif
|
||||
|
||||
m_env.SetToolMode(startupParams.bToolMode);
|
||||
m_env.bIsOutOfMemory = false;
|
||||
|
||||
if (m_bEditor)
|
||||
{
|
||||
@@ -1935,23 +1893,6 @@ AZ_POP_DISABLE_WARNING
|
||||
// so we log this immediately after setting the log filename
|
||||
LogVersion();
|
||||
|
||||
//here we should be good to ask Crypak to do something
|
||||
|
||||
// Initialise after pLog and CPU feature initialization
|
||||
// AND after console creation (Editor only)
|
||||
// May need access to engine folder .pak files
|
||||
gEnv->pThreadManager->GetThreadConfigManager()->LoadConfig("config/engine_core.thread_config");
|
||||
|
||||
if (m_bEditor)
|
||||
{
|
||||
gEnv->pThreadManager->GetThreadConfigManager()->LoadConfig("config/engine_sandbox.thread_config");
|
||||
}
|
||||
|
||||
// Setup main thread
|
||||
void* pThreadHandle = 0; // Let system figure out thread handle
|
||||
gEnv->pThreadManager->RegisterThirdPartyThread(pThreadHandle, "Main");
|
||||
m_env.pProfileLogSystem = new CProfileLogSystem();
|
||||
|
||||
bool devModeEnable = true;
|
||||
|
||||
#if defined(_RELEASE)
|
||||
@@ -1967,22 +1908,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
SetDevMode(devModeEnable);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CREATE NOTIFICATION NETWORK
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
m_pNotificationNetwork = nullptr;
|
||||
#ifndef _RELEASE
|
||||
#ifndef LINUX
|
||||
|
||||
if (!startupParams.bMinimal)
|
||||
{
|
||||
m_pNotificationNetwork = CNotificationNetwork::Create();
|
||||
}
|
||||
#endif//LINUX
|
||||
#endif // _RELEASE
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init NotificationNetwork");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CREATE CONSOLE
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -2051,8 +1976,6 @@ AZ_POP_DISABLE_WARNING
|
||||
// CPU features detection.
|
||||
m_pCpu = new CCpuFeatures;
|
||||
m_pCpu->Detect();
|
||||
m_env.pi.numCoresAvailableToProcess = m_pCpu->GetCPUCount();
|
||||
m_env.pi.numLogicalProcessors = m_pCpu->GetLogicalCPUCount();
|
||||
|
||||
// Check hard minimum CPU requirements
|
||||
if (!CheckCPURequirements(m_pCpu, this))
|
||||
@@ -2102,17 +2025,15 @@ AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
|
||||
{
|
||||
ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetCVarsWhiteListConfigSink();
|
||||
|
||||
// We have to load this file again since first time we did it without devmode
|
||||
LoadConfiguration(m_systemConfigName.c_str(), pCVarsWhiteListConfigSink);
|
||||
LoadConfiguration(m_systemConfigName.c_str());
|
||||
// Optional user defined overrides
|
||||
LoadConfiguration("user.cfg", pCVarsWhiteListConfigSink);
|
||||
LoadConfiguration("user.cfg");
|
||||
|
||||
#if defined(ENABLE_STATS_AGENT)
|
||||
if (m_pCmdLine->FindArg(eCLAT_Pre, "useamblecfg"))
|
||||
{
|
||||
LoadConfiguration("amble.cfg", pCVarsWhiteListConfigSink);
|
||||
LoadConfiguration("amble.cfg");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -2159,7 +2080,7 @@ AZ_POP_DISABLE_WARNING
|
||||
InlineInitializationProcessing("CSystem::Init LoadConfigurations");
|
||||
|
||||
#ifdef WIN32
|
||||
if ((g_cvars.sys_WER) && (!startupParams.bMinimal))
|
||||
if ((g_cvars.sys_WER))
|
||||
{
|
||||
SetUnhandledExceptionFilter(CryEngineExceptionFilterWER);
|
||||
}
|
||||
@@ -2169,7 +2090,6 @@ AZ_POP_DISABLE_WARNING
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Localization
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (!startupParams.bMinimal)
|
||||
{
|
||||
InitLocalization();
|
||||
}
|
||||
@@ -2187,7 +2107,6 @@ AZ_POP_DISABLE_WARNING
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AUDIO
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (!startupParams.bMinimal)
|
||||
{
|
||||
if (InitAudioSystem(startupParams))
|
||||
{
|
||||
@@ -2210,12 +2129,6 @@ AZ_POP_DISABLE_WARNING
|
||||
m_pUserCallback->OnInitProgress("First time asset processing - may take a minute...");
|
||||
}
|
||||
|
||||
#ifdef SOFTCODE_SYSTEM_ENABLED
|
||||
m_env.pSoftCodeMgr = new SoftCodeMgr();
|
||||
#else
|
||||
m_env.pSoftCodeMgr = nullptr;
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// System cursor
|
||||
@@ -2225,8 +2138,7 @@ AZ_POP_DISABLE_WARNING
|
||||
// - System cursor has to be enabled manually by the Game if needed; the custom UiCursor will typically be used instead
|
||||
|
||||
if (!gEnv->IsDedicated() &&
|
||||
!gEnv->IsEditor() &&
|
||||
!startupParams.bTesting)
|
||||
!gEnv->IsEditor())
|
||||
{
|
||||
AzFramework::InputSystemCursorRequestBus::Event(AzFramework::InputDeviceMouse::Id,
|
||||
&AzFramework::InputSystemCursorRequests::SetSystemCursorState,
|
||||
@@ -2322,27 +2234,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init ZStdDecompressor");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Initialize task threads.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
m_pThreadTaskManager->InitThreads();
|
||||
|
||||
SetAffinity();
|
||||
AZ_Assert(CryMemory::IsHeapValid(), "CryMemory heap must be valid before initializing VTune.");
|
||||
|
||||
|
||||
if (strstr(startupParams.szSystemCmdLine, "-VTUNE") != 0 || g_cvars.sys_vtune != 0)
|
||||
{
|
||||
if (!InitVTuneProfiler())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init InitTaskThreads");
|
||||
|
||||
if (m_env.pLyShine)
|
||||
{
|
||||
m_env.pLyShine->PostInit();
|
||||
@@ -2366,8 +2257,6 @@ AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
}
|
||||
EnableFloatExceptions(g_cvars.sys_float_exceptions);
|
||||
|
||||
MarkThisThreadForDebugging("Main");
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init End");
|
||||
@@ -2422,8 +2311,7 @@ static void LoadConfigurationCmd(IConsoleCmdArgs* pParams)
|
||||
return;
|
||||
}
|
||||
|
||||
ILoadConfigurationEntrySink* pCVarsWhiteListConfigSink = GetISystem()->GetCVarsWhiteListConfigSink();
|
||||
GetISystem()->LoadConfiguration(string("Config/") + pParams->GetArg(1), pCVarsWhiteListConfigSink);
|
||||
GetISystem()->LoadConfiguration(string("Config/") + pParams->GetArg(1));
|
||||
}
|
||||
|
||||
|
||||
@@ -2648,20 +2536,6 @@ void CmdDrillToFile(IConsoleCmdArgs* pArgs)
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeLogAllocations(ICVar* pVal)
|
||||
{
|
||||
g_iTraceAllocations = pVal->GetIVal();
|
||||
|
||||
if (g_iTraceAllocations == 2)
|
||||
{
|
||||
IDebugCallStack::instance()->StartMemLog();
|
||||
}
|
||||
else
|
||||
{
|
||||
IDebugCallStack::instance()->StopMemLog();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::CreateSystemVars()
|
||||
{
|
||||
@@ -2719,9 +2593,6 @@ void CSystem::CreateSystemVars()
|
||||
|
||||
m_cvAIUpdate = REGISTER_INT("ai_NoUpdate", 0, VF_CHEAT, "Disables AI system update when 1");
|
||||
|
||||
m_iTraceAllocations = g_iTraceAllocations;
|
||||
REGISTER_CVAR2_CB("sys_logallocations", &m_iTraceAllocations, m_iTraceAllocations, VF_DUMPTODISK, "Save allocation call stack", ChangeLogAllocations);
|
||||
|
||||
m_cvMemStats = REGISTER_INT("MemStats", 0, 0,
|
||||
"0/x=refresh rate in milliseconds\n"
|
||||
"Use 1000 to switch on and 0 to switch off\n"
|
||||
@@ -2860,16 +2731,6 @@ void CSystem::CreateSystemVars()
|
||||
m_sys_TaskThread_CPU[5] = REGISTER_INT("sys_TaskThread5_CPU", 1, 0,
|
||||
"Specifies the physical CPU index taskthread5 will run on");
|
||||
|
||||
//if physics thread is excluded all locks inside are mapped to NO_LOCK
|
||||
//var must be not visible to accidentally get enabled
|
||||
#if defined(EXCLUDE_PHYSICS_THREAD)
|
||||
m_sys_physics_CPU = REGISTER_INT("sys_physics_CPU_disabled", 0, 0,
|
||||
"Specifies the physical CPU index physics will run on");
|
||||
#else
|
||||
m_sys_physics_CPU = REGISTER_INT("sys_physics_CPU", 1, 0,
|
||||
"Specifies the physical CPU index physics will run on");
|
||||
#endif
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_12
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
@@ -3033,7 +2894,6 @@ void CSystem::CreateSystemVars()
|
||||
"0=off / 1=enabled");
|
||||
*/
|
||||
REGISTER_CVAR2("sys_AI", &g_cvars.sys_ai, 1, 0, "Enables AI Update");
|
||||
REGISTER_CVAR2("sys_physics", &g_cvars.sys_physics, 1, 0, "Enables Physics Update");
|
||||
REGISTER_CVAR2("sys_entities", &g_cvars.sys_entitysystem, 1, 0, "Enables Entities Update");
|
||||
REGISTER_CVAR2("sys_trackview", &g_cvars.sys_trackview, 1, 0, "Enables TrackView Update");
|
||||
|
||||
@@ -3068,10 +2928,6 @@ void CSystem::CreateSystemVars()
|
||||
|
||||
REGISTER_STRING("dlc_directory", "", 0, "Holds the path to the directory where DLC should be installed to and read from");
|
||||
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
CreateSystemScheduler(this);
|
||||
#endif // defined(MAP_LOADING_SLICING)
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
REGISTER_INT("sys_screensaver_allowed", 0, VF_NULL, "Specifies if screen saver is allowed to start up while the game is running.");
|
||||
#endif
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
#include <ILevelSystem.h>
|
||||
#include <LyShine/ILyShine.h>
|
||||
|
||||
#include "ThreadInfo.h"
|
||||
|
||||
#include <LoadScreenBus.h>
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
@@ -90,52 +88,6 @@ void CSystem::OnScene3DEnd()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Update screen and call some important tick functions during loading.
|
||||
void CSystem::SynchronousLoadingTick([[maybe_unused]] const char* pFunc, [[maybe_unused]] int line)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
if (gEnv && gEnv->bMultiplayer && !gEnv->IsEditor())
|
||||
{
|
||||
//UpdateLoadingScreen currently contains a couple of tick functions that need to be called regularly during the synchronous level loading,
|
||||
//when the usual engine and game ticks are suspended.
|
||||
UpdateLoadingScreen();
|
||||
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
GetISystemScheduler()->SliceAndSleep(pFunc, line);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::UpdateLoadingScreen()
|
||||
{
|
||||
// Do not update the network thread from here - it will cause context corruption - use the NetworkStallTicker thread system
|
||||
|
||||
if (GetCurrentThreadId() != gEnv->mMainThreadId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMRENDERER_CPP_SECTION_2
|
||||
#include AZ_RESTRICTED_FILE(SystemRender_cpp)
|
||||
#endif
|
||||
|
||||
#if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
EBUS_EVENT(LoadScreenBus, UpdateAndRender);
|
||||
#endif // if AZ_LOADSCREENCOMPONENT_ENABLED
|
||||
|
||||
if (!m_bEditor && !IsQuitting())
|
||||
{
|
||||
if (m_pProgressListener)
|
||||
{
|
||||
m_pProgressListener->OnLoadingProgress(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CSystem::DisplayErrorMessage(const char* acMessage,
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
// Description : Implementation of the CSystemScheduler class
|
||||
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
|
||||
#include "ProjectDefines.h"
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
|
||||
#include "SystemScheduler.h"
|
||||
|
||||
#include "MiniQueue.h"
|
||||
#include "ClientHandler.h"
|
||||
#include "ServerHandler.h"
|
||||
|
||||
void CreateSystemScheduler(CSystem* pSystem)
|
||||
{
|
||||
gEnv->pSystemScheduler = new CSystemScheduler(pSystem);
|
||||
}
|
||||
|
||||
CSystemScheduler::CSystemScheduler(CSystem* pSystem)
|
||||
: m_pSystem(pSystem)
|
||||
, m_lastSliceCheckTime(0.0f)
|
||||
, m_sliceLoadingRef(0)
|
||||
{
|
||||
int defaultSchedulingMode = 0;
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
defaultSchedulingMode = 2;
|
||||
}
|
||||
|
||||
m_svSchedulingMode = REGISTER_INT("sv_scheduling", defaultSchedulingMode, 0, "Scheduling mode\n"
|
||||
" 0: Normal mode\n"
|
||||
" 1: Client\n"
|
||||
" 2: Server\n");
|
||||
|
||||
m_svSchedulingBucket = REGISTER_INT("sv_schedulingBucket", 0, 0, "Scheduling bucket\n");
|
||||
|
||||
m_svSchedulingAffinity = REGISTER_INT("sv_SchedulingAffinity", 0, 0, "Scheduling affinity\n");
|
||||
|
||||
m_svSchedulingClientTimeout = REGISTER_INT("sv_schedulingClientTimeout", 1000, 0, "Client wait server\n");
|
||||
m_svSchedulingServerTimeout = REGISTER_INT("sv_schedulingServerTimeout", 100, 0, "Server wait server\n");
|
||||
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
m_svSliceLoadEnable = REGISTER_INT("sv_sliceLoadEnable", 1, 0, "Enable/disable slice loading logic\n");
|
||||
;
|
||||
m_svSliceLoadBudget = REGISTER_INT("sv_sliceLoadBudget", 10, 0, "Slice budget\n");
|
||||
;
|
||||
m_svSliceLoadLogging = REGISTER_INT("sv_sliceLoadLogging", 0, 0, "Enable/disable slice loading logging\n");
|
||||
#endif
|
||||
|
||||
m_pLastSliceName = "INACTIVE";
|
||||
m_lastSliceLine = 0;
|
||||
}
|
||||
|
||||
CSystemScheduler::~CSystemScheduler(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CSystemScheduler::SliceLoadingBegin()
|
||||
{
|
||||
m_lastSliceCheckTime = gEnv->pTimer->GetAsyncTime();
|
||||
m_sliceLoadingRef++;
|
||||
m_pLastSliceName = "START";
|
||||
m_lastSliceLine = 0;
|
||||
}
|
||||
|
||||
void CSystemScheduler::SliceLoadingEnd()
|
||||
{
|
||||
m_sliceLoadingRef--;
|
||||
m_pLastSliceName = "INACTIVE";
|
||||
m_lastSliceLine = 0;
|
||||
}
|
||||
|
||||
void CSystemScheduler::SliceAndSleep(const char* sliceName, int line)
|
||||
{
|
||||
#if defined(MAP_LOADING_SLICING)
|
||||
if (!gEnv->IsDedicated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sliceLoadingRef)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_svSliceLoadEnable->GetIVal())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SchedulingModeUpdate();
|
||||
|
||||
CTimeValue currTime = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
float sliceBudget = CLAMP(m_svSliceLoadBudget->GetFVal(), 0, 1000.0f / m_pSystem->GetDedicatedMaxRate()->GetFVal());
|
||||
bool doSleep = true;
|
||||
if ((currTime - m_pSystem->GetLastTickTime()).GetMilliSeconds() < sliceBudget)
|
||||
{
|
||||
m_lastSliceCheckTime = currTime;
|
||||
doSleep = false;
|
||||
}
|
||||
|
||||
if (doSleep)
|
||||
{
|
||||
if (m_svSliceLoadLogging->GetIVal())
|
||||
{
|
||||
float diff = (currTime - m_lastSliceCheckTime).GetMilliSeconds();
|
||||
if (diff > sliceBudget)
|
||||
{
|
||||
CryLogAlways("[SliceAndSleep]: Interval between slice [%s:%i] and [%s:%i] was [%f] out of budget [%f]", m_pLastSliceName, m_lastSliceLine, sliceName, line, diff, sliceBudget);
|
||||
}
|
||||
}
|
||||
|
||||
m_pSystem->SleepIfNeeded();
|
||||
}
|
||||
|
||||
m_pLastSliceName = sliceName;
|
||||
m_lastSliceLine = line;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSystemScheduler::SchedulingSleepIfNeeded()
|
||||
{
|
||||
if (!gEnv->IsDedicated())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SchedulingModeUpdate();
|
||||
m_pSystem->SleepIfNeeded();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Scheduling mode routines
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Scheduling mode update logic
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CSystemScheduler::SchedulingModeUpdate()
|
||||
{
|
||||
static std::unique_ptr<ClientHandler> m_client;
|
||||
static std::unique_ptr<ServerHandler> m_server;
|
||||
|
||||
if (int scheduling = m_svSchedulingMode->GetIVal())
|
||||
{
|
||||
if (scheduling == 1) //client
|
||||
{
|
||||
if (!m_client.get())
|
||||
{
|
||||
m_server.reset();
|
||||
m_client.reset(new ClientHandler(m_svSchedulingBucket->GetString(), m_svSchedulingAffinity->GetIVal(), m_svSchedulingClientTimeout->GetIVal()));
|
||||
}
|
||||
if (m_client->Sync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (scheduling == 2) //server
|
||||
{
|
||||
if (!m_server.get())
|
||||
{
|
||||
m_client.reset();
|
||||
m_server.reset(new ServerHandler(m_svSchedulingBucket->GetString(), m_svSchedulingAffinity->GetIVal(), m_svSchedulingServerTimeout->GetIVal()));
|
||||
}
|
||||
if (m_server->Sync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client.reset();
|
||||
m_server.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(MAP_LOADING_SLICING)
|
||||
|
||||
extern "C" void SliceAndSleep(const char* pFunc, int line)
|
||||
{
|
||||
if (GetISystemScheduler())
|
||||
{
|
||||
GetISystemScheduler()->SliceAndSleep(pFunc, line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_SYSTEMSCHEDULER_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_SYSTEMSCHEDULER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "System.h"
|
||||
#include <ISystemScheduler.h>
|
||||
|
||||
class CSystemScheduler
|
||||
: public ISystemScheduler
|
||||
{
|
||||
public:
|
||||
CSystemScheduler(CSystem* pSystem);
|
||||
virtual ~CSystemScheduler(void);
|
||||
|
||||
// ISystemScheduler
|
||||
virtual void SliceAndSleep(const char* sliceName, int line);
|
||||
virtual void SliceLoadingBegin();
|
||||
virtual void SliceLoadingEnd();
|
||||
|
||||
virtual void SchedulingSleepIfNeeded(void);
|
||||
// ~ISystemScheduler
|
||||
|
||||
protected:
|
||||
void SchedulingModeUpdate(void);
|
||||
|
||||
private:
|
||||
CSystem* m_pSystem;
|
||||
ICVar* m_svSchedulingAffinity;
|
||||
ICVar* m_svSchedulingClientTimeout;
|
||||
ICVar* m_svSchedulingServerTimeout;
|
||||
ICVar* m_svSchedulingBucket;
|
||||
ICVar* m_svSchedulingMode;
|
||||
ICVar* m_svSliceLoadEnable;
|
||||
ICVar* m_svSliceLoadBudget;
|
||||
ICVar* m_svSliceLoadLogging;
|
||||
|
||||
CTimeValue m_lastSliceCheckTime;
|
||||
|
||||
int m_sliceLoadingRef;
|
||||
|
||||
const char* m_pLastSliceName;
|
||||
int m_lastSliceLine;
|
||||
};
|
||||
|
||||
// Summary:
|
||||
// Creates the system scheduler interface.
|
||||
void CreateSystemScheduler(CSystem* pSystem);
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_SYSTEMSCHEDULER_H
|
||||
@@ -1,697 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "System.h"
|
||||
#include "ThreadConfigManager.h"
|
||||
#include "IThreadManager.h"
|
||||
#include <CryCustomTypes.h>
|
||||
#include "CryUtils.h"
|
||||
|
||||
#define INCLUDED_FROM_SYSTEM_THREADING_CPP
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
#define SYSTEMTHREADING_CPP_SECTION_1 1
|
||||
#define SYSTEMTHREADING_CPP_SECTION_2 2
|
||||
#define SYSTEMTHREADING_CPP_SECTION_3 3
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#include "CryThreadUtil_win32_thread.h"
|
||||
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMTHREADING_CPP_SECTION_1
|
||||
#include AZ_RESTRICTED_FILE(SystemThreading_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
#include "CryThreadUtil_pthread.h"
|
||||
#endif
|
||||
#undef INCLUDED_FROM_SYSTEM_THREADING_CPP
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void ApplyThreadConfig(CryThreadUtil::TThreadHandle pThreadHandle, const SThreadConfig& rThreadDesc)
|
||||
{
|
||||
// Apply config
|
||||
if (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_ThreadName)
|
||||
{
|
||||
CryThreadUtil::CrySetThreadName(pThreadHandle, rThreadDesc.szThreadName);
|
||||
}
|
||||
if (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_Affinity)
|
||||
{
|
||||
CryThreadUtil::CrySetThreadAffinityMask(pThreadHandle, rThreadDesc.affinityFlag);
|
||||
}
|
||||
if (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_Priority)
|
||||
{
|
||||
CryThreadUtil::CrySetThreadPriority(pThreadHandle, rThreadDesc.priority);
|
||||
}
|
||||
if (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_PriorityBoost)
|
||||
{
|
||||
CryThreadUtil::CrySetThreadPriorityBoost(pThreadHandle, !rThreadDesc.bDisablePriorityBoost);
|
||||
}
|
||||
|
||||
CryComment("<ThreadInfo> Configured thread \"%s\" %s | AffinityMask: %u %s | Priority: %i %s | PriorityBoost: %s %s",
|
||||
rThreadDesc.szThreadName, (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_ThreadName) ? "" : "(ignored)",
|
||||
rThreadDesc.affinityFlag, (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_Affinity) ? "" : "(ignored)",
|
||||
rThreadDesc.priority, (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_Priority) ? "" : "(ignored)",
|
||||
!rThreadDesc.bDisablePriorityBoost ? "enabled" : "disabled", (rThreadDesc.paramActivityFlag & SThreadConfig::eThreadParamFlag_PriorityBoost) ? "" : "(ignored)");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SThreadMetaData
|
||||
: public CMultiThreadRefCount
|
||||
{
|
||||
SThreadMetaData()
|
||||
: m_pThreadTask(0)
|
||||
, m_threadHandle(0)
|
||||
, m_threadId(0)
|
||||
, m_threadName("Cry_UnnamedThread")
|
||||
, m_isRunning(false)
|
||||
{
|
||||
}
|
||||
|
||||
IThread* m_pThreadTask; // Pointer to thread task to be executed
|
||||
CThreadManager* m_pThreadMngr; // Pointer to thread manager
|
||||
|
||||
CryThreadUtil::TThreadHandle m_threadHandle; // Thread handle
|
||||
threadID m_threadId; // The active threadId, 0 = Invalid Id
|
||||
|
||||
CryMutex m_threadExitMutex; // Mutex used to safeguard thread exit condition signaling
|
||||
CryConditionVariable m_threadExitCondition; // Signaled when the thread is about to exit
|
||||
|
||||
CryFixedStringT<THREAD_NAME_LENGTH_MAX> m_threadName; // Thread name
|
||||
volatile bool m_isRunning; // Indicates the thread is not ready to exit yet
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CThreadManager
|
||||
: public IThreadManager
|
||||
{
|
||||
public:
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~CThreadManager()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool SpawnThread(IThread* pThread, const char* sThreadName, ...) override;
|
||||
virtual bool JoinThread(IThread* pThreadTask, EJoinMode eJoinMode) override;
|
||||
|
||||
virtual bool RegisterThirdPartyThread(void* pThreadHandle, const char* sThreadName, ...) override;
|
||||
virtual bool UnRegisterThirdPartyThread(const char* sThreadName, ...) override;
|
||||
|
||||
virtual const char* GetThreadName(threadID nThreadId) override;
|
||||
virtual threadID GetThreadId(const char* sThreadName, ...) override;
|
||||
|
||||
virtual void ForEachOtherThread(IThreadManager::ThreadModifFunction fpThreadModiFunction, void* pFuncData = 0) override;
|
||||
|
||||
virtual void EnableFloatExceptions(EFPE_Severity eFPESeverity, threadID nThreadId = 0) override;
|
||||
virtual void EnableFloatExceptionsForEachOtherThread(EFPE_Severity eFPESeverity) override;
|
||||
|
||||
virtual uint GetFloatingPointExceptionMask() override;
|
||||
virtual void SetFloatingPointExceptionMask(uint nMask) override;
|
||||
|
||||
IThreadConfigManager* GetThreadConfigManager() override
|
||||
{
|
||||
return &m_threadConfigManager;
|
||||
}
|
||||
// </interfuscator:shuffle>
|
||||
private:
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
static unsigned __stdcall RunThread(void* thisPtr);
|
||||
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMTHREADING_CPP_SECTION_2
|
||||
#include AZ_RESTRICTED_FILE(SystemThreading_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
static void* RunThread(void* thisPtr);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool UnregisterThread(IThread* pThreadTask);
|
||||
|
||||
bool SpawnThreadImpl(IThread* pThread, const char* sThreadName);
|
||||
|
||||
bool RegisterThirdPartyThreadImpl(CryThreadUtil::TThreadHandle pThreadHandle, const char* sThreadName);
|
||||
bool UnRegisterThirdPartyThreadImpl(const char* sThreadName);
|
||||
|
||||
threadID GetThreadIdImpl(const char* sThreadName);
|
||||
|
||||
private:
|
||||
// Note: Guard SThreadMetaData with a _smart_ptr and lock to ensure that a thread waiting to be signaled by another still
|
||||
// has access to valid SThreadMetaData even though the other thread terminated and as a result unregistered itself from the CThreadManager.
|
||||
// An example would be the join method. Where one thread waits on a signal from an other thread to terminate and release its SThreadMetaData,
|
||||
// sharing the same SThreadMetaData condition variable.
|
||||
typedef std::map<IThread*, _smart_ptr<SThreadMetaData> > SpawnedThreadMap;
|
||||
typedef std::map<IThread*, _smart_ptr<SThreadMetaData> >::iterator SpawnedThreadMapIter;
|
||||
typedef std::map<IThread*, _smart_ptr<SThreadMetaData> >::const_iterator SpawnedThreadMapConstIter;
|
||||
typedef std::pair<IThread*, _smart_ptr<SThreadMetaData> > ThreadMapPair;
|
||||
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, _smart_ptr<SThreadMetaData> > SpawnedThirdPartyThreadMap;
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, _smart_ptr<SThreadMetaData> >::iterator SpawnedThirdPartyThreadMapIter;
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, _smart_ptr<SThreadMetaData> >::const_iterator SpawnedThirdPartyThreadMapConstIter;
|
||||
typedef std::pair<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, _smart_ptr<SThreadMetaData> > ThirdPartyThreadMapPair;
|
||||
|
||||
CryCriticalSection m_spawnedThreadsLock; // Use lock for the rare occasion a thread is created/destroyed
|
||||
SpawnedThreadMap m_spawnedThreads; // Holds information of all spawned threads (through this system)
|
||||
|
||||
CryCriticalSection m_spawnedThirdPartyThreadsLock; // Use lock for the rare occasion a thread is created/destroyed
|
||||
SpawnedThirdPartyThreadMap m_spawnedThirdPartyThread; // Holds information of all registered 3rd party threads (through this system)
|
||||
|
||||
CThreadConfigManager m_threadConfigManager;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
unsigned __stdcall CThreadManager::RunThread(void* thisPtr)
|
||||
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMTHREADING_CPP_SECTION_3
|
||||
#include AZ_RESTRICTED_FILE(SystemThreading_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
void* CThreadManager::RunThread(void* thisPtr)
|
||||
#endif
|
||||
{
|
||||
// Check that we are not spawning a thread before gEnv->pSystem has been set
|
||||
// Otherwise we cannot enable floating point exceptions
|
||||
if (!gEnv || !gEnv->pSystem)
|
||||
{
|
||||
CryFatalError("[Error]: CThreadManager::RunThread requires gEnv->pSystem to be initialized.");
|
||||
}
|
||||
|
||||
IThreadConfigManager* pThreadConfigMngr = gEnv->pThreadManager->GetThreadConfigManager();
|
||||
|
||||
SThreadMetaData* pThreadData = reinterpret_cast<SThreadMetaData*>(thisPtr);
|
||||
pThreadData->m_threadId = CryThreadUtil::CryGetCurrentThreadId();
|
||||
|
||||
// Apply config
|
||||
const SThreadConfig* pThreadConfig = pThreadConfigMngr->GetThreadConfig(pThreadData->m_threadName.c_str());
|
||||
ApplyThreadConfig(pThreadData->m_threadHandle, *pThreadConfig);
|
||||
|
||||
// Config not found, append thread name with no config tag
|
||||
if (pThreadConfig == pThreadConfigMngr->GetDefaultThreadConfig())
|
||||
{
|
||||
CryFixedStringT<THREAD_NAME_LENGTH_MAX> tmpString(pThreadData->m_threadName);
|
||||
const char* cNoConfigAppendix = "(NoCfgFound)";
|
||||
int nNumCharsToReplace = strlen(cNoConfigAppendix);
|
||||
|
||||
// Replace thread name ending
|
||||
if (pThreadData->m_threadName.size() > THREAD_NAME_LENGTH_MAX - nNumCharsToReplace)
|
||||
{
|
||||
tmpString.replace(THREAD_NAME_LENGTH_MAX - nNumCharsToReplace, nNumCharsToReplace, cNoConfigAppendix, nNumCharsToReplace);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpString.append(cNoConfigAppendix);
|
||||
}
|
||||
|
||||
// Print to log
|
||||
if (pThreadConfigMngr->ConfigLoaded())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> No Thread config found for thread %s using ... default config.", pThreadData->m_threadName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo> Thread config not loaded yet. Hence no thread config was found for thread %s ... using default config.", pThreadData->m_threadName.c_str());
|
||||
}
|
||||
|
||||
// Rename Thread
|
||||
CryThreadUtil::CrySetThreadName(pThreadData->m_threadHandle, tmpString.c_str());
|
||||
}
|
||||
|
||||
// Enable FPEs
|
||||
gEnv->pThreadManager->EnableFloatExceptions((EFPE_Severity)g_cvars.sys_float_exceptions);
|
||||
|
||||
// Execute thread code
|
||||
pThreadData->m_pThreadTask->ThreadEntry();
|
||||
|
||||
// Disable FPEs
|
||||
gEnv->pThreadManager->EnableFloatExceptions(eFPE_None);
|
||||
|
||||
// Signal imminent thread end
|
||||
pThreadData->m_threadExitMutex.Lock();
|
||||
pThreadData->m_isRunning = false;
|
||||
pThreadData->m_threadExitCondition.Notify();
|
||||
pThreadData->m_threadExitMutex.Unlock();
|
||||
|
||||
// Unregister thread
|
||||
// Note: Unregister after m_threadExitCondition.Notify() to ensure pThreadData is still valid
|
||||
pThreadData->m_pThreadMngr->UnregisterThread(pThreadData->m_pThreadTask);
|
||||
|
||||
CryThreadUtil::CryThreadExitCall();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::JoinThread(IThread* pThreadTask, EJoinMode eJoinMode)
|
||||
{
|
||||
// Get thread object
|
||||
_smart_ptr<SThreadMetaData> pThreadImpl = 0;
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
|
||||
SpawnedThreadMapIter res = m_spawnedThreads.find(pThreadTask);
|
||||
if (res == m_spawnedThreads.end())
|
||||
{
|
||||
// Thread has already finished and unregistered itself.
|
||||
// As it is complete we cannot wait for it.
|
||||
// Hence return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
pThreadImpl = res->second; // Keep object alive
|
||||
}
|
||||
|
||||
// On try join, exit if the thread is not in a state to exit
|
||||
if (eJoinMode == eJM_TryJoin && pThreadImpl->m_isRunning)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait for completion of the target thread exit condition
|
||||
pThreadImpl->m_threadExitMutex.Lock();
|
||||
while (pThreadImpl->m_isRunning)
|
||||
{
|
||||
pThreadImpl->m_threadExitCondition.Wait(pThreadImpl->m_threadExitMutex);
|
||||
}
|
||||
pThreadImpl->m_threadExitMutex.Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::UnregisterThread(IThread* pThreadTask)
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
|
||||
SpawnedThreadMapIter res = m_spawnedThreads.find(pThreadTask);
|
||||
if (res == m_spawnedThreads.end())
|
||||
{
|
||||
// Duplicate thread deletion
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: UnregisterThread: Unable to unregister thread. Thread name could not be found. Double deletion? IThread pointer: %p", pThreadTask);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_spawnedThreads.erase(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* CThreadManager::GetThreadName(threadID nThreadId)
|
||||
{
|
||||
// Loop over internally spawned threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
|
||||
SpawnedThreadMapConstIter iter = m_spawnedThreads.begin();
|
||||
SpawnedThreadMapConstIter iterEnd = m_spawnedThreads.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadId == nThreadId)
|
||||
{
|
||||
return iter->second->m_threadName.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over third party threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThirdPartyThreadsLock);
|
||||
|
||||
SpawnedThirdPartyThreadMapConstIter iter = m_spawnedThirdPartyThread.begin();
|
||||
SpawnedThirdPartyThreadMapConstIter iterEnd = m_spawnedThirdPartyThread.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadId == nThreadId)
|
||||
{
|
||||
return iter->second->m_threadName.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadManager::ForEachOtherThread(IThreadManager::ThreadModifFunction fpThreadModiFunction, void* pFuncData)
|
||||
{
|
||||
threadID nCurThreadId = CryThreadUtil::CryGetCurrentThreadId();
|
||||
|
||||
// Loop over internally spawned threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
|
||||
SpawnedThreadMapConstIter iter = m_spawnedThreads.begin();
|
||||
SpawnedThreadMapConstIter iterEnd = m_spawnedThreads.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadId != nCurThreadId)
|
||||
{
|
||||
fpThreadModiFunction(iter->second->m_threadId, pFuncData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over third party threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThirdPartyThreadsLock);
|
||||
|
||||
SpawnedThirdPartyThreadMapConstIter iter = m_spawnedThirdPartyThread.begin();
|
||||
SpawnedThirdPartyThreadMapConstIter iterEnd = m_spawnedThirdPartyThread.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadId != nCurThreadId)
|
||||
{
|
||||
fpThreadModiFunction(iter->second->m_threadId, pFuncData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::SpawnThread(IThread* pThreadTask, const char* sThreadName, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, sThreadName);
|
||||
|
||||
// Format thread name
|
||||
char strThreadName[THREAD_NAME_LENGTH_MAX];
|
||||
const int cNumCharsNeeded = azvsnprintf(strThreadName, CRY_ARRAY_COUNT(strThreadName), sThreadName, args);
|
||||
if (cNumCharsNeeded > THREAD_NAME_LENGTH_MAX - 1 || cNumCharsNeeded < 0)
|
||||
{
|
||||
strThreadName[THREAD_NAME_LENGTH_MAX - 1] = '\0'; // The WinApi only null terminates if strLen < bufSize
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: ThreadName \"%s\" has been truncated. Max characters allowed: %i. ", strThreadName, THREAD_NAME_LENGTH_MAX - 1);
|
||||
}
|
||||
|
||||
// Spawn thread
|
||||
bool ret = SpawnThreadImpl(pThreadTask, strThreadName);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: CSystem::SpawnThread error spawning thread: \"%s\" ", strThreadName);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::SpawnThreadImpl(IThread* pThreadTask, const char* sThreadName)
|
||||
{
|
||||
if (pThreadTask == NULL)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, "<ThreadInfo>: SpawnThread '%s' ThreadTask is NULL : ignoring", sThreadName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init thread meta data
|
||||
SThreadMetaData* pThreadMetaData = new SThreadMetaData();
|
||||
pThreadMetaData->m_pThreadTask = pThreadTask;
|
||||
pThreadMetaData->m_pThreadMngr = this;
|
||||
pThreadMetaData->m_threadName = sThreadName;
|
||||
|
||||
// Add thread to map
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
SpawnedThreadMapIter res = m_spawnedThreads.find(pThreadTask);
|
||||
if (res != m_spawnedThreads.end())
|
||||
{
|
||||
// Thread with same name already spawned
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: SpawnThread: Thread \"%s\" already exists.", sThreadName);
|
||||
delete pThreadMetaData;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert thread data
|
||||
m_spawnedThreads.insert(ThreadMapPair(pThreadTask, pThreadMetaData));
|
||||
}
|
||||
|
||||
// Load config if we can and if no config has been defined to be loaded
|
||||
const SThreadConfig* pThreadConfig = gEnv->pThreadManager->GetThreadConfigManager()->GetThreadConfig(sThreadName);
|
||||
|
||||
// Create thread description
|
||||
CryThreadUtil::SThreadCreationDesc desc = {sThreadName, RunThread, pThreadMetaData, pThreadConfig->paramActivityFlag & SThreadConfig::eThreadParamFlag_StackSize ? pThreadConfig->stackSizeBytes : 0};
|
||||
|
||||
// Spawn new thread
|
||||
pThreadMetaData->m_isRunning = CryThreadUtil::CryCreateThread(&(pThreadMetaData->m_threadHandle), desc);
|
||||
|
||||
// Validate thread creation
|
||||
if (!pThreadMetaData->m_isRunning)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: SpawnThread: Could not spawn thread \"%s\" .", sThreadName);
|
||||
|
||||
// Remove thread from map (also releases SThreadMetaData _smart_ptr)
|
||||
m_spawnedThreads.erase(m_spawnedThreads.find(pThreadTask));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::RegisterThirdPartyThread(void* pThreadHandle, const char* sThreadName, ...)
|
||||
{
|
||||
if (!pThreadHandle)
|
||||
{
|
||||
pThreadHandle = reinterpret_cast<void*>(CryThreadUtil::CryGetCurrentThreadHandle());
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, sThreadName);
|
||||
|
||||
// Format thread name
|
||||
char strThreadName[THREAD_NAME_LENGTH_MAX];
|
||||
const int cNumCharsNeeded = azvsnprintf(strThreadName, CRY_ARRAY_COUNT(strThreadName), sThreadName, args);
|
||||
if (cNumCharsNeeded > THREAD_NAME_LENGTH_MAX - 1)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: ThreadName \"%s\" has been truncated. Max characters allowed: %i. ", strThreadName, THREAD_NAME_LENGTH_MAX - 1);
|
||||
}
|
||||
|
||||
// Register 3rd party thread
|
||||
bool ret = RegisterThirdPartyThreadImpl(reinterpret_cast<CryThreadUtil::TThreadHandle>(pThreadHandle), strThreadName);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::RegisterThirdPartyThreadImpl(CryThreadUtil::TThreadHandle threadHandle, const char* sThreadName)
|
||||
{
|
||||
if (strcmp(sThreadName, "") == 0)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: CThreadManager::RegisterThirdPartyThread error registering third party thread. No name provided.");
|
||||
return false;
|
||||
}
|
||||
// Init thread meta data
|
||||
SThreadMetaData* pThreadMetaData = new SThreadMetaData();
|
||||
pThreadMetaData->m_pThreadTask = 0;
|
||||
pThreadMetaData->m_pThreadMngr = this;
|
||||
pThreadMetaData->m_threadName = sThreadName;
|
||||
pThreadMetaData->m_threadHandle = CryThreadUtil::CryDuplicateThreadHandle(threadHandle); // Ensure that we are not storing a pseudo handle
|
||||
pThreadMetaData->m_threadId = CryThreadUtil::CryGetThreadId(pThreadMetaData->m_threadHandle);
|
||||
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThirdPartyThreadsLock);
|
||||
|
||||
// Check for duplicate
|
||||
SpawnedThirdPartyThreadMapConstIter res = m_spawnedThirdPartyThread.find(sThreadName);
|
||||
if (res != m_spawnedThirdPartyThread.end())
|
||||
{
|
||||
CryFatalError("CThreadManager::RegisterThirdPartyThread - Unable to register thread \"%s\""
|
||||
"because another third party thread with the same name \"%s\" has already been registered with ThreadHandle: %p",
|
||||
sThreadName, res->second->m_threadName.c_str(), reinterpret_cast<void*>(threadHandle));
|
||||
|
||||
delete pThreadMetaData;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert thread data
|
||||
m_spawnedThirdPartyThread.insert(ThirdPartyThreadMapPair(pThreadMetaData->m_threadName.c_str(), pThreadMetaData));
|
||||
}
|
||||
|
||||
// Get thread config
|
||||
const SThreadConfig* pThreadConfig = gEnv->pThreadManager->GetThreadConfigManager()->GetThreadConfig(sThreadName);
|
||||
|
||||
// Apply config (if not default config)
|
||||
if (strcmp(pThreadConfig->szThreadName, sThreadName) == 0)
|
||||
{
|
||||
ApplyThreadConfig(threadHandle, *pThreadConfig);
|
||||
}
|
||||
|
||||
// Update FP exception mask for 3rd party thread
|
||||
if (pThreadMetaData->m_threadId)
|
||||
{
|
||||
CryThreadUtil::EnableFloatExceptions(pThreadMetaData->m_threadId, (EFPE_Severity)g_cvars.sys_float_exceptions);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::UnRegisterThirdPartyThread(const char* sThreadName, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, sThreadName);
|
||||
|
||||
// Format thread name
|
||||
char strThreadName[THREAD_NAME_LENGTH_MAX];
|
||||
const int cNumCharsNeeded = azvsnprintf(strThreadName, CRY_ARRAY_COUNT(strThreadName), sThreadName, args);
|
||||
if (cNumCharsNeeded > THREAD_NAME_LENGTH_MAX - 1)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: ThreadName \"%s\" has been truncated. Max characters allowed: %i. ", strThreadName, THREAD_NAME_LENGTH_MAX - 1);
|
||||
}
|
||||
|
||||
// Unregister 3rd party thread
|
||||
bool ret = UnRegisterThirdPartyThreadImpl(strThreadName);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadManager::UnRegisterThirdPartyThreadImpl(const char* sThreadName)
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThirdPartyThreadsLock);
|
||||
|
||||
SpawnedThirdPartyThreadMapIter res = m_spawnedThirdPartyThread.find(sThreadName);
|
||||
if (res == m_spawnedThirdPartyThread.end())
|
||||
{
|
||||
// Duplicate thread deletion
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: UnRegisterThirdPartyThread: Unable to unregister thread. Thread name \"%s\" could not be found. Double deletion? ", sThreadName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close thread handle
|
||||
CryThreadUtil::CryCloseThreadHandle(res->second->m_threadHandle);
|
||||
|
||||
// Delete reference from container
|
||||
m_spawnedThirdPartyThread.erase(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CThreadManager::GetThreadId(const char* sThreadName, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, sThreadName);
|
||||
|
||||
// Format thread name
|
||||
char strThreadName[THREAD_NAME_LENGTH_MAX];
|
||||
const int cNumCharsNeeded = azvsnprintf(strThreadName, CRY_ARRAY_COUNT(strThreadName), sThreadName, args);
|
||||
if (cNumCharsNeeded > THREAD_NAME_LENGTH_MAX - 1)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: ThreadName \"%s\" has been truncated. Max characters allowed: %i. ", strThreadName, THREAD_NAME_LENGTH_MAX - 1);
|
||||
}
|
||||
|
||||
// Get thread name
|
||||
threadID ret = GetThreadIdImpl(strThreadName);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
threadID CThreadManager::GetThreadIdImpl(const char* sThreadName)
|
||||
{
|
||||
// Loop over internally spawned threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThreadsLock);
|
||||
|
||||
SpawnedThreadMapConstIter iter = m_spawnedThreads.begin();
|
||||
SpawnedThreadMapConstIter iterEnd = m_spawnedThreads.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadName.compare(sThreadName) == 0)
|
||||
{
|
||||
return iter->second->m_threadId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop over third party threads
|
||||
{
|
||||
AUTO_LOCK(m_spawnedThirdPartyThreadsLock);
|
||||
|
||||
SpawnedThirdPartyThreadMapConstIter iter = m_spawnedThirdPartyThread.begin();
|
||||
SpawnedThirdPartyThreadMapConstIter iterEnd = m_spawnedThirdPartyThread.end();
|
||||
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
if (iter->second->m_threadName.compare(sThreadName) == 0)
|
||||
{
|
||||
return iter->second->m_threadId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void EnableFPExceptionsForThread(threadID nThreadId, void* pData)
|
||||
{
|
||||
EFPE_Severity eFPESeverity = *(EFPE_Severity*)pData;
|
||||
CryThreadUtil::EnableFloatExceptions(nThreadId, eFPESeverity);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadManager::EnableFloatExceptions(EFPE_Severity eFPESeverity, threadID nThreadId /*=0*/)
|
||||
{
|
||||
CryThreadUtil::EnableFloatExceptions(nThreadId, eFPESeverity);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadManager::EnableFloatExceptionsForEachOtherThread(EFPE_Severity eFPESeverity)
|
||||
{
|
||||
ForEachOtherThread(EnableFPExceptionsForThread, &eFPESeverity);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint CThreadManager::GetFloatingPointExceptionMask()
|
||||
{
|
||||
return CryThreadUtil::GetFloatingPointExceptionMask();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadManager::SetFloatingPointExceptionMask(uint nMask)
|
||||
{
|
||||
CryThreadUtil::SetFloatingPointExceptionMask(nMask);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::InitThreadSystem()
|
||||
{
|
||||
m_pThreadManager = new CThreadManager();
|
||||
m_env.pThreadManager = m_pThreadManager;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::ShutDownThreadSystem()
|
||||
{
|
||||
SAFE_DELETE(m_pThreadManager);
|
||||
}
|
||||
@@ -46,8 +46,6 @@
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#include "IDebugCallStack.h"
|
||||
|
||||
#if defined(APPLE) || defined(LINUX)
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
@@ -752,13 +750,6 @@ void CSystem::FatalError(const char* format, ...)
|
||||
}
|
||||
|
||||
// Dump callstack.
|
||||
#endif
|
||||
#if defined (WIN32)
|
||||
//Triggers a fatal error, so the DebugCallstack can create the error.log and terminate the application
|
||||
IDebugCallStack::instance()->FatalError(szBuffer);
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMWIN32_CPP_SECTION_1
|
||||
#include AZ_RESTRICTED_FILE(SystemWin32_cpp)
|
||||
#endif
|
||||
|
||||
CryDebugBreak();
|
||||
@@ -800,8 +791,6 @@ void CSystem::ReportBug([[maybe_unused]] const char* format, ...)
|
||||
va_start(ArgList, format);
|
||||
azvsnprintf(szBuffer + strlen(sPrefix), MAX_WARNING_LENGTH - strlen(sPrefix), format, ArgList);
|
||||
va_end(ArgList);
|
||||
|
||||
IDebugCallStack::instance()->ReportBug(szBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -910,10 +899,6 @@ void CSystem::LogSystemInfo()
|
||||
OSVERSIONINFO OSVerInfo;
|
||||
OSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
|
||||
// log Windows type
|
||||
Win32SysInspect::GetOS(m_env.pi.winVer, m_env.pi.win64Bit, szBuffer, sizeof(szBuffer));
|
||||
CryLogAlways(szBuffer);
|
||||
|
||||
// log system language
|
||||
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SENGLANGUAGE, szLanguageBuffer, sizeof(szLanguageBuffer));
|
||||
azsprintf(szBuffer, "System language: %s", szLanguageBuffer);
|
||||
|
||||
@@ -1,577 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "ThreadConfigManager.h"
|
||||
#include "IConsole.h"
|
||||
#include "System.h"
|
||||
#include <StringUtils.h>
|
||||
#include <CryCustomTypes.h>
|
||||
#include "CryUtils.h"
|
||||
namespace
|
||||
{
|
||||
const char* sCurThreadConfigFilename = "";
|
||||
const uint32 sPlausibleStackSizeLimitKB = (1024 * 100); // 100mb
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CThreadConfigManager::CThreadConfigManager()
|
||||
{
|
||||
m_defaultConfig.szThreadName = "CryThread_Unnamed";
|
||||
m_defaultConfig.stackSizeBytes = 0;
|
||||
m_defaultConfig.affinityFlag = -1;
|
||||
m_defaultConfig.priority = THREAD_PRIORITY_NORMAL;
|
||||
m_defaultConfig.bDisablePriorityBoost = false;
|
||||
m_defaultConfig.paramActivityFlag = (SThreadConfig::TThreadParamFlag)~0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const SThreadConfig* CThreadConfigManager::GetThreadConfig(const char* szThreadName, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szThreadName);
|
||||
|
||||
// Format thread name
|
||||
char strThreadName[THREAD_NAME_LENGTH_MAX];
|
||||
const int cNumCharsNeeded = azvsnprintf(strThreadName, CRY_ARRAY_COUNT(strThreadName), szThreadName, args);
|
||||
if (cNumCharsNeeded > THREAD_NAME_LENGTH_MAX - 1)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: ThreadName \"%s\" has been truncated. Max characters allowed: %i. ", strThreadName, THREAD_NAME_LENGTH_MAX - 1);
|
||||
}
|
||||
|
||||
// Get Thread Config
|
||||
const SThreadConfig* retThreasdConfig = GetThreadConfigImpl(strThreadName);
|
||||
|
||||
va_end(args);
|
||||
return retThreasdConfig;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const SThreadConfig* CThreadConfigManager::GetThreadConfigImpl(const char* szThreadName)
|
||||
{
|
||||
// Get thread config for platform
|
||||
ThreadConfigMapConstIter threatRet = m_threadConfig.find(CryFixedStringT<THREAD_NAME_LENGTH_MAX>(szThreadName));
|
||||
if (threatRet == m_threadConfig.end())
|
||||
{
|
||||
// Search in wildcard setups
|
||||
ThreadConfigMapConstIter wildCardIter = m_wildcardThreadConfig.begin();
|
||||
ThreadConfigMapConstIter wildCardIterEnd = m_wildcardThreadConfig.end();
|
||||
for (; wildCardIter != wildCardIterEnd; ++wildCardIter)
|
||||
{
|
||||
if (CryStringUtils::MatchWildcard(szThreadName, wildCardIter->second.szThreadName))
|
||||
{
|
||||
// Store new thread config
|
||||
SThreadConfig threadConfig = wildCardIter->second;
|
||||
std::pair<ThreadConfigMapIter, bool> res;
|
||||
res = m_threadConfig.insert(ThreadConfigMapPair(CryFixedStringT<THREAD_NAME_LENGTH_MAX>(szThreadName), threadConfig));
|
||||
|
||||
// Store name (ref to key)
|
||||
SThreadConfig& rMapThreadConfig = res.first->second;
|
||||
rMapThreadConfig.szThreadName = res.first->first.c_str();
|
||||
|
||||
// Return new thread config
|
||||
return &res.first->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Failure case, no match found
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadInfo>: Unable to find config for thread:%s", szThreadName);
|
||||
return &m_defaultConfig;
|
||||
}
|
||||
|
||||
// Return thread config
|
||||
return &threatRet->second;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const SThreadConfig* CThreadConfigManager::GetDefaultThreadConfig() const
|
||||
{
|
||||
return &m_defaultConfig;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadConfigManager::LoadConfig(const char* pcPath)
|
||||
{
|
||||
// Adjust filename for OnDisk or in .pak file loading
|
||||
char szFullPathBuf[AZ::IO::IArchive::MaxPath];
|
||||
gEnv->pCryPak->AdjustFileName(pcPath, szFullPathBuf, AZ_ARRAY_SIZE(szFullPathBuf), 0);
|
||||
|
||||
// Open file
|
||||
XmlNodeRef xmlRoot = GetISystem()->LoadXmlFromFile(szFullPathBuf);
|
||||
if (!xmlRoot)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: File \"%s\" not found!", pcPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load config for active platform
|
||||
sCurThreadConfigFilename = pcPath;
|
||||
const char* strPlatformId = IdentifyPlatform();
|
||||
CryFixedStringT<32> tmpPlatformStr;
|
||||
bool retValue = false;
|
||||
|
||||
// Try load common platform settings
|
||||
tmpPlatformStr.Format("%s_Common", strPlatformId);
|
||||
LoadPlatformConfig(xmlRoot, tmpPlatformStr.c_str());
|
||||
|
||||
#if defined(CRY_PLATFORM_DESKTOP)
|
||||
// Handle PC specifically as we do not know the core setup of the executing machine.
|
||||
// Try and find the next power of 2 core setup. Otherwise fallback to a lower power of 2 core setup spec
|
||||
|
||||
// Try and load next pow of 2 setup for active pc core configuration
|
||||
const unsigned int numCPUs = ((CSystem*)GetISystem())->GetCPUFeatures()->GetLogicalCPUCount();
|
||||
uint32 i = numCPUs;
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
tmpPlatformStr.Format("%s_%i", strPlatformId, i);
|
||||
retValue = LoadPlatformConfig(xmlRoot, tmpPlatformStr.c_str());
|
||||
if (retValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retValue && i != numCPUs)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: (%s: %u core) Unable to find platform config \"%s\". Next valid config found was %s_%u.",
|
||||
strPlatformId, numCPUs, tmpPlatformStr.c_str(), strPlatformId, i);
|
||||
}
|
||||
|
||||
#else
|
||||
tmpPlatformStr.Format("%s", strPlatformId);
|
||||
retValue = LoadPlatformConfig(xmlRoot, strPlatformId);
|
||||
#endif
|
||||
|
||||
// Print out info
|
||||
if (retValue)
|
||||
{
|
||||
CryLogAlways("<ThreadConfigInfo>: Thread profile loaded: \"%s\" (%s) ", tmpPlatformStr.c_str(), pcPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could not find any matching platform
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: Active platform identifier string \"%s\" not found in config \"%s\".", strPlatformId, sCurThreadConfigFilename);
|
||||
}
|
||||
|
||||
sCurThreadConfigFilename = "";
|
||||
return retValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadConfigManager::ConfigLoaded() const
|
||||
{
|
||||
return !m_threadConfig.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadConfigManager::LoadPlatformConfig(const XmlNodeRef& rXmlRoot, const char* sPlatformId)
|
||||
{
|
||||
// Validate node
|
||||
if (!rXmlRoot->isTag("ThreadConfig"))
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: Unable to find root xml node \"ThreadConfig\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find active platform
|
||||
const uint32 numPlatforms = rXmlRoot->getChildCount();
|
||||
for (uint32 i = 0; i < numPlatforms; ++i)
|
||||
{
|
||||
const XmlNodeRef xmlPlatformNode = rXmlRoot->getChild(i);
|
||||
|
||||
// Is platform node
|
||||
if (!xmlPlatformNode->isTag("Platform"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is has Name attribute
|
||||
if (!xmlPlatformNode->haveAttr("Name"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is platform of interest
|
||||
const char* platformName = xmlPlatformNode->getAttr("Name");
|
||||
if (_stricmp(sPlatformId, platformName) == 0)
|
||||
{
|
||||
// Load platform
|
||||
LoadThreadDefaultConfig(xmlPlatformNode);
|
||||
LoadPlatformThreadConfigs(xmlPlatformNode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadPlatformThreadConfigs(const XmlNodeRef& rXmlPlatformRef)
|
||||
{
|
||||
// Get thread configurations for active platform
|
||||
const uint32 numThreads = rXmlPlatformRef->getChildCount();
|
||||
for (uint32 j = 0; j < numThreads; ++j)
|
||||
{
|
||||
const XmlNodeRef xmlThreadNode = rXmlPlatformRef->getChild(j);
|
||||
|
||||
if (!xmlThreadNode->isTag("Thread"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure thread config has name
|
||||
if (!xmlThreadNode->haveAttr("Name"))
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Thread node without \"name\" attribute encountered.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load thread config
|
||||
SThreadConfig loadedThreadConfig = SThreadConfig(m_defaultConfig);
|
||||
LoadThreadConfig(xmlThreadNode, loadedThreadConfig);
|
||||
|
||||
// Get thread name and check if it contains wildcard characters
|
||||
const char* szThreadName = xmlThreadNode->getAttr("Name");
|
||||
bool bWildCard = strchr(szThreadName, '*') ? true : false;
|
||||
ThreadConfigMap& threadConfig = bWildCard ? m_wildcardThreadConfig : m_threadConfig;
|
||||
|
||||
// Check for duplicate and override it with new config if found
|
||||
if (threadConfig.find(szThreadName) != threadConfig.end())
|
||||
{
|
||||
CryLogAlways("<ThreadConfigInfo>: [XML Parsing] Thread with name \"%s\" already loaded. Overriding with new configuration", szThreadName);
|
||||
threadConfig[szThreadName] = loadedThreadConfig;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store new thread config
|
||||
std::pair<ThreadConfigMapIter, bool> res;
|
||||
res = threadConfig.insert(ThreadConfigMapPair(CryFixedStringT<THREAD_NAME_LENGTH_MAX>(szThreadName), loadedThreadConfig));
|
||||
|
||||
// Store name (ref to key)
|
||||
SThreadConfig& rMapThreadConfig = res.first->second;
|
||||
rMapThreadConfig.szThreadName = res.first->first.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CThreadConfigManager::LoadThreadDefaultConfig(const XmlNodeRef& rXmlPlatformRef)
|
||||
{
|
||||
// Find default thread config node
|
||||
const uint32 numNodes = rXmlPlatformRef->getChildCount();
|
||||
for (uint32 j = 0; j < numNodes; ++j)
|
||||
{
|
||||
const XmlNodeRef xmlNode = rXmlPlatformRef->getChild(j);
|
||||
|
||||
// Load default config
|
||||
if (xmlNode->isTag("ThreadDefault"))
|
||||
{
|
||||
LoadThreadConfig(xmlNode, m_defaultConfig);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadAffinity(const XmlNodeRef& rXmlThreadRef, uint32& rAffinity, SThreadConfig::TThreadParamFlag& rParamActivityFlag)
|
||||
{
|
||||
const char* szValidCharacters = "-,0123456789";
|
||||
uint32 affinity = 0;
|
||||
|
||||
// Validate node
|
||||
if (!rXmlThreadRef->haveAttr("Affinity"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate token
|
||||
CryFixedStringT<32> affinityRawStr(rXmlThreadRef->getAttr("Affinity"));
|
||||
if (affinityRawStr.empty())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Empty attribute \"Affinity\" encountered");
|
||||
return;
|
||||
}
|
||||
|
||||
if (affinityRawStr.compareNoCase("ignore") == 0)
|
||||
{
|
||||
// Param is inactive, clear bit
|
||||
rParamActivityFlag &= ~SThreadConfig::eThreadParamFlag_Affinity;
|
||||
return;
|
||||
}
|
||||
|
||||
CryFixedStringT<32>::size_type nPos = affinityRawStr.find_first_not_of(" -,0123456789");
|
||||
if (nPos != CryFixedStringT<32>::npos)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING,
|
||||
"<ThreadConfigInfo>: [XML Parsing] Invalid character \"%c\" encountered in \"Affinity\" attribute. Valid characters:\"%s\" Offending token:\"%s\"", affinityRawStr.at(nPos),
|
||||
szValidCharacters, affinityRawStr.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Tokenize comma separated string
|
||||
int pos = 0;
|
||||
CryFixedStringT<32> affnityTokStr = affinityRawStr.Tokenize(",", pos);
|
||||
while (!affnityTokStr.empty())
|
||||
{
|
||||
affnityTokStr.Trim();
|
||||
|
||||
long affinityId = strtol(affnityTokStr.c_str(), NULL, 10);
|
||||
if (affinityId == LONG_MAX || affinityId == LONG_MIN)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Unknown value \"%s\" encountered for attribute \"Affinity\"", affnityTokStr.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow scheduler to pick thread
|
||||
if (affinityId == -1)
|
||||
{
|
||||
affinity = ~0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set affinity bit
|
||||
affinity |= BIT(affinityId);
|
||||
|
||||
// Move to next token
|
||||
affnityTokStr = affinityRawStr.Tokenize(",", pos);
|
||||
}
|
||||
|
||||
// Set affinity reference
|
||||
rAffinity = affinity;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadPriority(const XmlNodeRef& rXmlThreadRef, int32& rPriority, SThreadConfig::TThreadParamFlag& rParamActivityFlag)
|
||||
{
|
||||
const char* szValidCharacters = "-,0123456789";
|
||||
|
||||
// Validate node
|
||||
if (!rXmlThreadRef->haveAttr("Priority"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate token
|
||||
CryFixedStringT<32> threadPrioStr(rXmlThreadRef->getAttr("Priority"));
|
||||
threadPrioStr.Trim();
|
||||
if (threadPrioStr.empty())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Empty attribute \"Priority\" encountered");
|
||||
return;
|
||||
}
|
||||
|
||||
if (threadPrioStr.compareNoCase("ignore") == 0)
|
||||
{
|
||||
// Param is inactive, clear bit
|
||||
rParamActivityFlag &= ~SThreadConfig::eThreadParamFlag_Priority;
|
||||
return;
|
||||
}
|
||||
|
||||
// Test for character string (no numbers allowed)
|
||||
if (threadPrioStr.find_first_of(szValidCharacters) == CryFixedStringT<32>::npos)
|
||||
{
|
||||
threadPrioStr.MakeLower();
|
||||
|
||||
// Set priority
|
||||
if (threadPrioStr.compare("below_normal") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_BELOW_NORMAL;
|
||||
}
|
||||
else if (threadPrioStr.compare("normal") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_NORMAL;
|
||||
}
|
||||
else if (threadPrioStr.compare("above_normal") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||
}
|
||||
else if (threadPrioStr.compare("idle") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_IDLE;
|
||||
}
|
||||
else if (threadPrioStr.compare("lowest") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_LOWEST;
|
||||
}
|
||||
else if (threadPrioStr.compare("highest") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_HIGHEST;
|
||||
}
|
||||
else if (threadPrioStr.compare("time_critical") == 0)
|
||||
{
|
||||
rPriority = THREAD_PRIORITY_TIME_CRITICAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Platform unsupported value \"%s\" encountered for attribute \"Priority\"", threadPrioStr.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Test for number string (no alphabetical characters allowed)
|
||||
else if (threadPrioStr.find_first_not_of(szValidCharacters) == CryFixedStringT<32>::npos)
|
||||
{
|
||||
long numValue = strtol(threadPrioStr.c_str(), NULL, 10);
|
||||
if (numValue == LONG_MAX || numValue == LONG_MIN)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Unsupported number type \"%s\" for for attribute \"Priority\"", threadPrioStr.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Set priority
|
||||
rPriority = numValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// String contains characters and numbers
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Unsupported type \"%s\" encountered for attribute \"Priority\". Token containers numbers and characters", threadPrioStr.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadDisablePriorityBoost(const XmlNodeRef& rXmlThreadRef, bool& rPriorityBoost, SThreadConfig::TThreadParamFlag& rParamActivityFlag)
|
||||
{
|
||||
// Validate node
|
||||
if (!rXmlThreadRef->haveAttr("DisablePriorityBoost"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract bool info
|
||||
CryFixedStringT<16> sAttribToken(rXmlThreadRef->getAttr("DisablePriorityBoost"));
|
||||
sAttribToken.Trim();
|
||||
sAttribToken.MakeLower();
|
||||
|
||||
if (sAttribToken.compare("ignore") == 0)
|
||||
{
|
||||
// Param is inactive, clear bit
|
||||
rParamActivityFlag &= ~SThreadConfig::eThreadParamFlag_PriorityBoost;
|
||||
return;
|
||||
}
|
||||
else if (sAttribToken.compare("true") == 0 || sAttribToken.compare("1") == 0)
|
||||
{
|
||||
rPriorityBoost = true;
|
||||
}
|
||||
else if (sAttribToken.compare("false") == 0 || sAttribToken.compare("0") == 0)
|
||||
{
|
||||
rPriorityBoost = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Unsupported bool type \"%s\" encountered for attribute \"DisablePriorityBoost\"",
|
||||
rXmlThreadRef->getAttr("DisablePriorityBoost"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadStackSize(const XmlNodeRef& rXmlThreadRef, uint32& rStackSize, SThreadConfig::TThreadParamFlag& rParamActivityFlag)
|
||||
{
|
||||
const char* sValidCharacters = "0123456789";
|
||||
|
||||
if (rXmlThreadRef->haveAttr("StackSizeKB"))
|
||||
{
|
||||
// Read stack size
|
||||
CryFixedStringT<32> stackSize(rXmlThreadRef->getAttr("StackSizeKB"));
|
||||
|
||||
// Validate stack size
|
||||
if (stackSize.empty())
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Empty attribute \"StackSize\" encountered");
|
||||
return;
|
||||
}
|
||||
else if (stackSize.compareNoCase("ignore") == 0)
|
||||
{
|
||||
// Param is inactive, clear bit
|
||||
rParamActivityFlag &= ~SThreadConfig::eThreadParamFlag_StackSize;
|
||||
return;
|
||||
}
|
||||
else if (stackSize.find_first_not_of(sValidCharacters) == CryFixedStringT<32>::npos)
|
||||
{
|
||||
// Convert string to long
|
||||
long stackSizeVal = strtol(stackSize.c_str(), NULL, 10);
|
||||
if (stackSizeVal == LONG_MAX || stackSizeVal == LONG_MIN)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] Invalid number for \"StackSize\" encountered. \"%s\"", stackSize.c_str());
|
||||
return;
|
||||
}
|
||||
else if (stackSizeVal <= 0 || stackSizeVal > sPlausibleStackSizeLimitKB)
|
||||
{
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "<ThreadConfigInfo>: [XML Parsing] \"StackSize\" value not plausible \"%" PRId64 "KB\"", (int64)stackSizeVal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set stack size
|
||||
rStackSize = stackSizeVal * 1024; // Convert to bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::LoadThreadConfig(const XmlNodeRef& rXmlThreadRef, SThreadConfig& rThreadConfig)
|
||||
{
|
||||
LoadAffinity(rXmlThreadRef, rThreadConfig.affinityFlag, rThreadConfig.paramActivityFlag);
|
||||
LoadPriority(rXmlThreadRef, rThreadConfig.priority, rThreadConfig.paramActivityFlag);
|
||||
LoadDisablePriorityBoost(rXmlThreadRef, rThreadConfig.bDisablePriorityBoost, rThreadConfig.paramActivityFlag);
|
||||
LoadStackSize(rXmlThreadRef, rThreadConfig.stackSizeBytes, rThreadConfig.paramActivityFlag);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* CThreadConfigManager::IdentifyPlatform()
|
||||
{
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#include AZ_RESTRICTED_FILE(ThreadConfigManager_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(ANDROID)
|
||||
return "android";
|
||||
#elif defined(LINUX)
|
||||
return "linux";
|
||||
#elif defined(APPLE)
|
||||
return "mac";
|
||||
#elif defined(WIN32) || defined(WIN64)
|
||||
return "pc";
|
||||
#else
|
||||
#error "Undefined platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CThreadConfigManager::DumpThreadConfigurationsToLog()
|
||||
{
|
||||
#if !defined(RELEASE)
|
||||
|
||||
// Print header
|
||||
CryLogAlways("== Thread Startup Config List (\"%s\") ==", IdentifyPlatform());
|
||||
|
||||
// Print loaded default config
|
||||
CryLogAlways(" (Default) 1. \"%s\" (StackSize:%uKB | Affinity:%u | Priority:%i | PriorityBoost:\"%s\")", m_defaultConfig.szThreadName, m_defaultConfig.stackSizeBytes / 1024,
|
||||
m_defaultConfig.affinityFlag, m_defaultConfig.priority, m_defaultConfig.bDisablePriorityBoost ? "disabled" : "enabled");
|
||||
|
||||
// Print loaded thread configs
|
||||
int listItemCounter = 1;
|
||||
ThreadConfigMapConstIter iter = m_threadConfig.begin();
|
||||
ThreadConfigMapConstIter iterEnd = m_threadConfig.end();
|
||||
for (; iter != iterEnd; ++iter)
|
||||
{
|
||||
const SThreadConfig& threadConfig = iter->second;
|
||||
CryLogAlways("%3d.\"%s\" %s (StackSize:%uKB %s | Affinity:%u %s | Priority:%i %s | PriorityBoost:\"%s\" %s)", ++listItemCounter,
|
||||
threadConfig.szThreadName, (threadConfig.paramActivityFlag & SThreadConfig::eThreadParamFlag_ThreadName) ? "" : "(ignored)",
|
||||
threadConfig.stackSizeBytes / 1024u, (threadConfig.paramActivityFlag & SThreadConfig::eThreadParamFlag_StackSize) ? "" : "(ignored)",
|
||||
threadConfig.affinityFlag, (threadConfig.paramActivityFlag & SThreadConfig::eThreadParamFlag_Affinity) ? "" : "(ignored)",
|
||||
threadConfig.priority, (threadConfig.paramActivityFlag & SThreadConfig::eThreadParamFlag_Priority) ? "" : "(ignored)",
|
||||
!threadConfig.bDisablePriorityBoost ? "enabled" : "disabled", (threadConfig.paramActivityFlag & SThreadConfig::eThreadParamFlag_PriorityBoost) ? "" : "(ignored)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "IThreadConfigManager.h"
|
||||
|
||||
/*
|
||||
ThreadConfigManager:
|
||||
Loads a thread configuration from an xml file and stores them.
|
||||
|
||||
== XML File Layout and Rules: ===
|
||||
|
||||
= Platform names =
|
||||
(case insensitive)
|
||||
"ANDROID"
|
||||
"PC"
|
||||
"MAC"
|
||||
etc.
|
||||
|
||||
= Basic Layout =
|
||||
<ThreadConfig>
|
||||
<Platform name="XXX">
|
||||
<ThreadDefault Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="A" Affinity="XX" Priority="XX" StackSizeKB="XX">
|
||||
<Thread name ="B" Affinity="XX" >
|
||||
...
|
||||
</Platform>
|
||||
|
||||
<Platform name="YYY">
|
||||
...
|
||||
</Platform>
|
||||
</ThreadConfig>
|
||||
|
||||
= Parser Order for Platform =
|
||||
1. PlatformName_Common (valid for all potential platform configurations. Can be overridden by concert platform configuration)
|
||||
2. PlatformName or PlatformName_X (for platforms with unknown CPU count where X is the number of potential cores. The equal or next lower matching configuration for the identified core count at runtime will be taken)
|
||||
|
||||
Note: Overriding of thread configuration by later parsed configuration allowed.
|
||||
|
||||
= <ThreadDefault> and <Thread> XML attributes =
|
||||
|
||||
!!!
|
||||
Note: Use "ignore" as value if you do not want the thread system to set the value specifically!
|
||||
If a value is not defines the <ThreadDefault> value of the parameter will be used.
|
||||
This is useful when dealing with 3rdParty threads where you are not in control of the parameter setup.
|
||||
!!!
|
||||
|
||||
Name:
|
||||
"x" (string) : Name of thread
|
||||
"x*y" (string) : Name of thread with wildcard character
|
||||
|
||||
Affinity:
|
||||
"-1" : Put SW thread affinity in the hands of the scheduler - (default) -
|
||||
"x" : Run thread on specified core
|
||||
"x, y, ..." : Run thread on specified cores
|
||||
|
||||
Priority:
|
||||
"idle" : Hint to CryEngine to run thread with pre-set priority
|
||||
"below_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"normal" : Hint to CryEngine to run thread with pre-set priority - (default) -
|
||||
"above_normal" : Hint to CryEngine to run thread with pre-set priority
|
||||
"highest" : Hint to CryEngine to run thread with pre-set priority
|
||||
"time_critical" : Hint to CryEngine to run thread with pre-set priority
|
||||
"x" (number) : User defined thread priority number
|
||||
|
||||
StackSizeKB:
|
||||
"0" : Let platform decide on the stack size - (default) -
|
||||
"x" : Create thread with "x" KB of stack size
|
||||
|
||||
DisablePriorityBoost:
|
||||
"true" : Disable priority boosting - (default) -
|
||||
"false" : Enable priority boosting
|
||||
*/
|
||||
|
||||
class CThreadConfigManager
|
||||
: public IThreadConfigManager
|
||||
{
|
||||
public:
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, SThreadConfig> ThreadConfigMap;
|
||||
typedef std::pair<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, SThreadConfig> ThreadConfigMapPair;
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, SThreadConfig>::iterator ThreadConfigMapIter;
|
||||
typedef std::map<CryFixedStringT<THREAD_NAME_LENGTH_MAX>, SThreadConfig>::const_iterator ThreadConfigMapConstIter;
|
||||
|
||||
public:
|
||||
CThreadConfigManager();
|
||||
~CThreadConfigManager()
|
||||
{
|
||||
}
|
||||
|
||||
// Called once during System startup.
|
||||
// Loads the thread configuration for the executing platform from file.
|
||||
virtual bool LoadConfig(const char* pcPath) override;
|
||||
|
||||
// Returns true if a config has been loaded
|
||||
virtual bool ConfigLoaded() const override;
|
||||
|
||||
// Gets the thread configuration for the specified thread on the active platform.
|
||||
// If no matching config is found a default configuration is returned
|
||||
// (which does not have the same name as the search string).
|
||||
virtual const SThreadConfig* GetThreadConfig(const char* sThreadName, ...) override;
|
||||
virtual const SThreadConfig* GetDefaultThreadConfig() const override;
|
||||
|
||||
virtual void DumpThreadConfigurationsToLog() override;
|
||||
|
||||
private:
|
||||
const char* IdentifyPlatform();
|
||||
|
||||
const SThreadConfig* GetThreadConfigImpl(const char* cThreadName);
|
||||
|
||||
bool LoadPlatformConfig(const XmlNodeRef& rXmlRoot, const char* sPlatformId);
|
||||
|
||||
void LoadPlatformThreadConfigs(const XmlNodeRef& rXmlPlatformRef);
|
||||
bool LoadThreadDefaultConfig(const XmlNodeRef& rXmlPlatformRef);
|
||||
void LoadThreadConfig(const XmlNodeRef& rXmlThreadRef, SThreadConfig& rThreadConfig);
|
||||
|
||||
void LoadAffinity(const XmlNodeRef& rXmlThreadRef, uint32& rAffinity, SThreadConfig::TThreadParamFlag& rParamActivityFlag);
|
||||
void LoadPriority(const XmlNodeRef& rXmlThreadRef, int32& rPriority, SThreadConfig::TThreadParamFlag& rParamActivityFlag);
|
||||
void LoadDisablePriorityBoost(const XmlNodeRef& rXmlThreadRef, bool& rPriorityBoost, SThreadConfig::TThreadParamFlag& rParamActivityFlag);
|
||||
void LoadStackSize(const XmlNodeRef& rXmlThreadRef, uint32& rStackSize, SThreadConfig::TThreadParamFlag& rParamActivityFlag);
|
||||
|
||||
private:
|
||||
ThreadConfigMap m_threadConfig; // Note: The map key is referenced by as const char* by the value's storage class. Other containers may not support this behaviour as they will re-allocate memory as they grow/shrink.
|
||||
ThreadConfigMap m_wildcardThreadConfig;
|
||||
SThreadConfig m_defaultConfig;
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include "ThreadInfo.h"
|
||||
#include "System.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
#define THREADINFO_CPP_SECTION_1 1
|
||||
#define THREADINFO_CPP_SECTION_2 2
|
||||
#endif
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION THREADINFO_CPP_SECTION_1
|
||||
#include AZ_RESTRICTED_FILE(ThreadInfo_cpp)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
#if AZ_LEGACY_CRYSYSTEM_TRAIT_THREADINFO_WINDOWS_STYLE
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SThreadInfo::GetCurrentThreads(TThreadInfo& threadsOut)
|
||||
{
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
DWORD currProcessId = GetCurrentProcessId();
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 te;
|
||||
te.dwSize = sizeof(te);
|
||||
if (Thread32First(h, &te))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
|
||||
{
|
||||
if (te.th32OwnerProcessID == currProcessId)
|
||||
{
|
||||
threadsOut[te.th32ThreadID] = CryThreadGetName(te.th32ThreadID);
|
||||
}
|
||||
}
|
||||
te.dwSize = sizeof(te);
|
||||
} while (Thread32Next(h, &te));
|
||||
}
|
||||
CloseHandle(h);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SThreadInfo::OpenThreadHandles(TThreads& threadsOut, const TThreadIds& threadIds /* = TThreadIds()*/, bool ignoreCurrThread /* = true*/)
|
||||
{
|
||||
TThreadIds threadids = threadIds;
|
||||
if (threadids.empty())
|
||||
{
|
||||
TThreadInfo threads;
|
||||
GetCurrentThreads(threads);
|
||||
DWORD currThreadId = GetCurrentThreadId();
|
||||
for (TThreadInfo::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
if (!ignoreCurrThread || it->first != currThreadId)
|
||||
{
|
||||
threadids.push_back(it->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (TThreadIds::iterator it = threadids.begin(), end = threadids.end(); it != end; ++it)
|
||||
{
|
||||
SThreadHandle thread;
|
||||
thread.Id = *it;
|
||||
thread.Handle = OpenThread(THREAD_ALL_ACCESS, FALSE, *it);
|
||||
threadsOut.push_back(thread);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SThreadInfo::CloseThreadHandles(const TThreads& threads)
|
||||
{
|
||||
for (TThreads::const_iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
CloseHandle(it->Handle);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION THREADINFO_CPP_SECTION_2
|
||||
#include AZ_RESTRICTED_FILE(ThreadInfo_cpp)
|
||||
#elif defined(LINUX) || defined(APPLE)
|
||||
void SThreadInfo::GetCurrentThreads(TThreadInfo& threadsOut)
|
||||
{
|
||||
assert(false); // not implemented!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SThreadInfo::OpenThreadHandles(TThreads& threadsOut, const TThreadIds& threadIds /* = TThreadIds()*/, bool ignoreCurrThread /* = true*/)
|
||||
{
|
||||
assert(false); // not implemented!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SThreadInfo::CloseThreadHandles(const TThreads& threads)
|
||||
{
|
||||
assert(false); // not implemented!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_THREADINFO_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_THREADINFO_H
|
||||
#pragma once
|
||||
|
||||
|
||||
struct SThreadInfo
|
||||
{
|
||||
public:
|
||||
struct SThreadHandle
|
||||
{
|
||||
HANDLE Handle;
|
||||
uint32 Id;
|
||||
};
|
||||
|
||||
typedef std::vector<uint32> TThreadIds;
|
||||
typedef std::vector<SThreadHandle> TThreads;
|
||||
typedef std::map<uint32, string> TThreadInfo;
|
||||
|
||||
// returns thread info
|
||||
static void GetCurrentThreads(TThreadInfo& threadsOut);
|
||||
|
||||
// fills threadsOut vector with thread handles of given thread ids; if threadIds vector is emtpy it fills all running threads
|
||||
// if ignoreCurrThread is true it will not return the current thread
|
||||
static void OpenThreadHandles(TThreads& threadsOut, const TThreadIds& threadIds = TThreadIds(), bool ignoreCurrThread = true);
|
||||
|
||||
// closes thread handles; should be called whenever GetCurrentThreads was called!
|
||||
static void CloseThreadHandles(const TThreads& threads);
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_THREADINFO_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,181 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_THREADTASK_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_THREADTASK_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <IThreadTask.h>
|
||||
#include <CryThread.h>
|
||||
#include <MultiThread_Containers.h>
|
||||
|
||||
#define MAIN_THREAD_INDEX 0
|
||||
|
||||
class CThreadTask_Thread;
|
||||
|
||||
|
||||
void MarkThisThreadForDebugging(const char* name);
|
||||
void UnmarkThisThreadFromDebugging();
|
||||
void UpdateFPExceptionsMaskForThreads();
|
||||
|
||||
|
||||
class CThreadTaskManager;
|
||||
///
|
||||
struct IThreadTaskRunnable
|
||||
{
|
||||
virtual ~IThreadTaskRunnable(){}
|
||||
virtual void Run() = 0;
|
||||
virtual void Cancel() = 0;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CThreadTask_Thread
|
||||
: public CryThread<IThreadTaskRunnable>
|
||||
, public IThreadTask_Thread
|
||||
{
|
||||
protected:
|
||||
void Init();
|
||||
public:
|
||||
CThreadTask_Thread(CThreadTaskManager* pTaskMgr, const char* sName, int nThreadIndex, int nProcessor, int nThreadPriority, ThreadPoolHandle poolHandle = -1);
|
||||
~CThreadTask_Thread();
|
||||
|
||||
// see IThreadTaskRunnable, CryThread<>
|
||||
void Run() override;
|
||||
void Cancel() override;
|
||||
|
||||
// see CryThread<>
|
||||
void Terminate() override;
|
||||
|
||||
// IThreadTask_Thread
|
||||
void AddTask(SThreadTaskInfo* pTaskInfo) override;
|
||||
void RemoveTask(SThreadTaskInfo* pTaskInfo) override;
|
||||
void RemoveAllTasks() override;
|
||||
void SingleUpdate() override;
|
||||
|
||||
void ChangeProcessor(int nProcessor);
|
||||
public:
|
||||
CThreadTaskManager* m_pTaskManager;
|
||||
string m_sThreadName;
|
||||
int m_nThreadIndex; // -1 means the thread is blocking
|
||||
int m_nProcessor;
|
||||
int m_nThreadPriority;
|
||||
|
||||
THREAD_HANDLE m_hThreadHandle;
|
||||
|
||||
// Tasks running on this thread.
|
||||
typedef CryMT::CLocklessPointerQueue<SThreadTaskInfo, stl::STLGlobalAllocator<SThreadTaskInfo> > Tasks;
|
||||
Tasks tasks;
|
||||
|
||||
// The task is being processing now
|
||||
SThreadTaskInfo* m_pProcessingTask;
|
||||
|
||||
CryEvent m_waitForTasks;
|
||||
|
||||
// Set to true when thread must stop.
|
||||
volatile bool bStopThread;
|
||||
volatile bool bRunning;
|
||||
|
||||
// handle of threads pool which this thread belongs to(if any)
|
||||
ThreadPoolHandle m_poolHandle;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CThreadTaskManager
|
||||
: public IThreadTaskManager
|
||||
{
|
||||
private:
|
||||
typedef std::vector<CThreadTask_Thread*, stl::STLGlobalAllocator<CThreadTask_Thread*> > Threads;
|
||||
// note: this struct is auxilary and NOT thread-safe
|
||||
// it is only for internal use inside the task manager
|
||||
struct CThreadsPool
|
||||
{
|
||||
ThreadPoolHandle m_hHandle;
|
||||
Threads m_Threads;
|
||||
ThreadPoolDesc m_pDescription;
|
||||
const bool SetAffinity(const ThreadPoolAffinityMask AffinityMask);
|
||||
const bool operator < (const CThreadsPool& p) const { return m_hHandle < p.m_hHandle; }
|
||||
const bool operator == (const CThreadsPool& p) const { return m_hHandle == p.m_hHandle; }
|
||||
};
|
||||
|
||||
typedef std::vector<CThreadsPool> ThreadsPools;
|
||||
|
||||
public:
|
||||
CThreadTaskManager();
|
||||
~CThreadTaskManager();
|
||||
|
||||
void InitThreads();
|
||||
void CloseThreads();
|
||||
void StopAllThreads();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IThreadTaskManager
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void RegisterTask(IThreadTask* pTask, const SThreadTaskParams& options);
|
||||
virtual void UnregisterTask(IThreadTask* pTask);
|
||||
virtual void SetMaxThreadCount(int nMaxThreads);
|
||||
virtual void SetThreadName(threadID dwThreadId, const char* sThreadName);
|
||||
virtual const char* GetThreadName(threadID dwThreadId);
|
||||
virtual threadID GetThreadByName(const char* sThreadName);
|
||||
|
||||
// Thread pool framework
|
||||
virtual ThreadPoolHandle CreateThreadsPool(const ThreadPoolDesc& desc);
|
||||
virtual const bool DestroyThreadsPool(const ThreadPoolHandle& handle);
|
||||
virtual const bool GetThreadsPoolDesc(const ThreadPoolHandle handle, ThreadPoolDesc* pDesc) const;
|
||||
virtual const bool SetThreadsPoolAffinity(const ThreadPoolHandle handle, const ThreadPoolAffinityMask AffinityMask);
|
||||
|
||||
virtual void MarkThisThreadForDebugging(const char* name, bool bDump);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is on update function of the main thread.
|
||||
void OnUpdate();
|
||||
|
||||
void AddSystemThread(threadID nThreadId);
|
||||
void RemoveSystemThread(threadID nThreadId);
|
||||
|
||||
// Balancing tasks in the pool between threads
|
||||
void BalanceThreadsPool(const ThreadPoolHandle& handle);
|
||||
void BalanceThreadInPool(CThreadTask_Thread* pFreeThread, Threads* pThreads = NULL);
|
||||
|
||||
private:
|
||||
void ScheduleTask(SThreadTaskInfo* pTaskInfo);
|
||||
void RescheduleTasks();
|
||||
private:
|
||||
|
||||
// User created threads pools
|
||||
mutable CryReadModifyLock m_threadsPoolsLock;
|
||||
ThreadsPools m_threadsPools;
|
||||
|
||||
// Physical threads available to system.
|
||||
Threads m_threads;
|
||||
|
||||
// Threads with single blocking task attached.
|
||||
Threads m_blockingThreads;
|
||||
|
||||
typedef CryMT::CLocklessPointerQueue<SThreadTaskInfo> Tasks;
|
||||
|
||||
Tasks m_unassignedTasks;
|
||||
|
||||
mutable CryCriticalSection m_threadNameLock;
|
||||
mutable CryCriticalSection m_threadRemove;
|
||||
typedef std::map<threadID, string> ThreadNames;
|
||||
ThreadNames m_threadNames;
|
||||
|
||||
mutable CryCriticalSection m_systemThreadsLock;
|
||||
std::vector<threadID> m_systemThreads;
|
||||
|
||||
// Max threads that can be executed at same time.
|
||||
int m_nMaxThreads;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_THREADTASK_H
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CrySystem_precompiled.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <Cry_Math.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class CryMathTestFixture
|
||||
: public ::testing::Test
|
||||
{};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_MATH_TESTS
|
||||
TEST_F(CryMathTestFixture, DISABLED_InverserSqrt_HasAtLeast22BitsOfAccuracy)
|
||||
#else
|
||||
TEST_F(CryMathTestFixture, InverserSqrt_HasAtLeast22BitsOfAccuracy)
|
||||
#endif
|
||||
{
|
||||
float testFloat(0.336950600);
|
||||
const float result = isqrt_safe_tpl(testFloat * testFloat);
|
||||
const float epsilon = 0.00001f;
|
||||
EXPECT_NEAR(2.96779, result, epsilon);
|
||||
}
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_MATH_TESTS
|
||||
TEST_F(CryMathTestFixture, DISABLED_SimdSqrt_HasAtLeast23BitsOfAccuracy)
|
||||
#else
|
||||
TEST_F(CryMathTestFixture, SimdSqrt_HasAtLeast23BitsOfAccuracy)
|
||||
#endif
|
||||
{
|
||||
float testFloat(3434.34839439);
|
||||
const float result = sqrt_tpl(testFloat);
|
||||
const float epsilon = 0.00001f;
|
||||
EXPECT_NEAR(58.60331, result, epsilon);
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include "CrySystem_precompiled.h"
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/UnitTest/UnitTest.h>
|
||||
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/IO/SystemFile.h> // for max path decl
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/std/parallel/semaphore.h>
|
||||
#include <AzCore/std/functional.h> // for function<> in the find files callback.
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzFramework/Archive/ArchiveFileIO.h>
|
||||
#include <AzFramework/Archive/Archive.h>
|
||||
#include <AzFramework/Archive/INestedArchive.h>
|
||||
#include <ILevelSystem.h>
|
||||
|
||||
namespace CryPakUnitTests
|
||||
{
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
|
||||
// Note: none of the below is really a unit test, its all basic feature tests
|
||||
// for critical functionality
|
||||
|
||||
class Integ_CryPakUnitTests
|
||||
: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
bool IsPackValid(const char* path)
|
||||
{
|
||||
AZ::IO::IArchive* pak = gEnv->pCryPak;
|
||||
if (!pak)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pak->OpenPack(path, AZ::IO::IArchive::FLAGS_PATH_REAL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pak->ClosePack(path);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(Integ_CryPakUnitTests, TestCryPakModTime)
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance();
|
||||
ASSERT_NE(nullptr, fileIo);
|
||||
|
||||
AZ::IO::IArchive* pak = gEnv->pCryPak;
|
||||
// repeat the following test multiple times, since timing (seconds) can affect it and it involves time!
|
||||
for (int iteration = 0; iteration < 10; ++iteration)
|
||||
{
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds{ 100 });
|
||||
|
||||
// helper paths and strings
|
||||
AZStd::string gameFolder = fileIo->GetAlias("@usercache@");
|
||||
|
||||
AZStd::string testFile = "unittest.bin";
|
||||
AZStd::string testFilePath = gameFolder + "\\" + testFile;
|
||||
AZStd::string testPak = "unittest.pak";
|
||||
AZStd::string testPakPath = gameFolder + "\\" + testPak;
|
||||
AZStd::string zipCmd = "-zip=" + testPakPath;
|
||||
|
||||
// delete test files in case they already exist
|
||||
fileIo->Remove(testFilePath.c_str());
|
||||
pak->ClosePack(testPakPath);
|
||||
fileIo->Remove(testPakPath.c_str());
|
||||
|
||||
// create a test file
|
||||
char data[] = "unittest";
|
||||
FILE* f = nullptr;
|
||||
azfopen(&f, testFilePath.c_str(), "wb");
|
||||
EXPECT_TRUE(f != nullptr); // file successfully opened for writing
|
||||
EXPECT_TRUE(fwrite(data, sizeof(char), sizeof(data), f) == sizeof(data)); // file written to successfully
|
||||
EXPECT_TRUE(fclose(f) == 0); // file closed successfully
|
||||
|
||||
AZ::IO::HandleType fDisk = pak->FOpen(testFilePath.c_str(), "rb");
|
||||
EXPECT_TRUE(fDisk > 0); // opened file on disk successfully
|
||||
uint64_t modTimeDisk = pak->GetModificationTime(fDisk); // high res mod time extracted from file on disk
|
||||
EXPECT_TRUE(pak->FClose(fDisk) == 0); // file closed successfully
|
||||
|
||||
// create a low res copy of disk file's mod time
|
||||
uint64_t absDiff, maxDiff = 20000000ul;
|
||||
uint16_t dosDate, dosTime;
|
||||
FILETIME ft;
|
||||
LARGE_INTEGER lt;
|
||||
|
||||
ft.dwHighDateTime = modTimeDisk >> 32;
|
||||
ft.dwLowDateTime = modTimeDisk & 0xFFFFFFFF;
|
||||
EXPECT_TRUE(FileTimeToDosDateTime(&ft, &dosDate, &dosTime) != FALSE); // converted to DOSTIME successfully
|
||||
ft.dwHighDateTime = 0;
|
||||
ft.dwLowDateTime = 0;
|
||||
EXPECT_TRUE(DosDateTimeToFileTime(dosDate, dosTime, &ft) != FALSE); // converted to FILETIME successfully
|
||||
lt.HighPart = ft.dwHighDateTime;
|
||||
lt.LowPart = ft.dwLowDateTime;
|
||||
uint64_t modTimeDiskLowRes = lt.QuadPart;
|
||||
|
||||
absDiff = modTimeDiskLowRes >= modTimeDisk ? modTimeDiskLowRes - modTimeDisk : modTimeDisk - modTimeDiskLowRes;
|
||||
EXPECT_LE(absDiff, maxDiff); // FILETIME (high res) and DOSTIME (low res) should be at most 2 seconds apart
|
||||
|
||||
gEnv->pResourceCompilerHelper->CallResourceCompiler(testFilePath.c_str(), zipCmd.c_str());
|
||||
EXPECT_EQ(AZ::IO::ResultCode::Success, fileIo->Remove(testFilePath.c_str())); // test file on disk deleted successfully
|
||||
|
||||
EXPECT_TRUE(pak->OpenPack(testPakPath)); // opened pak successfully
|
||||
|
||||
AZ::IO::HandleType fPak = pak->FOpen(testFilePath.c_str(), "rb");
|
||||
EXPECT_GT(fPak, 0); // file (in pak) opened correctly
|
||||
uint64_t modTimePak = pak->GetModificationTime(fPak); // low res mod time extracted from file in pak
|
||||
EXPECT_EQ(0, pak->FClose(fPak)); // file closed successfully
|
||||
|
||||
EXPECT_TRUE(pak->ClosePack(testPakPath)); // closed pak successfully
|
||||
EXPECT_EQ(AZ::IO::ResultCode::Success, fileIo->Remove(testPakPath.c_str())); // test pak file deleted successfully
|
||||
|
||||
absDiff = modTimePak >= modTimeDisk ? modTimePak - modTimeDisk : modTimeDisk - modTimePak;
|
||||
// compare mod times. They are allowed to be up to 2 seconds apart but no more
|
||||
EXPECT_LE(absDiff, maxDiff); // FILETIME (disk) and DOSTIME (pak) should be at most 2 seconds apart
|
||||
// note: Do not directly compare the disk time and pack time, the resolution drops the last digit off in some cases in pak
|
||||
// it only has a 2 second resolution. you may compare to make sure that the pak time is WITHIN 2 seconds (as above) but not equal.
|
||||
|
||||
// we depend on the fact that crypak is rounding up, instead of down
|
||||
EXPECT_GE(modTimePak, modTimeDisk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -783,12 +783,6 @@ void CUNIXConsole::KeyEnter()
|
||||
|
||||
if (pushCommand)
|
||||
{
|
||||
CSystem* pSystem = static_cast<CSystem*>(gEnv->pSystem);
|
||||
#if defined(CVARS_WHITELIST)
|
||||
ICVarsWhitelist* pCVarsWhitelist = pSystem->GetCVarsWhiteList();
|
||||
bool execute = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(m_InputLine, false) : true;
|
||||
if (execute)
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
m_CommandQueue.push_back(m_InputLine);
|
||||
}
|
||||
|
||||
@@ -140,147 +140,6 @@ void Command_SetWaitFrames(IConsoleCmdArgs* pCmd)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CNotificationNetworkConsole
|
||||
|
||||
*/
|
||||
|
||||
#include <INotificationNetwork.h>
|
||||
class CNotificationNetworkConsole
|
||||
: public INotificationNetworkListener
|
||||
{
|
||||
private:
|
||||
static const uint32 LENGTH_MAX = 256;
|
||||
static CNotificationNetworkConsole* s_pInstance;
|
||||
|
||||
public:
|
||||
static bool Initialize()
|
||||
{
|
||||
if (s_pInstance)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
INotificationNetwork* pNotificationNetwork = gEnv->pSystem->GetINotificationNetwork();
|
||||
if (!pNotificationNetwork)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
s_pInstance = new CNotificationNetworkConsole();
|
||||
pNotificationNetwork->ListenerBind("Command", s_pInstance);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Shutdown()
|
||||
{
|
||||
if (!s_pInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delete s_pInstance;
|
||||
s_pInstance = NULL;
|
||||
}
|
||||
|
||||
static void Update()
|
||||
{
|
||||
if (s_pInstance)
|
||||
{
|
||||
s_pInstance->ProcessCommand();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CNotificationNetworkConsole()
|
||||
{
|
||||
m_pConsole = NULL;
|
||||
|
||||
m_commandBuffer[0][0] = '\0';
|
||||
m_commandBuffer[1][0] = '\0';
|
||||
m_commandBufferIndex = 0;
|
||||
m_commandCriticalSection = ::CryCreateCriticalSection();
|
||||
}
|
||||
|
||||
~CNotificationNetworkConsole()
|
||||
{
|
||||
if (m_commandCriticalSection)
|
||||
{
|
||||
::CryDeleteCriticalSection(m_commandCriticalSection);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessCommand()
|
||||
{
|
||||
if (!ValidateConsole())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char* command = NULL;
|
||||
::CryEnterCriticalSection(m_commandCriticalSection);
|
||||
if (*m_commandBuffer[m_commandBufferIndex])
|
||||
{
|
||||
command = m_commandBuffer[m_commandBufferIndex];
|
||||
}
|
||||
++m_commandBufferIndex &= 1;
|
||||
::CryLeaveCriticalSection(m_commandCriticalSection);
|
||||
|
||||
if (command)
|
||||
{
|
||||
m_pConsole->ExecuteString(command);
|
||||
*command = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidateConsole()
|
||||
{
|
||||
if (m_pConsole)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!gEnv->pConsole)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pConsole = gEnv->pConsole;
|
||||
return true;
|
||||
}
|
||||
|
||||
// INotificationNetworkListener
|
||||
public:
|
||||
void OnNotificationNetworkReceive(const void* pBuffer, size_t length)
|
||||
{
|
||||
if (!ValidateConsole())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (length > LENGTH_MAX)
|
||||
{
|
||||
length = LENGTH_MAX;
|
||||
}
|
||||
|
||||
::CryEnterCriticalSection(m_commandCriticalSection);
|
||||
::memcpy(m_commandBuffer[m_commandBufferIndex], pBuffer, length);
|
||||
m_commandBuffer[m_commandBufferIndex][LENGTH_MAX - 1] = '\0';
|
||||
::CryLeaveCriticalSection(m_commandCriticalSection);
|
||||
}
|
||||
|
||||
private:
|
||||
IConsole* m_pConsole;
|
||||
|
||||
char m_commandBuffer[2][LENGTH_MAX];
|
||||
size_t m_commandBufferIndex;
|
||||
void* m_commandCriticalSection;
|
||||
};
|
||||
|
||||
CNotificationNetworkConsole* CNotificationNetworkConsole::s_pInstance = NULL;
|
||||
|
||||
void ConsoleShow(IConsoleCmdArgs*)
|
||||
{
|
||||
gEnv->pConsole->ShowConsole(true);
|
||||
@@ -359,8 +218,6 @@ CXConsole::CXConsole()
|
||||
m_waitSeconds = 0.0f;
|
||||
m_blockCounter = 0;
|
||||
|
||||
CNotificationNetworkConsole::Initialize();
|
||||
|
||||
AzFramework::ConsoleRequestBus::Handler::BusConnect();
|
||||
AzFramework::CommandRegistrationBus::Handler::BusConnect();
|
||||
|
||||
@@ -379,8 +236,6 @@ CXConsole::~CXConsole()
|
||||
gEnv->pSystem->GetIRemoteConsole()->UnregisterListener(this);
|
||||
}
|
||||
|
||||
CNotificationNetworkConsole::Shutdown();
|
||||
|
||||
if (!m_mapVariables.empty())
|
||||
{
|
||||
while (!m_mapVariables.empty())
|
||||
@@ -1205,8 +1060,6 @@ void CXConsole::Update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CNotificationNetworkConsole::Update();
|
||||
}
|
||||
|
||||
//enable this for now, we need it for profiling etc
|
||||
@@ -1749,11 +1602,6 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
int devOnlyMask = VF_DEV_ONLY;
|
||||
int dediOnlyMask = VF_DEDI_ONLY;
|
||||
int excludeMask = cheatMask | constMask | readOnlyMask | devOnlyMask | dediOnlyMask;
|
||||
#if defined(CVARS_WHITELIST)
|
||||
CSystem* pSystem = static_cast<CSystem*>(gEnv->pSystem);
|
||||
ICVarsWhitelist* pCVarsWhitelist = pSystem->GetCVarsWhiteList();
|
||||
bool excludeWhitelist = true;
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
if (numArgs > 1)
|
||||
{
|
||||
@@ -1786,13 +1634,6 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
excludeMask &= ~dediOnlyMask;
|
||||
}
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
if (azstricmp(arg, "whitelist") == 0)
|
||||
{
|
||||
excludeWhitelist = false;
|
||||
}
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
--numArgs;
|
||||
}
|
||||
}
|
||||
@@ -1810,11 +1651,6 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
int devOnlyFlags = (command.m_nFlags & devOnlyMask);
|
||||
int dediOnlyFlags = (command.m_nFlags & dediOnlyMask);
|
||||
bool shouldLog = ((cheatFlags | devOnlyFlags | dediOnlyFlags) == 0) || (((cheatFlags | devOnlyFlags | dediOnlyFlags) & ~excludeMask) != 0);
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(command.m_sName, true) : true;
|
||||
shouldLog &= (!whitelisted || (whitelisted & !excludeWhitelist));
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
if (shouldLog)
|
||||
{
|
||||
CryLogAlways("[CVARS]: [COMMAND] %s%s%s%s%s",
|
||||
@@ -1822,11 +1658,7 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
(cheatFlags != 0) ? " [VF_CHEAT]" : "",
|
||||
(devOnlyFlags != 0) ? " [VF_DEV_ONLY]" : "",
|
||||
(dediOnlyFlags != 0) ? " [VF_DEDI_ONLY]" : "",
|
||||
#if defined(CVARS_WHITELIST)
|
||||
(whitelisted == true) ? " [WHITELIST]" : ""
|
||||
#else
|
||||
""
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
);
|
||||
++commandCount;
|
||||
}
|
||||
@@ -1843,11 +1675,6 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
int devOnlyFlags = (flags & devOnlyMask);
|
||||
int dediOnlyFlags = (flags & dediOnlyMask);
|
||||
bool shouldLog = ((cheatFlags | constFlags | readOnlyFlags | devOnlyFlags | dediOnlyFlags) == 0) || (((cheatFlags | constFlags | readOnlyFlags | devOnlyFlags | dediOnlyFlags) & ~excludeMask) != 0);
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(pVariable->GetName(), true) : true;
|
||||
shouldLog &= (!whitelisted || (whitelisted & !excludeWhitelist));
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
|
||||
if (shouldLog)
|
||||
{
|
||||
CryLogAlways("[CVARS]: [VARIABLE] %s%s%s%s%s%s%s",
|
||||
@@ -1857,11 +1684,7 @@ void CXConsole::AuditCVars(IConsoleCmdArgs* pArg)
|
||||
(readOnlyFlags != 0) ? " [VF_READONLY]" : "",
|
||||
(devOnlyFlags != 0) ? " [VF_DEV_ONLY]" : "",
|
||||
(dediOnlyFlags != 0) ? " [VF_DEDI_ONLY]" : "",
|
||||
#if defined(CVARS_WHITELIST)
|
||||
(whitelisted == true) ? " [WHITELIST]" : ""
|
||||
#else
|
||||
""
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
);
|
||||
++cvarCount;
|
||||
}
|
||||
@@ -2520,11 +2343,6 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
|
||||
}
|
||||
}
|
||||
//try to search in command list
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
CSystem* pSystem = static_cast<CSystem*>(gEnv->pSystem);
|
||||
ICVarsWhitelist* pCVarsWhitelist = pSystem->GetCVarsWhiteList();
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
bool bArgumentAutoComplete = false;
|
||||
std::vector<string> matches;
|
||||
|
||||
@@ -2565,10 +2383,6 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
|
||||
string cmd = string(sVar) + " " + pArgumentAutoComplete->GetValue(i);
|
||||
if (_strnicmp(m_sPrevTab.c_str(), cmd.c_str(), m_sPrevTab.length()) == 0)
|
||||
{
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(cmd, true) : true;
|
||||
if (whitelisted)
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
bArgumentAutoComplete = true;
|
||||
matches.push_back(cmd);
|
||||
@@ -2590,10 +2404,6 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
|
||||
{
|
||||
if (_strnicmp(m_sPrevTab.c_str(), itrCmds->first.c_str(), m_sPrevTab.length()) == 0)
|
||||
{
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(itrCmds->first, true) : true;
|
||||
if (whitelisted)
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
matches.push_back((char* const)itrCmds->first.c_str());
|
||||
}
|
||||
@@ -2613,10 +2423,6 @@ const char* CXConsole::ProcessCompletion(const char* szInputBuffer)
|
||||
{//if(itrVars->first.compare(0,m_sPrevTab.length(),m_sPrevTab)==0)
|
||||
if (_strnicmp(m_sPrevTab.c_str(), itrVars->first, m_sPrevTab.length()) == 0)
|
||||
{
|
||||
#if defined(CVARS_WHITELIST)
|
||||
bool whitelisted = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(itrVars->first, true) : true;
|
||||
if (whitelisted)
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
matches.push_back((char* const)itrVars->first);
|
||||
}
|
||||
@@ -2990,12 +2796,6 @@ void CXConsole::ExecuteInputBuffer()
|
||||
|
||||
AddCommandToHistory(sTemp.c_str());
|
||||
|
||||
#if defined(CVARS_WHITELIST)
|
||||
CSystem* pSystem = static_cast<CSystem*>(gEnv->pSystem);
|
||||
ICVarsWhitelist* pCVarsWhitelist = pSystem->GetCVarsWhiteList();
|
||||
bool execute = (pCVarsWhitelist) ? pCVarsWhitelist->IsWhiteListed(sTemp, false) : true;
|
||||
if (execute)
|
||||
#endif // defined(CVARS_WHITELIST)
|
||||
{
|
||||
ExecuteStringInternal(sTemp.c_str(), true); // from console
|
||||
}
|
||||
|
||||
@@ -1809,8 +1809,6 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString,
|
||||
ParseEnd();
|
||||
}
|
||||
|
||||
SYNCHRONOUS_LOADING_TICK();
|
||||
|
||||
delete [] pFileContents;
|
||||
|
||||
return root;
|
||||
|
||||
@@ -19,14 +19,11 @@ set(FILES
|
||||
ConsoleBatchFile.cpp
|
||||
ConsoleHelpGen.cpp
|
||||
CryAsyncMemcpy.cpp
|
||||
DebugCallStack.cpp
|
||||
GeneralMemoryHeap.cpp
|
||||
HandlerBase.cpp
|
||||
IDebugCallStack.cpp
|
||||
AsyncPakManager.cpp
|
||||
Log.cpp
|
||||
SystemRender.cpp
|
||||
NotificationNetwork.cpp
|
||||
PhysRenderer.cpp
|
||||
ResourceManager.cpp
|
||||
ServerHandler.cpp
|
||||
@@ -36,7 +33,6 @@ set(FILES
|
||||
SystemCFG.cpp
|
||||
SystemEventDispatcher.cpp
|
||||
SystemInit.cpp
|
||||
SystemScheduler.cpp
|
||||
SystemWin32.cpp
|
||||
Timer.cpp
|
||||
UnixConsole.cpp
|
||||
@@ -52,7 +48,6 @@ set(FILES
|
||||
ServerHandler.h
|
||||
ServerThrottle.h
|
||||
SyncLock.h
|
||||
SystemScheduler.h
|
||||
UnixConsole.h
|
||||
SystemInit.h
|
||||
XML/ReadWriteXMLSink.h
|
||||
@@ -63,12 +58,8 @@ set(FILES
|
||||
ConsoleBatchFile.h
|
||||
ConsoleHelpGen.h
|
||||
CryWaterMark.h
|
||||
DebugCallStack.h
|
||||
GeneralMemoryHeap.h
|
||||
IDebugCallStack.h
|
||||
IThreadConfigManager.h
|
||||
Log.h
|
||||
NotificationNetwork.h
|
||||
resource.h
|
||||
SimpleStringPool.h
|
||||
CrySystem_precompiled.h
|
||||
@@ -107,24 +98,12 @@ set(FILES
|
||||
XML/WriteXMLSource.cpp
|
||||
ZipFile.h
|
||||
ZipFileFormat_info.h
|
||||
ProfileLogSystem.cpp
|
||||
Sampler.cpp
|
||||
ProfileLogSystem.h
|
||||
Sampler.h
|
||||
LocalizedStringManager.cpp
|
||||
LocalizedStringManager.h
|
||||
CryThreadUtil_win32_thread.h
|
||||
ThreadInfo.cpp
|
||||
ThreadInfo.h
|
||||
ThreadTask.h
|
||||
ThreadTask.cpp
|
||||
ThreadConfigManager.h
|
||||
ThreadConfigManager.cpp
|
||||
SystemThreading.cpp
|
||||
ZLibCompressor.cpp
|
||||
ZLibCompressor.h
|
||||
SoftCode/SoftCodeMgr.cpp
|
||||
SoftCode/SoftCodeMgr.h
|
||||
Huffman.cpp
|
||||
Huffman.h
|
||||
RemoteConsole/RemoteConsole.cpp
|
||||
|
||||
@@ -18,7 +18,5 @@ set(FILES
|
||||
Tests/Test_Localization.cpp
|
||||
Tests/test_Main.cpp
|
||||
Tests/test_MaterialUtils.cpp
|
||||
UnitTests/CryMathTests.cpp
|
||||
UnitTests/CryPakUnitTests.cpp
|
||||
DllMain.cpp
|
||||
)
|
||||
|
||||
@@ -1304,7 +1304,7 @@ namespace AZ
|
||||
// Add all auto loadable non-asset gems to the list of gem modules to load
|
||||
if (!moduleLoadData.m_autoLoad)
|
||||
{
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
for (AZ::OSString& dynamicLibraryPath : moduleLoadData.m_dynamicLibraryPaths)
|
||||
{
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzFramework/IO/RemoteStorageDrive.h>
|
||||
#include <AzFramework/Network/NetBindingComponent.h>
|
||||
#include <AzFramework/Network/NetBindingSystemComponent.h>
|
||||
#include <AzFramework/Physics/Utils.h>
|
||||
#include <AzFramework/Render/GameIntersectorComponent.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
@@ -66,7 +64,6 @@
|
||||
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
|
||||
#include <AzFramework/Viewport/CameraState.h>
|
||||
#include <AzFramework/Driller/RemoteDrillerInterface.h>
|
||||
#include <AzFramework/Network/NetworkContext.h>
|
||||
#include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h>
|
||||
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
|
||||
#include <AzFramework/Viewport/ScreenGeometry.h>
|
||||
@@ -197,7 +194,6 @@ namespace AzFramework
|
||||
|
||||
ApplicationRequests::Bus::Handler::BusConnect();
|
||||
AZ::UserSettingsFileLocatorBus::Handler::BusConnect();
|
||||
NetSystemRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
@@ -207,7 +203,6 @@ namespace AzFramework
|
||||
Stop();
|
||||
}
|
||||
|
||||
NetSystemRequestBus::Handler::BusDisconnect();
|
||||
AZ::UserSettingsFileLocatorBus::Handler::BusDisconnect();
|
||||
ApplicationRequests::Bus::Handler::BusDisconnect();
|
||||
|
||||
@@ -285,13 +280,6 @@ namespace AzFramework
|
||||
|
||||
m_pimpl.reset();
|
||||
|
||||
/* The following line of code is a temporary fix.
|
||||
* GridMate's ReplicaChunkDescriptor is stored in a global environment variable 'm_globalDescriptorTable'
|
||||
* which does not get cleared when Application shuts down. We need to un-reflect here to clear ReplicaChunkDescriptor
|
||||
* so that ReplicaChunkDescriptor::m_vdt doesn't get flooded when we repeatedly instantiate Application in unit tests.
|
||||
*/
|
||||
AZ::ReflectionEnvironment::GetReflectionManager()->RemoveReflectContext<NetworkContext>();
|
||||
|
||||
// Free any memory owned by the command line container.
|
||||
m_commandLine = CommandLine();
|
||||
|
||||
@@ -320,8 +308,6 @@ namespace AzFramework
|
||||
azrtti_typeid<AzFramework::AssetCatalogComponent>(),
|
||||
azrtti_typeid<AzFramework::CustomAssetTypeComponent>(),
|
||||
azrtti_typeid<AzFramework::FileTag::ExcludeFileComponent>(),
|
||||
azrtti_typeid<AzFramework::NetBindingComponent>(),
|
||||
azrtti_typeid<AzFramework::NetBindingSystemComponent>(),
|
||||
azrtti_typeid<AzFramework::TransformComponent>(),
|
||||
azrtti_typeid<AzFramework::SceneSystemComponent>(),
|
||||
azrtti_typeid<AzFramework::AzFrameworkConfigurationSystemComponent>(),
|
||||
@@ -457,9 +443,6 @@ namespace AzFramework
|
||||
void Application::CreateReflectionManager()
|
||||
{
|
||||
ComponentApplication::CreateReflectionManager();
|
||||
|
||||
// Setup NetworkContext
|
||||
AZ::ReflectionEnvironment::GetReflectionManager()->AddReflectContext<NetworkContext>();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -479,19 +462,6 @@ namespace AzFramework
|
||||
return uuid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
NetworkContext* Application::GetNetworkContext()
|
||||
{
|
||||
NetworkContext* result = nullptr;
|
||||
|
||||
if (auto reflectionManager = AZ::ReflectionEnvironment::GetReflectionManager())
|
||||
{
|
||||
result = reflectionManager->GetReflectContext<NetworkContext>();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Application::ResolveEnginePath(AZStd::string& engineRelativePath) const
|
||||
{
|
||||
AZ::IO::FixedMaxPath fullPath = m_engineRoot / engineRelativePath;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
#include <AzFramework/Network/NetSystemBus.h>
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
|
||||
@@ -49,7 +48,6 @@ namespace AzFramework
|
||||
: public AZ::ComponentApplication
|
||||
, public AZ::UserSettingsFileLocatorBus::Handler
|
||||
, public ApplicationRequests::Bus::Handler
|
||||
, public NetSystemRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
// Base class for platform specific implementations of the application.
|
||||
@@ -138,11 +136,6 @@ namespace AzFramework
|
||||
// Convenience function that should be called instead of the standard exit() function to ensure platform requirements are met.
|
||||
static void Exit(int errorCode) { ApplicationRequests::Bus::Broadcast(&ApplicationRequests::TerminateOnError, errorCode); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! NetSystemEventBus::Handler
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
NetworkContext* GetNetworkContext() override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include <AzFramework/Entity/GameEntityContextComponent.h>
|
||||
#include <AzFramework/FileTag/FileTagComponent.h>
|
||||
#include <AzFramework/Input/System/InputSystemComponent.h>
|
||||
#include <AzFramework/Network/NetBindingComponent.h>
|
||||
#include <AzFramework/Network/NetBindingSystemComponent.h>
|
||||
#include <AzFramework/Render/GameIntersectorComponent.h>
|
||||
#include <AzFramework/Scene/SceneSystemComponent.h>
|
||||
#include <AzFramework/Script/ScriptComponent.h>
|
||||
@@ -42,8 +40,6 @@ namespace AzFramework
|
||||
AzFramework::AssetCatalogComponent::CreateDescriptor(),
|
||||
AzFramework::CustomAssetTypeComponent::CreateDescriptor(),
|
||||
AzFramework::FileTag::ExcludeFileComponent::CreateDescriptor(),
|
||||
AzFramework::NetBindingComponent::CreateDescriptor(),
|
||||
AzFramework::NetBindingSystemComponent::CreateDescriptor(),
|
||||
AzFramework::TransformComponent::CreateDescriptor(),
|
||||
AzFramework::NonUniformScaleComponent::CreateDescriptor(),
|
||||
AzFramework::GameEntityContextComponent::CreateDescriptor(),
|
||||
|
||||
@@ -878,15 +878,15 @@ namespace AzFramework
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<TransformComponent, AZ::Component, NetBindable>()
|
||||
serializeContext->ClassDeprecate("NetBindable", "{80206665-D429-4703-B42E-94434F82F381}");
|
||||
|
||||
serializeContext->Class<TransformComponent, AZ::Component>()
|
||||
->Version(4, &TransformComponentVersionConverter)
|
||||
->Field("Parent", &TransformComponent::m_parentId)
|
||||
->Field("Transform", &TransformComponent::m_worldTM)
|
||||
->Field("LocalTransform", &TransformComponent::m_localTM)
|
||||
->Field("ParentActivationTransformMode", &TransformComponent::m_parentActivationTransformMode)
|
||||
->Field("IsStatic", &TransformComponent::m_isStatic)
|
||||
->Field("InterpolatePosition", &TransformComponent::m_interpolatePosition)
|
||||
->Field("InterpolateRotation", &TransformComponent::m_interpolateRotation)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <AzCore/Component/EntityBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzFramework/Network/NetBindable.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -41,10 +40,9 @@ namespace AzFramework
|
||||
, public AZ::TransformBus::Handler
|
||||
, public AZ::TransformNotificationBus::Handler
|
||||
, private AZ::TransformHierarchyInformationBus::Handler
|
||||
, public NetBindable
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(TransformComponent, AZ::TransformComponentTypeId, NetBindable, AZ::TransformInterface);
|
||||
AZ_COMPONENT(TransformComponent, AZ::TransformComponentTypeId, AZ::TransformInterface);
|
||||
|
||||
friend class AzToolsFramework::Components::TransformComponent;
|
||||
|
||||
@@ -218,11 +216,5 @@ namespace AzFramework
|
||||
bool m_parentActive = false; ///< Keeps track of the state of the parent entity.
|
||||
bool m_onNewParentKeepWorldTM = true; ///< If set, recompute localTM instead of worldTM when parent becomes active.
|
||||
bool m_isStatic = false; ///< If true, the transform is static and doesn't move while entity is active.
|
||||
|
||||
//! @deprecated
|
||||
//! @{
|
||||
AZ::InterpolationMode m_interpolatePosition = AZ::InterpolationMode::NoInterpolation;
|
||||
AZ::InterpolationMode m_interpolateRotation = AZ::InterpolationMode::NoInterpolation;
|
||||
//! @}
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef AZFRAMEWORK_NETWORK_DYNAMICSERIALIZABLEFIELDMARSHALER_H
|
||||
#define AZFRAMEWORK_NETWORK_DYNAMICSERIALIZABLEFIELDMARSHALER_H
|
||||
|
||||
#include <AzCore/IO/ByteContainerStream.h>
|
||||
#include <AzCore/IO/GenericStreams.h>
|
||||
#include <AzCore/Math/Uuid.h>
|
||||
#include <AzCore/Serialization/DynamicSerializableField.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
|
||||
#include <GridMate/Serialize/Buffer.h>
|
||||
#include <GridMate/Serialize/MathMarshal.h>
|
||||
#include <GridMate/Serialize/UuidMarshal.h>
|
||||
|
||||
namespace GridMate
|
||||
{
|
||||
/**
|
||||
* Marshaler for DynamicSerializableField, contains a template param for allocating the memory buffer that it's going to use to write to.
|
||||
*/
|
||||
template<size_t BufferSize>
|
||||
class DynamicSerializableFieldMarshaler
|
||||
{
|
||||
public:
|
||||
DynamicSerializableFieldMarshaler()
|
||||
: m_serializeContext(nullptr)
|
||||
{
|
||||
EBUS_EVENT_RESULT(m_serializeContext, AZ::ComponentApplicationBus, GetSerializeContext);
|
||||
}
|
||||
|
||||
// Mainly here for unit test purposes.
|
||||
DynamicSerializableFieldMarshaler(AZ::SerializeContext* context)
|
||||
: m_serializeContext(context)
|
||||
{
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE void Marshal(WriteBuffer& wb, const AZ::DynamicSerializableField& value) const
|
||||
{
|
||||
AZ_Error("DynamicSerializableFieldMarshaler", m_serializeContext, "Unknown SerializationContext. Aborting Marshal attempt.\n");
|
||||
if (m_serializeContext)
|
||||
{
|
||||
Marshaler<AZ::u32> sizeMarshaler;
|
||||
Marshaler<AZ::Uuid> uuidMarshaler;
|
||||
|
||||
AZStd::vector<AZ::u8> memoryBuffer(BufferSize);
|
||||
|
||||
// Start buffer in write mode.
|
||||
AZ::IO::ByteContainerStream<decltype(memoryBuffer)> memoryStream(&memoryBuffer);
|
||||
|
||||
AZ::u32 bufferSize = 0;
|
||||
|
||||
if (m_serializeContext->FindClassData(value.m_typeId))
|
||||
{
|
||||
if (AZ::Utils::SaveObjectToStream(memoryStream, AZ::DataStream::StreamType::ST_BINARY, value.m_data, value.m_typeId, m_serializeContext))
|
||||
{
|
||||
bufferSize = static_cast<AZ::u32>(memoryStream.GetCurPos());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("DynamicSerializableFieldMarshaler", !value.IsValid(), "Could not save object to stream because type Id %s is not registered with the serializer.\n", value.m_typeId.ToString<AZStd::string>().c_str());
|
||||
}
|
||||
|
||||
sizeMarshaler.Marshal(wb, bufferSize);
|
||||
uuidMarshaler.Marshal(wb, value.m_typeId);
|
||||
wb.WriteRaw(memoryBuffer.data(), bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
AZ_FORCE_INLINE void Unmarshal(AZ::DynamicSerializableField& value, ReadBuffer& rb) const
|
||||
{
|
||||
value.DestroyData(m_serializeContext);
|
||||
|
||||
AZ_Error("DynamicSerializableFieldMarshaler", m_serializeContext, "Unknown SerializationContext. Aborting Unmarshal attempt.\n");
|
||||
if (m_serializeContext)
|
||||
{
|
||||
Marshaler<AZ::u32> sizeMarshaler;
|
||||
AZ::u32 marshaledBufferSize = 0;
|
||||
sizeMarshaler.Unmarshal(marshaledBufferSize, rb);
|
||||
|
||||
AZ_Assert(marshaledBufferSize <= BufferSize,"Trying to deserialize too much data for the allocated buffer size\n");
|
||||
|
||||
// Marshal out the TypeId so I can use it on the receiving end.
|
||||
Marshaler<AZ::Uuid> uuidMarshaler;
|
||||
uuidMarshaler.Unmarshal(value.m_typeId, rb);
|
||||
|
||||
if (marshaledBufferSize > 0)
|
||||
{
|
||||
// See if there's some nice way to use this.
|
||||
// - Can't make this a member variable, since both these methods are const.
|
||||
AZStd::vector<AZ::u8> memoryBuffer(marshaledBufferSize + 1);
|
||||
|
||||
if (rb.ReadRaw(memoryBuffer.data(), marshaledBufferSize))
|
||||
{
|
||||
// Start buffer in read mode.
|
||||
AZ::IO::ByteContainerStream<decltype(memoryBuffer)> memoryStream(&memoryBuffer);
|
||||
|
||||
// we'll use a strict filter here, one that doesn't allow deserialization to automatically start loading assets, nor tolerates errors.
|
||||
// this is becuase this is coming from a network interface and should always be error-free.
|
||||
AZ::ObjectStream::FilterDescriptor filterToUse(&AZ::Data::AssetFilterNoAssetLoading, AZ::ObjectStream::FILTERFLAG_STRICT);
|
||||
value.m_data = AZ::Utils::LoadObjectFromStream(memoryStream, m_serializeContext, &value.m_typeId, filterToUse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::SerializeContext* m_serializeContext;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialized marshaler for AZ::DynamicSerializableField
|
||||
* Mainly here to hook into the DataSet Marshaler auto detection logic, and provide a default buffer size for the actual marshaler
|
||||
*/
|
||||
template<>
|
||||
class Marshaler<AZ::DynamicSerializableField>
|
||||
: public DynamicSerializableFieldMarshaler<1024>
|
||||
{
|
||||
public:
|
||||
|
||||
Marshaler()
|
||||
{
|
||||
}
|
||||
|
||||
// Mainly here for unit test purposes.
|
||||
Marshaler(AZ::SerializeContext* context)
|
||||
: DynamicSerializableFieldMarshaler(context)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user