mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-04-22 09:40:46 +00:00
Merge remote-tracking branch 'SRSaunders/hud-vulkan-macos'
This commit is contained in:
commit
436144f6e1
22 changed files with 469 additions and 99 deletions
|
@ -510,7 +510,7 @@ Recommended in this case is `cmake-vs2022-win64-no-ffmpeg.bat`
|
|||
|
||||
Xcode release and universal builds now automatically package the executable into a macOS app bundle, defining an Info.plist file and copying the base directory and custom icon into the application bundle's Contents/Resources folder. This is controlled by adding -DMACOSX_BUNDLE=ON to the CMake options.
|
||||
|
||||
Depending on which package manager you install (Homebrew or MacPorts) you may need to change the openal-soft library and include paths specified in the cmake shell scripts. For single architecture builds (debug, release, retail) the default openal-soft paths are set for Homebrew on x86, while for universal builds the default paths are set for MacPorts on x86 or Apple Silicon. If you want to build using the single architecture shell scripts (debug, release, retail) on Apple Silicon, you will need to change the openal-soft paths from `/usr/local/...` to either `/opt/homebrew/...` (Homebrew) or `/opt/local/...` (MacPorts).
|
||||
For single architecture builds (debug, release, retail) the default openal-soft paths are set for Homebrew, while for universal builds the default paths are set for MacPorts. The single architecture build scripts are now portable and automatically detect Homebrew's openal-soft path prefix for x86 and Apple Silicon. The universal build script remains portable since MacPorts uses the same openal-soft installation path on x86 and Apple Silicon.
|
||||
|
||||
4. Compile RBDOOM-3-BFG targets:
|
||||
|
||||
|
|
|
@ -429,6 +429,8 @@ if(USE_VULKAN)
|
|||
if(USE_VMA)
|
||||
add_definitions(-DUSE_AMD_ALLOCATOR)
|
||||
include_directories("libs/vma/include")
|
||||
file(GLOB VMA_INCLUDES libs/vma/include/*.h)
|
||||
source_group("libs\\vma" FILES ${VMA_INCLUDES})
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
@ -1304,6 +1306,7 @@ set(RBDOOM3_INCLUDES
|
|||
#${FREETYPE_SOURCES}
|
||||
${SOUND_INCLUDES}
|
||||
${OGGVORBIS_INCLUDES}
|
||||
${VMA_INCLUDES}
|
||||
${OPTICK_INCLUDES}
|
||||
${UI_INCLUDES}
|
||||
${SWF_INCLUDES}
|
||||
|
@ -1776,7 +1779,8 @@ else()
|
|||
# delete precompiled header file after executable is compiled: IDE build case (e.g. Xcode)
|
||||
else()
|
||||
add_custom_command(TARGET RBDoom3BFG POST_BUILD
|
||||
COMMAND ${remove_command} "idlib/precompiled.h.gch"
|
||||
# SRS - added wildcards to remove tmp files from cmake ZERO_CHECK regeneration
|
||||
COMMAND ${remove_command} "idlib/precompiled.h*.gch*"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "remove idlib/precompiled.h.gch"
|
||||
)
|
||||
|
|
|
@ -2,5 +2,16 @@ cd ..
|
|||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# asemarafa/SRS - Determine the Homebrew path prefix for openal-soft
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
OPENAL_PREFIX=$(brew --prefix openal-soft 2>/dev/null)
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
echo "Error: openal-soft is not installed via Homebrew."
|
||||
echo "Either install it using 'brew install openal-soft' or define the path prefix via OPENAL_PREFIX."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# change or remove -DCMAKE_OSX_DEPLOYMENT_TARGET=<version> to match supported runtime targets
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=$OPENAL_PREFIX/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=$OPENAL_PREFIX/include ../neo -Wno-dev
|
||||
|
|
|
@ -2,5 +2,16 @@ cd ..
|
|||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# asemarafa/SRS - Determine the Homebrew path prefix for openal-soft
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
OPENAL_PREFIX=$(brew --prefix openal-soft 2>/dev/null)
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
echo "Error: openal-soft is not installed via Homebrew."
|
||||
echo "Either install it using 'brew install openal-soft' or define the path prefix via OPENAL_PREFIX."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# change or remove -DCMAKE_OSX_DEPLOYMENT_TARGET=<version> to match supported runtime targets
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG -DID_RETAIL" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG -DID_RETAIL" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=$OPENAL_PREFIX/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=$OPENAL_PREFIX/include ../neo -Wno-dev
|
||||
|
|
|
@ -2,10 +2,22 @@ cd ..
|
|||
rm -rf xcode-debug
|
||||
mkdir xcode-debug
|
||||
cd xcode-debug
|
||||
|
||||
# asemarafa/SRS - Determine the Homebrew path prefix for openal-soft
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
OPENAL_PREFIX=$(brew --prefix openal-soft 2>/dev/null)
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
echo "Error: openal-soft is not installed via Homebrew."
|
||||
echo "Either install it using 'brew install openal-soft' or define the path prefix via OPENAL_PREFIX."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# note 1: remove or set -DCMAKE_SUPPRESS_REGENERATION=OFF to reenable ZERO_CHECK target which checks for CMakeLists.txt changes and re-runs CMake before builds
|
||||
# however, if ZERO_CHECK is reenabled **must** add VULKAN_SDK location to Xcode Custom Paths (under Prefs/Locations) otherwise build failures may occur
|
||||
# note 2: policy CMAKE_POLICY_DEFAULT_CMP0142=NEW suppresses non-existant per-config suffixes on Xcode library search paths, works for cmake version 3.25 and later
|
||||
# note 3: env variable MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1 enables MoltenVK's image view swizzle which may be required on older macOS versions or hardware (see vulkaninfo)
|
||||
# note 4: env variable MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=0 disables synchronous queue submits which is optimal for the synchronization method used by the game
|
||||
# note 5: env variable MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2 enables MoltenVK's use of Metal argument buffers only if VK_EXT_descriptor_indexing is enabled
|
||||
cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENVIRONMENT="MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1;MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=0;MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2" -DCMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION=OFF -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev
|
||||
# note 3: env variable MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1 enables MoltenVK's image view swizzle which may be required on older macOS versions or hardware (see vulkaninfo) - only used for VulkanSDK < 1.3.275
|
||||
# note 4: env variable MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=0 disables synchronous queue submits which is optimal for the synchronization method used by the game - only used for VulkanSDK < 1.3.275
|
||||
# note 5: env variable MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2 enables MoltenVK's use of Metal argument buffers only if VK_EXT_descriptor_indexing is enabled - only used for VulkanSDK < 1.3.275
|
||||
# note 6: env variable MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA=1.0 disables MoltenVK's timestampPeriod lowpass filter for non-Apple GPUs - only used for VulkanSDK < 1.3.275
|
||||
cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENVIRONMENT="MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1;MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=0;MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2;MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA=1.0" -DCMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION=OFF -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=$OPENAL_PREFIX/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=$OPENAL_PREFIX/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev
|
||||
|
|
|
@ -2,7 +2,18 @@ cd ..
|
|||
rm -rf xcode-release
|
||||
mkdir xcode-release
|
||||
cd xcode-release
|
||||
|
||||
# asemarafa/SRS - Determine the Homebrew path prefix for openal-soft
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
OPENAL_PREFIX=$(brew --prefix openal-soft 2>/dev/null)
|
||||
if [ -z "$OPENAL_PREFIX" ]; then
|
||||
echo "Error: openal-soft is not installed via Homebrew."
|
||||
echo "Either install it using 'brew install openal-soft' or define the path prefix via OPENAL_PREFIX."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# note 1: remove or set -DCMAKE_SUPPRESS_REGENERATION=OFF to reenable ZERO_CHECK target which checks for CMakeLists.txt changes and re-runs CMake before builds
|
||||
# however, if ZERO_CHECK is reenabled **must** add VULKAN_SDK location to Xcode Custom Paths (under Prefs/Locations) otherwise build failures may occur
|
||||
# note 2: policy CMAKE_POLICY_DEFAULT_CMP0142=NEW suppresses non-existant per-config suffixes on Xcode library search paths, works for cmake version 3.25 and later
|
||||
cmake -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_CONFIGURATION_TYPES="Release;MinSizeRel;RelWithDebInfo" -DMACOSX_BUNDLE=ON -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION=OFF -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev
|
||||
cmake -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_CONFIGURATION_TYPES="Release;MinSizeRel;RelWithDebInfo" -DMACOSX_BUNDLE=ON -DFFMPEG=OFF -DBINKDEC=ON -DUSE_MoltenVK=ON -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION=OFF -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=$OPENAL_PREFIX/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=$OPENAL_PREFIX/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev
|
||||
|
|
|
@ -2,6 +2,15 @@ cd ..
|
|||
rm -rf xcode-universal
|
||||
mkdir xcode-universal
|
||||
cd xcode-universal
|
||||
|
||||
# SRS - Determine if openal-soft universal variant is installed via MacPorts
|
||||
OPENAL_VARIANTS=$(port info --variants openal-soft 2>/dev/null)
|
||||
if [[ $OPENAL_VARIANTS != *universal* ]]; then
|
||||
echo "Error: openal-soft universal variant is not installed via MacPorts."
|
||||
echo "Please install it using 'sudo port install openal-soft +universal'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# note 1: remove or set -DCMAKE_SUPPRESS_REGENERATION=OFF to reenable ZERO_CHECK target which checks for CMakeLists.txt changes and re-runs CMake before builds
|
||||
# however, if ZERO_CHECK is reenabled **must** add VULKAN_SDK location to Xcode Custom Paths (under Prefs/Locations) otherwise build failures may occur
|
||||
# note 2: policy CMAKE_POLICY_DEFAULT_CMP0142=NEW suppresses non-existant per-config suffixes on Xcode library search paths, works for cmake version 3.25 and later
|
||||
|
|
|
@ -315,6 +315,7 @@ void idCommonLocal::TimeRenderDemo( const char* demoName, bool twice, bool quit
|
|||
while( readDemo )
|
||||
{
|
||||
BusyWait(); // SRS - BusyWait() calls UpdateScreen() which draws and renders out-of-sequence but still supports frame timing
|
||||
commonLocal.frameTiming.finishSyncTime_EndFrame = Sys_Microseconds();
|
||||
commonLocal.mainFrameTiming = commonLocal.frameTiming;
|
||||
// ** End of current logical frame **
|
||||
|
||||
|
|
|
@ -380,14 +380,26 @@ public:
|
|||
// RB end
|
||||
|
||||
// SRS start
|
||||
uint64 GetRendererStartFrameSyncMicroseconds() const
|
||||
void SetRendererMvkEncodeMicroseconds( uint64 mvkEncodeMicroSeconds )
|
||||
{
|
||||
return mainFrameTiming.finishSyncTime - mainFrameTiming.startSyncTime;
|
||||
metal_encode = mvkEncodeMicroSeconds;
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 GetRendererEndFrameSyncMicroseconds() const
|
||||
uint64 GetRendererMvkEncodeMicroseconds() const
|
||||
{
|
||||
return mainFrameTiming.finishSyncTime_EndFrame - mainFrameTiming.startRenderTime;
|
||||
return metal_encode;
|
||||
}
|
||||
|
||||
void SetRendererGpuMemoryMB( int gpuMemoryMB )
|
||||
{
|
||||
gpu_memory = gpuMemoryMB;
|
||||
return;
|
||||
}
|
||||
|
||||
int GetRendererGpuMemoryMB() const
|
||||
{
|
||||
return gpu_memory;
|
||||
}
|
||||
// SRS end
|
||||
|
||||
|
@ -604,6 +616,11 @@ private:
|
|||
backEndCounters_t stats_backend;
|
||||
performanceCounters_t stats_frontend;
|
||||
|
||||
// SRS - MoltenVK's Vulkan to Metal command buffer encoding time, set default to 0 for non-macOS platforms (Windows and Linux)
|
||||
uint64 metal_encode = 0;
|
||||
// SRS - Cross-platform GPU Memory usage counter, set default to 0 in case platform or graphics API does not support queries
|
||||
int gpu_memory = 0;
|
||||
|
||||
// Used during loading screens
|
||||
int lastPacifierSessionTime;
|
||||
int lastPacifierGuiTime;
|
||||
|
|
|
@ -225,8 +225,10 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
extern idCVar r_swapInterval;
|
||||
|
||||
static float previousTimes[FPS_FRAMES];
|
||||
static float previousCpuUsage[FPS_FRAMES] = {};
|
||||
static float previousGpuUsage[FPS_FRAMES] = {};
|
||||
static float previousTimesNormalized[FPS_FRAMES_HISTORY];
|
||||
static int index;
|
||||
static int index = 0;
|
||||
static int previous;
|
||||
static int valuesOffset = 0;
|
||||
|
||||
|
@ -239,6 +241,8 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
previous = t;
|
||||
|
||||
int fps = 0;
|
||||
float cpuUsage = 0.0;
|
||||
float gpuUsage = 0.0;
|
||||
|
||||
const float milliSecondsPerFrame = 1000.0f / com_engineHz_latched;
|
||||
|
||||
|
@ -253,6 +257,8 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
for( int i = 0 ; i < FPS_FRAMES ; i++ )
|
||||
{
|
||||
total += previousTimes[i];
|
||||
cpuUsage += previousCpuUsage[i];
|
||||
gpuUsage += previousGpuUsage[i];
|
||||
}
|
||||
if( !total )
|
||||
{
|
||||
|
@ -260,6 +266,8 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
}
|
||||
fps = 1000000 * FPS_FRAMES / total;
|
||||
fps = ( fps + 500 ) / 1000;
|
||||
cpuUsage /= FPS_FRAMES;
|
||||
gpuUsage /= FPS_FRAMES;
|
||||
|
||||
const char* s = va( "%ifps", fps );
|
||||
int w = strlen( s ) * BIGCHAR_WIDTH;
|
||||
|
@ -309,12 +317,26 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
const int64 frameIdleTime = int64( commonLocal.mainFrameTiming.startGameTime ) - int64( commonLocal.mainFrameTiming.finishSyncTime );
|
||||
const int64 frameBusyTime = int64( commonLocal.frameTiming.finishSyncTime ) - int64( commonLocal.mainFrameTiming.startGameTime );
|
||||
|
||||
// SRS - Frame sync time represents swap buffer synchronization + game thread wait + other time spent outside of rendering
|
||||
const int64 frameSyncTime = int64( commonLocal.frameTiming.finishSyncTime ) - int64( commonLocal.mainFrameTiming.startRenderTime ) - int64( rendererBackEndTime );
|
||||
// SRS - Frame sync time represents swap buffer synchronization + other frame time spent outside of game thread and renderer backend
|
||||
const int64 gameThreadWaitTime = int64( commonLocal.mainFrameTiming.finishSyncTime_EndFrame ) - int64( commonLocal.mainFrameTiming.finishRenderTime );
|
||||
const int64 frameSyncTime = int64( commonLocal.frameTiming.finishSyncTime ) - int64( commonLocal.mainFrameTiming.startRenderTime + rendererBackEndTime ) - gameThreadWaitTime;
|
||||
|
||||
// SRS - GPU idle time is simply the difference between measured frame-over-frame time and GPU busy time (directly from GPU timers)
|
||||
const int64 rendererGPUIdleTime = frameBusyTime + frameIdleTime - rendererGPUTime;
|
||||
|
||||
// SRS - Estimate CPU busy time measured from start of game thread until completion of game thread and renderer backend (including excess MoltenVK encoding time if applicable)
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
const int64 rendererMvkEncodeTime = commonLocal.GetRendererMvkEncodeMicroseconds();
|
||||
const int64 rendererQueueSubmitTime = int64( commonLocal.mainFrameTiming.finishRenderTime - commonLocal.mainFrameTiming.startRenderTime ) - int64( rendererBackEndTime );
|
||||
const int64 rendererCPUBusyTime = int64( commonLocal.mainFrameTiming.finishSyncTime_EndFrame - commonLocal.mainFrameTiming.startGameTime ) + Min( Max( int64( 0 ), rendererMvkEncodeTime - rendererQueueSubmitTime - gameThreadWaitTime ), frameSyncTime - rendererQueueSubmitTime );
|
||||
#else
|
||||
const int64 rendererCPUBusyTime = int64( commonLocal.mainFrameTiming.finishSyncTime_EndFrame - commonLocal.mainFrameTiming.startGameTime );
|
||||
#endif
|
||||
|
||||
// SRS - Save current CPU and GPU usage factors in ring buffer to calculate smoothed averages for future frames
|
||||
previousCpuUsage[(index - 1) % FPS_FRAMES] = float( rendererCPUBusyTime ) / float( frameBusyTime + frameIdleTime ) * 100.0;
|
||||
previousGpuUsage[(index - 1) % FPS_FRAMES] = float( rendererGPUTime ) / float( rendererGPUTime + rendererGPUIdleTime ) * 100.0;
|
||||
|
||||
#if 1
|
||||
|
||||
// RB: use ImGui to show more detailed stats about the scene loads
|
||||
|
@ -322,7 +344,7 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
{
|
||||
// start smaller
|
||||
int32 statsWindowWidth = 320;
|
||||
int32 statsWindowHeight = 315;
|
||||
int32 statsWindowHeight = 330;
|
||||
|
||||
if( com_showFPS.GetInteger() > 2 )
|
||||
{
|
||||
|
@ -427,7 +449,7 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
|
||||
ImGui::TextColored( colorCyan, "API: %s, AA[%i, %i]: %s, %s", API, width, height, aaMode, resolutionText.c_str() );
|
||||
|
||||
ImGui::TextColored( colorGold, "Device: %s", deviceManager->GetRendererString() );
|
||||
ImGui::TextColored( colorGold, "Device: %s, Memory: %i MB", deviceManager->GetRendererString(), commonLocal.GetRendererGpuMemoryMB() );
|
||||
|
||||
ImGui::TextColored( colorLtGrey, "GENERAL: views:%i draws:%i tris:%i",
|
||||
commonLocal.stats_frontend.c_numViews,
|
||||
|
@ -477,7 +499,7 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
|
||||
if( com_showFPS.GetInteger() > 2 )
|
||||
{
|
||||
const char* overlay = va( "Average FPS %i", fps );
|
||||
const char* overlay = va( "Average FPS %-4i", fps );
|
||||
|
||||
ImGui::PlotLines( "Relative\nFrametime ms", previousTimesNormalized, FPS_FRAMES_HISTORY, valuesOffset, overlay, -10.0f, 10.0f, ImVec2( 0, 50 ) );
|
||||
}
|
||||
|
@ -494,12 +516,20 @@ float idConsoleLocal::DrawFPS( float y )
|
|||
ImGui::TextColored( gameThreadRenderTime > maxTime ? colorRed : colorWhite, "RF: %5llu us SSR: %5llu us", gameThreadRenderTime, rendererGPU_SSRTime );
|
||||
ImGui::TextColored( rendererBackEndTime > maxTime ? colorRed : colorWhite, "RB: %5llu us Ambient Pass: %5llu us", rendererBackEndTime, rendererGPUAmbientPassTime );
|
||||
ImGui::TextColored( rendererGPUShadowAtlasTime > maxTime ? colorRed : colorWhite, "Shadows: %5llu us Shadow Atlas: %5llu us", rendererShadowsTime, rendererGPUShadowAtlasTime );
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
// SRS - For more recent versions of MoltenVK with enhanced performance statistics (v1.2.6 and later), display the Vulkan to Metal encoding thread time on macOS
|
||||
ImGui::TextColored( rendererMvkEncodeTime > maxTime || rendererGPUInteractionsTime > maxTime ? colorRed : colorWhite, "Encode: %5lld us Interactions: %5llu us", rendererMvkEncodeTime, rendererGPUInteractionsTime );
|
||||
ImGui::TextColored( rendererGPUShaderPassesTime > maxTime ? colorRed : colorWhite, "Sync: %5lld us Shader Pass: %5llu us", frameSyncTime, rendererGPUShaderPassesTime );
|
||||
#else
|
||||
ImGui::TextColored( rendererGPUInteractionsTime > maxTime ? colorRed : colorWhite, "Sync: %5lld us Interactions: %5llu us", frameSyncTime, rendererGPUInteractionsTime );
|
||||
ImGui::TextColored( rendererGPUShaderPassesTime > maxTime ? colorRed : colorWhite, " Shader Pass: %5llu us", rendererGPUShaderPassesTime );
|
||||
#endif
|
||||
ImGui::TextColored( rendererGPU_TAATime > maxTime ? colorRed : colorWhite, " TAA: %5llu us", rendererGPU_TAATime );
|
||||
ImGui::TextColored( rendererGPUPostProcessingTime > maxTime ? colorRed : colorWhite, " PostFX: %5llu us", rendererGPUPostProcessingTime );
|
||||
ImGui::TextColored( frameBusyTime > maxTime || rendererGPUTime > maxTime ? colorRed : colorWhite, "Total: %5lld us Total: %5lld us", frameBusyTime, rendererGPUTime );
|
||||
ImGui::TextColored( colorWhite, "Idle: %5lld us Idle: %5lld us", frameIdleTime, rendererGPUIdleTime );
|
||||
// SRS - Show CPU and GPU overall usage statistics
|
||||
ImGui::TextColored( colorWhite, "Usage: %3.0f %% Usage: %3.0f %%", cpuUsage, gpuUsage );
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -882,13 +882,13 @@ void idCommonLocal::Frame()
|
|||
}
|
||||
frameTiming.finishRenderTime = Sys_Microseconds();
|
||||
|
||||
// SRS - Use finishSyncTime_EndFrame to record timing just before gameThread.WaitForThread() for com_smp = 1
|
||||
frameTiming.finishSyncTime_EndFrame = Sys_Microseconds();
|
||||
|
||||
// make sure the game / draw thread has completed
|
||||
// This may block if the game is taking longer than the render back end
|
||||
gameThread.WaitForThread();
|
||||
|
||||
// SRS - Use finishSyncTime_EndFrame to record timing just after gameThread.WaitForThread()
|
||||
frameTiming.finishSyncTime_EndFrame = Sys_Microseconds();
|
||||
|
||||
// Send local usermds to the server.
|
||||
// This happens after the game frame has run so that prediction data is up to date.
|
||||
SendUsercmds( Game()->GetLocalClientNum() );
|
||||
|
|
|
@ -70,5 +70,11 @@
|
|||
#else
|
||||
#define OPTICK_ENABLE_GPU_VULKAN (OPTICK_ENABLE_GPU /*&& 0*/)
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Vulkan Functions
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(OPTICK_STATIC_VULKAN_FUNCTIONS)
|
||||
#define OPTICK_STATIC_VULKAN_FUNCTIONS (0 /*1*/)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
|
||||
// Vulkan Forward Declarations
|
||||
#define OPTICK_DEFINE_HANDLE(object) typedef struct object##_T *object;
|
||||
OPTICK_DEFINE_HANDLE(VkInstance);
|
||||
OPTICK_DEFINE_HANDLE(VkDevice);
|
||||
OPTICK_DEFINE_HANDLE(VkPhysicalDevice);
|
||||
OPTICK_DEFINE_HANDLE(VkQueue);
|
||||
|
@ -125,6 +126,7 @@ struct VkCommandBufferBeginInfo;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
typedef void* (VKAPI_PTR *PFN_vkGetInstanceProcAddr_)(VkInstance instance, const char* pName);
|
||||
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties_)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
|
||||
typedef int32_t (VKAPI_PTR *PFN_vkCreateQueryPool_)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
|
||||
typedef int32_t (VKAPI_PTR *PFN_vkCreateCommandPool_)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
|
||||
|
@ -165,6 +167,7 @@ namespace Optick
|
|||
{
|
||||
struct OPTICK_API VulkanFunctions
|
||||
{
|
||||
PFN_vkGetInstanceProcAddr_ vkGetInstanceProcAddr;
|
||||
PFN_vkGetPhysicalDeviceProperties_ vkGetPhysicalDeviceProperties;
|
||||
PFN_vkCreateQueryPool_ vkCreateQueryPool;
|
||||
PFN_vkCreateCommandPool_ vkCreateCommandPool;
|
||||
|
@ -778,7 +781,7 @@ struct OPTICK_API GPUContext
|
|||
};
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
OPTICK_API void InitGpuD3D12(ID3D12Device* device, ID3D12CommandQueue** cmdQueues, uint32_t numQueues);
|
||||
OPTICK_API void InitGpuVulkan(VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions);
|
||||
OPTICK_API void InitGpuVulkan(VkInstance vkInstance, VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions);
|
||||
OPTICK_API void GpuFlip(void* swapChain, uint32_t frameID = 0);
|
||||
OPTICK_API GPUContext SetGpuContext(GPUContext context);
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1046,7 +1049,7 @@ struct OptickApp
|
|||
|
||||
// GPU events
|
||||
#define OPTICK_GPU_INIT_D3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS) ::Optick::InitGpuD3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS);
|
||||
#define OPTICK_GPU_INIT_VULKAN(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS) ::Optick::InitGpuVulkan(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS);
|
||||
#define OPTICK_GPU_INIT_VULKAN(INSTANCE, DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS) ::Optick::InitGpuVulkan(INSTANCE, DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS);
|
||||
|
||||
// Setup GPU context:
|
||||
// Params:
|
||||
|
@ -1121,7 +1124,7 @@ struct OptickApp
|
|||
#define OPTICK_SET_MEMORY_ALLOCATOR(ALLOCATE_FUNCTION, DEALLOCATE_FUNCTION, INIT_THREAD_CALLBACK)
|
||||
#define OPTICK_SHUTDOWN()
|
||||
#define OPTICK_GPU_INIT_D3D12(DEVICE, CMD_QUEUES, NUM_CMD_QUEUS)
|
||||
#define OPTICK_GPU_INIT_VULKAN(DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS)
|
||||
#define OPTICK_GPU_INIT_VULKAN(INSTANCE, DEVICES, PHYSICAL_DEVICES, CMD_QUEUES, CMD_QUEUES_FAMILY, NUM_CMD_QUEUS, FUNCTIONS)
|
||||
#define OPTICK_GPU_CONTEXT(...)
|
||||
#define OPTICK_GPU_EVENT(NAME)
|
||||
#define OPTICK_GPU_FLIP(...)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(OPTICK_MSVC)
|
||||
|
||||
|
@ -143,11 +144,12 @@ static const ProcessID INVALID_PROCESS_ID = (ProcessID)-1;
|
|||
#ifdef _DEBUG
|
||||
#define OPTICK_ASSERT(arg, description) if (!(arg)) { OPTICK_DEBUG_BREAK; }
|
||||
#define OPTICK_FAILED(description) { OPTICK_DEBUG_BREAK; }
|
||||
#define OPTICK_VERIFY(arg, description, operation) if (!(arg)) { OPTICK_DEBUG_BREAK; operation; }
|
||||
#else
|
||||
#define OPTICK_ASSERT(arg, description)
|
||||
#define OPTICK_FAILED(description)
|
||||
#define OPTICK_FAILED(description) { throw std::runtime_error(description); }
|
||||
#define OPTICK_VERIFY(arg, description, operation) if (!(arg)) { OPTICK_FAILED(description); operation; }
|
||||
#endif
|
||||
#define OPTICK_VERIFY(arg, description, operation) if (!(arg)) { OPTICK_DEBUG_BREAK; operation; }
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace Optick
|
|||
GPUProfilerVulkan();
|
||||
~GPUProfilerVulkan();
|
||||
|
||||
void InitDevice(VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions);
|
||||
void InitDevice(VkInstance instance, VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions);
|
||||
void QueryTimestamp(VkCommandBuffer commandBuffer, int64_t* outCpuTimestamp);
|
||||
void Flip(VkSwapchainKHR swapChain);
|
||||
|
||||
|
@ -94,10 +94,10 @@ namespace Optick
|
|||
}
|
||||
};
|
||||
|
||||
void InitGpuVulkan(VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions)
|
||||
void InitGpuVulkan(VkInstance vkInstance, VkDevice* vkDevices, VkPhysicalDevice* vkPhysicalDevices, VkQueue* vkQueues, uint32_t* cmdQueuesFamily, uint32_t numQueues, const VulkanFunctions* functions)
|
||||
{
|
||||
GPUProfilerVulkan* gpuProfiler = Memory::New<GPUProfilerVulkan>();
|
||||
gpuProfiler->InitDevice(vkDevices, vkPhysicalDevices, vkQueues, cmdQueuesFamily, numQueues, functions);
|
||||
gpuProfiler->InitDevice(vkInstance, vkDevices, vkPhysicalDevices, vkQueues, cmdQueuesFamily, numQueues, functions);
|
||||
Core::Get().InitGPUProfiler(gpuProfiler);
|
||||
}
|
||||
|
||||
|
@ -107,15 +107,17 @@ namespace Optick
|
|||
prevPresentID = 0;
|
||||
}
|
||||
|
||||
void GPUProfilerVulkan::InitDevice(VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions)
|
||||
void GPUProfilerVulkan::InitDevice(VkInstance instance, VkDevice* devices, VkPhysicalDevice* physicalDevices, VkQueue* cmdQueues, uint32_t* cmdQueuesFamily, uint32_t nodeCount, const VulkanFunctions* functions)
|
||||
{
|
||||
if (functions != nullptr)
|
||||
{
|
||||
vulkanFunctions = *functions;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
#if OPTICK_STATIC_VULKAN_FUNCTIONS
|
||||
vulkanFunctions = {
|
||||
nullptr, // don't define vkGetInstanceProcAddr if vulkan functions are static
|
||||
vkGetPhysicalDeviceProperties,
|
||||
(PFN_vkCreateQueryPool_)vkCreateQueryPool,
|
||||
(PFN_vkCreateCommandPool_)vkCreateCommandPool,
|
||||
|
@ -142,6 +144,23 @@ namespace Optick
|
|||
vkFreeCommandBuffers,
|
||||
nullptr, // dynamically define vkGetPastPresentationTimingGOOGLE if VK_GOOGLE_display_timing extension available
|
||||
};
|
||||
#else
|
||||
OPTICK_FAILED("Either set OPTICK_STATIC_VULKAN_FUNCTIONS = 1 or VulkanFunctions must be defined! Can't initialize GPU Profiler!");
|
||||
#endif
|
||||
}
|
||||
|
||||
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr_ = nullptr;
|
||||
if (vulkanFunctions.vkGetInstanceProcAddr)
|
||||
{
|
||||
if (instance)
|
||||
{
|
||||
vkGetDeviceProcAddr_ = (PFN_vkGetDeviceProcAddr)(*vulkanFunctions.vkGetInstanceProcAddr)(instance, "vkGetDeviceProcAddr");
|
||||
vulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties_)(*vulkanFunctions.vkGetInstanceProcAddr)(instance, "vkGetPhysicalDeviceProperties");
|
||||
}
|
||||
else
|
||||
{
|
||||
OPTICK_FAILED("VkInstance must be defined if VulkanFunctions::vkGetInstanceProcAddr is defined! Can't initialize GPU Profiler!");
|
||||
}
|
||||
}
|
||||
|
||||
VkQueryPoolCreateInfo queryPoolCreateInfo;
|
||||
|
@ -168,6 +187,40 @@ namespace Optick
|
|||
VkResult r;
|
||||
for (uint32_t i = 0; i < nodeCount; ++i)
|
||||
{
|
||||
if (vkGetDeviceProcAddr_)
|
||||
{
|
||||
vulkanFunctions.vkCreateQueryPool = (PFN_vkCreateQueryPool_)vkGetDeviceProcAddr_(devices[i], "vkCreateQueryPool");
|
||||
vulkanFunctions.vkCreateCommandPool = (PFN_vkCreateCommandPool_)vkGetDeviceProcAddr_(devices[i], "vkCreateCommandPool");
|
||||
vulkanFunctions.vkCreateEvent = (PFN_vkCreateEvent_)vkGetDeviceProcAddr_(devices[i], "vkCreateEvent");
|
||||
vulkanFunctions.vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers_)vkGetDeviceProcAddr_(devices[i], "vkAllocateCommandBuffers");
|
||||
vulkanFunctions.vkCreateFence = (PFN_vkCreateFence_)vkGetDeviceProcAddr_(devices[i], "vkCreateFence");
|
||||
vulkanFunctions.vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool_)vkGetDeviceProcAddr_(devices[i], "vkCmdResetQueryPool");
|
||||
vulkanFunctions.vkResetQueryPool = (PFN_vkResetQueryPool_)vkGetDeviceProcAddr_(devices[i], "vkResetQueryPool");
|
||||
vulkanFunctions.vkCmdWaitEvents = (PFN_vkCmdWaitEvents_)vkGetDeviceProcAddr_(devices[i], "vkCmdWaitEvents");
|
||||
vulkanFunctions.vkResetEvent = (PFN_vkResetEvent_)vkGetDeviceProcAddr_(devices[i], "vkResetEvent");
|
||||
vulkanFunctions.vkSetEvent = (PFN_vkSetEvent_)vkGetDeviceProcAddr_(devices[i], "vkSetEvent");
|
||||
vulkanFunctions.vkQueueSubmit = (PFN_vkQueueSubmit_)vkGetDeviceProcAddr_(devices[i], "vkQueueSubmit");
|
||||
vulkanFunctions.vkWaitForFences = (PFN_vkWaitForFences_)vkGetDeviceProcAddr_(devices[i], "vkWaitForFences");
|
||||
vulkanFunctions.vkResetCommandBuffer = (PFN_vkResetCommandBuffer_)vkGetDeviceProcAddr_(devices[i], "vkResetCommandBuffer");
|
||||
vulkanFunctions.vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp_)vkGetDeviceProcAddr_(devices[i], "vkCmdWriteTimestamp");
|
||||
vulkanFunctions.vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults_)vkGetDeviceProcAddr_(devices[i], "vkGetQueryPoolResults");
|
||||
vulkanFunctions.vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer_)vkGetDeviceProcAddr_(devices[i], "vkBeginCommandBuffer");
|
||||
vulkanFunctions.vkEndCommandBuffer = (PFN_vkEndCommandBuffer_)vkGetDeviceProcAddr_(devices[i], "vkEndCommandBuffer");
|
||||
vulkanFunctions.vkResetFences = (PFN_vkResetFences_)vkGetDeviceProcAddr_(devices[i], "vkResetFences");
|
||||
vulkanFunctions.vkDestroyCommandPool = (PFN_vkDestroyCommandPool_)vkGetDeviceProcAddr_(devices[i], "vkDestroyCommandPool");
|
||||
vulkanFunctions.vkDestroyQueryPool = (PFN_vkDestroyQueryPool_)vkGetDeviceProcAddr_(devices[i], "vkDestroyQueryPool");
|
||||
vulkanFunctions.vkDestroyEvent = (PFN_vkDestroyEvent_)vkGetDeviceProcAddr_(devices[i], "vkDestroyEvent");
|
||||
vulkanFunctions.vkDestroyFence = (PFN_vkDestroyFence_)vkGetDeviceProcAddr_(devices[i], "vkDestroyFence");
|
||||
vulkanFunctions.vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers_)vkGetDeviceProcAddr_(devices[i], "vkFreeCommandBuffers");
|
||||
vulkanFunctions.vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE_)vkGetDeviceProcAddr_(devices[i], "vkGetPastPresentationTimingGOOGLE");
|
||||
}
|
||||
#if OPTICK_STATIC_VULKAN_FUNCTIONS
|
||||
else if (!vulkanFunctions.vkGetPastPresentationTimingGOOGLE)
|
||||
{
|
||||
vulkanFunctions.vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE_)vkGetDeviceProcAddr(devices[i], "vkGetPastPresentationTimingGOOGLE");
|
||||
}
|
||||
#endif
|
||||
|
||||
VkPhysicalDeviceProperties properties = { 0 };
|
||||
(*vulkanFunctions.vkGetPhysicalDeviceProperties)(physicalDevices[i], &properties);
|
||||
GPUProfiler::InitNode(properties.deviceName, i);
|
||||
|
@ -175,7 +228,6 @@ namespace Optick
|
|||
NodePayload* nodePayload = Memory::New<NodePayload>();
|
||||
nodePayloads[i] = nodePayload;
|
||||
nodePayload->vulkanFunctions = &vulkanFunctions;
|
||||
nodePayload->vulkanFunctions->vkGetPastPresentationTimingGOOGLE = (PFN_vkGetPastPresentationTimingGOOGLE_)vkGetDeviceProcAddr(devices[i], "vkGetPastPresentationTimingGOOGLE");
|
||||
nodePayload->device = devices[i];
|
||||
nodePayload->physicalDevice = physicalDevices[i];
|
||||
nodePayload->queue = cmdQueues[i];
|
||||
|
@ -498,7 +550,7 @@ namespace Optick
|
|||
#include "optick_common.h"
|
||||
namespace Optick
|
||||
{
|
||||
void InitGpuVulkan(VkDevice* /*vkDevices*/, VkPhysicalDevice* /*vkPhysicalDevices*/, VkQueue* /*vkQueues*/, uint32_t* /*cmdQueuesFamily*/, uint32_t /*numQueues*/, const VulkanFunctions* /*functions*/)
|
||||
void InitGpuVulkan(VkInstance /*vkInstance*/, VkDevice* /*vkDevices*/, VkPhysicalDevice* /*vkPhysicalDevices*/, VkQueue* /*vkQueues*/, uint32_t* /*cmdQueuesFamily*/, uint32_t /*numQueues*/, const VulkanFunctions* /*functions*/)
|
||||
{
|
||||
OPTICK_FAILED("OPTICK_ENABLE_GPU_VULKAN is disabled! Can't initialize GPU Profiler!");
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ Server::Server(short port) : socket(Memory::New<Socket>()), saveCb(nullptr)
|
|||
{
|
||||
if (!socket->Bind(port, 4))
|
||||
{
|
||||
OPTICK_FAILED("Failed to bind a socket! Most probably the port is blocked by anti-virus! Change the port and verify that your game has enough permissions to communicate over the TCP\IP.");
|
||||
OPTICK_FAILED("Failed to bind a socket! Most probably the port is blocked by anti-virus! Change the port and verify that your game has enough permissions to communicate over the TCP/IP.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -499,4 +499,4 @@ Server & Server::Get()
|
|||
|
||||
}
|
||||
|
||||
#endif //USE_OPTICK
|
||||
#endif //USE_OPTICK
|
||||
|
|
|
@ -44,7 +44,7 @@ static const char* MD5_SnapshotName = "_MD5_Snapshot_";
|
|||
static const byte MD5B_VERSION = 106;
|
||||
static const unsigned int MD5B_MAGIC = ( '5' << 24 ) | ( 'D' << 16 ) | ( 'M' << 8 ) | MD5B_VERSION;
|
||||
|
||||
idCVar r_useGPUSkinning( "r_useGPUSkinning", "1", CVAR_INTEGER, "animate normals and tangents instead of deriving" );
|
||||
idCVar r_useGPUSkinning( "r_useGPUSkinning", "1", CVAR_INTEGER | CVAR_NOCHEAT, "animate normals and tangents instead of deriving" );
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
|
|
|
@ -1791,11 +1791,12 @@ void idRenderBackend::GL_EndFrame()
|
|||
|
||||
commandList->close();
|
||||
|
||||
deviceManager->GetDevice()->executeCommandList( commandList );
|
||||
|
||||
// required for Vulkan: transition our swap image to present
|
||||
deviceManager->EndFrame();
|
||||
|
||||
// SRS - execute after EndFrame() to avoid need for barrier command list on Vulkan
|
||||
deviceManager->GetDevice()->executeCommandList( commandList );
|
||||
|
||||
// update jitter for perspective matrix
|
||||
taaPass->AdvanceFrame();
|
||||
}
|
||||
|
|
|
@ -5386,12 +5386,13 @@ void idRenderBackend::ExecuteBackEndCommands( const emptyCommand_t* cmds )
|
|||
|
||||
DrawFlickerBox();
|
||||
|
||||
GL_EndFrame();
|
||||
|
||||
// stop rendering on this thread
|
||||
uint64 backEndFinishTime = Sys_Microseconds();
|
||||
pc.cpuTotalMicroSec = backEndFinishTime - backEndStartTime;
|
||||
|
||||
// SRS - capture backend timing before GL_EndFrame() since it can block when r_mvkSynchronousQueueSubmits is enabled on macOS/MoltenVK
|
||||
GL_EndFrame();
|
||||
|
||||
if( r_debugRenderToTexture.GetInteger() == 1 )
|
||||
{
|
||||
common->Printf( "3d: %i, 2d: %i, SetBuf: %i, CpyRenders: %i, CpyFrameBuf: %i\n", c_draw3d, c_draw2d, c_setBuffers, c_copyRenders, pc.c_copyFrameBuffer );
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "renderer/RenderCommon.h"
|
||||
#include "renderer/RenderSystem.h"
|
||||
#include "framework/Common_local.h"
|
||||
#include <sys/DeviceManager.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
@ -57,7 +58,7 @@ class DeviceManager_DX12 : public DeviceManager
|
|||
RefCountPtr<IDXGISwapChain3> m_SwapChain;
|
||||
DXGI_SWAP_CHAIN_DESC1 m_SwapChainDesc{};
|
||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC m_FullScreenDesc{};
|
||||
RefCountPtr<IDXGIAdapter> m_DxgiAdapter;
|
||||
RefCountPtr<IDXGIAdapter3> m_DxgiAdapter;
|
||||
bool m_TearingSupported = false;
|
||||
|
||||
std::vector<RefCountPtr<ID3D12Resource>> m_SwapChainBuffers;
|
||||
|
@ -388,7 +389,7 @@ bool DeviceManager_DX12::CreateDeviceAndSwapChain()
|
|||
}
|
||||
}
|
||||
|
||||
m_DxgiAdapter = targetAdapter;
|
||||
targetAdapter->QueryInterface( IID_PPV_ARGS( &m_DxgiAdapter ) );
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc;
|
||||
ZeroMemory( &queueDesc, sizeof( queueDesc ) );
|
||||
|
@ -566,6 +567,12 @@ void DeviceManager_DX12::ResizeSwapChain()
|
|||
void DeviceManager_DX12::BeginFrame()
|
||||
{
|
||||
OPTICK_CATEGORY( "DX12_BeginFrame", Optick::Category::Wait );
|
||||
|
||||
// SRS - get DXGI GPU memory usage for display in statistics overlay HUD
|
||||
DXGI_QUERY_VIDEO_MEMORY_INFO memoryInfoLocal = {}, memoryInfoNonLocal = {};
|
||||
m_DxgiAdapter->QueryVideoMemoryInfo( 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memoryInfoLocal );
|
||||
m_DxgiAdapter->QueryVideoMemoryInfo( 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &memoryInfoNonLocal );
|
||||
commonLocal.SetRendererGpuMemoryMB( int( ( memoryInfoLocal.CurrentUsage + memoryInfoNonLocal.CurrentUsage ) / 1024 / 1024 ) );
|
||||
}
|
||||
|
||||
nvrhi::ITexture* DeviceManager_DX12::GetCurrentBackBuffer()
|
||||
|
|
|
@ -32,16 +32,27 @@
|
|||
#include <unordered_set>
|
||||
|
||||
#include "renderer/RenderCommon.h"
|
||||
#include "framework/Common_local.h"
|
||||
#include <sys/DeviceManager.h>
|
||||
|
||||
#include <nvrhi/vulkan.h>
|
||||
// SRS - optionally needed for MoltenVK runtime config visibility
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
#include <MoltenVK/vk_mvk_moltenvk.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined( USE_MoltenVK )
|
||||
#if 0
|
||||
#include <MoltenVK/mvk_vulkan.h>
|
||||
#include <MoltenVK/mvk_config.h> // SRS - will eventually move to these mvk include files for MoltenVK >= 1.2.7 / SDK >= 1.3.275.0
|
||||
#else
|
||||
#include <MoltenVK/vk_mvk_moltenvk.h> // SRS - now deprecated, but provides backwards compatibility for MoltenVK < 1.2.7 / SDK < 1.3.275.0
|
||||
#endif
|
||||
#endif
|
||||
#if defined( VK_EXT_layer_settings ) || defined( USE_MoltenVK )
|
||||
idCVar r_mvkSynchronousQueueSubmits( "r_mvkSynchronousQueueSubmits", "0", CVAR_BOOL | CVAR_INIT, "Use MoltenVK's synchronous queue submit option." );
|
||||
idCVar r_mvkUseMetalArgumentBuffers( "r_mvkUseMetalArgumentBuffers", "2", CVAR_INTEGER | CVAR_INIT, "Use MoltenVK's Metal argument buffers option (0=Off, 1=Always On, 2=On when VK_EXT_descriptor_indexing enabled)", 0, 2 );
|
||||
#endif
|
||||
#endif
|
||||
#include <nvrhi/validation.h>
|
||||
#include <libs/optick/optick.h>
|
||||
|
||||
#if defined( USE_AMD_ALLOCATOR )
|
||||
#define VMA_IMPLEMENTATION
|
||||
|
@ -201,20 +212,21 @@ private:
|
|||
{
|
||||
// instance
|
||||
{
|
||||
#if defined(__APPLE__) && defined( VK_KHR_portability_enumeration )
|
||||
#if defined(__APPLE__)
|
||||
#if defined( VK_KHR_portability_enumeration )
|
||||
// SRS - This is optional since it only became manadatory with Vulkan SDK 1.3.216.0 or later
|
||||
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
||||
#endif
|
||||
#if defined( VK_EXT_layer_settings )
|
||||
// SRS - This is optional since implemented only for MoltenVK 1.2.7 / SDK 1.3.275.0 or later
|
||||
VK_EXT_LAYER_SETTINGS_EXTENSION_NAME,
|
||||
#endif
|
||||
#endif
|
||||
VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME,
|
||||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
|
||||
},
|
||||
// layers
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
// SRS - synchronization2 not supported natively on MoltenVK, use layer implementation instead
|
||||
"VK_LAYER_KHRONOS_synchronization2"
|
||||
#endif
|
||||
},
|
||||
{ },
|
||||
// device
|
||||
{
|
||||
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
|
||||
|
@ -225,7 +237,11 @@ private:
|
|||
#if USE_OPTICK
|
||||
VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
|
||||
#endif
|
||||
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME
|
||||
#if defined( VK_KHR_format_feature_flags2 )
|
||||
VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME,
|
||||
#endif
|
||||
VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME,
|
||||
VK_EXT_MEMORY_BUDGET_EXTENSION_NAME
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -272,7 +288,7 @@ private:
|
|||
nvrhi::vulkan::DeviceHandle m_NvrhiDevice;
|
||||
nvrhi::DeviceHandle m_ValidationLayer;
|
||||
|
||||
nvrhi::CommandListHandle m_BarrierCommandList;
|
||||
//nvrhi::CommandListHandle m_BarrierCommandList; // SRS - no longer needed
|
||||
std::queue<vk::Semaphore> m_PresentSemaphoreQueue;
|
||||
vk::Semaphore m_PresentSemaphore;
|
||||
|
||||
|
@ -286,6 +302,19 @@ private:
|
|||
// SRS - flag indicating support for presentation timing via VK_GOOGLE_display_timing extension
|
||||
bool displayTimingEnabled = false;
|
||||
|
||||
// SRS - slot for Vulkan device API version at runtime (initialize to Vulkan build version)
|
||||
uint32_t m_DeviceApiVersion = VK_HEADER_VERSION_COMPLETE;
|
||||
|
||||
// SRS - function pointer for initing Vulkan DynamicLoader, VMA, Optick, and MoltenVK functions
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = nullptr;
|
||||
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
#if MVK_VERSION >= MVK_MAKE_VERSION( 1, 2, 6 )
|
||||
// SRS - function pointer for retrieving MoltenVK advanced performance statistics
|
||||
PFN_vkGetPerformanceStatisticsMVK vkGetPerformanceStatisticsMVK = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL vulkanDebugCallback(
|
||||
VkDebugReportFlagsEXT flags,
|
||||
|
@ -426,6 +455,7 @@ bool DeviceManager_VK::createInstance()
|
|||
|
||||
std::unordered_set<std::string> requiredLayers = enabledExtensions.layers;
|
||||
|
||||
auto instanceVersion = vk::enumerateInstanceVersion();
|
||||
for( const auto& layer : vk::enumerateInstanceLayerProperties() )
|
||||
{
|
||||
const std::string name = layer.layerName;
|
||||
|
@ -433,6 +463,13 @@ bool DeviceManager_VK::createInstance()
|
|||
{
|
||||
enabledExtensions.layers.insert( name );
|
||||
}
|
||||
#if defined(__APPLE__) && !defined( USE_MoltenVK )
|
||||
// SRS - Vulkan SDK < 1.3.268.1 does not have native VK_KHR_synchronization2 support on macOS, add Khronos layer to emulate
|
||||
else if( name == "VK_LAYER_KHRONOS_synchronization2" && instanceVersion < VK_MAKE_API_VERSION( 0, 1, 3, 268 ) )
|
||||
{
|
||||
enabledExtensions.layers.insert( name );
|
||||
}
|
||||
#endif
|
||||
|
||||
requiredLayers.erase( name );
|
||||
}
|
||||
|
@ -470,11 +507,68 @@ bool DeviceManager_VK::createInstance()
|
|||
.setPpEnabledExtensionNames( instanceExtVec.data() )
|
||||
.setPApplicationInfo( &applicationInfo );
|
||||
|
||||
#if defined(__APPLE__) && defined( VK_KHR_portability_enumeration )
|
||||
#if defined(__APPLE__)
|
||||
#if defined( VK_KHR_portability_enumeration )
|
||||
if( enabledExtensions.instance.find( VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME ) != enabledExtensions.instance.end() )
|
||||
{
|
||||
info.setFlags( vk::InstanceCreateFlagBits( VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR ) );
|
||||
}
|
||||
#endif
|
||||
#if defined( VK_EXT_layer_settings )
|
||||
// SRS - set MoltenVK runtime configuration parameters on macOS via standardized VK_EXT_layer_settings extension
|
||||
std::vector<vk::LayerSettingEXT> layerSettings;
|
||||
vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo;
|
||||
|
||||
const vk::Bool32 valueTrue = vk::True, valueFalse = vk::False;
|
||||
const int32_t useMetalArgumentBuffers = r_mvkUseMetalArgumentBuffers.GetInteger();
|
||||
const float timestampPeriodLowPassAlpha = 1.0;
|
||||
|
||||
if( enabledExtensions.instance.find( VK_EXT_LAYER_SETTINGS_EXTENSION_NAME ) != enabledExtensions.instance.end() )
|
||||
{
|
||||
// SRS - use MoltenVK layer for configuration via VK_EXT_layer_settings extension
|
||||
vk::LayerSettingEXT layerSetting = { "MoltenVK", "", vk::LayerSettingTypeEXT( 0 ), 1, nullptr };
|
||||
|
||||
// SRS - Set MoltenVK's synchronous queue submit option for vkQueueSubmit() & vkQueuePresentKHR()
|
||||
layerSetting.pSettingName = "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS";
|
||||
layerSetting.type = vk::LayerSettingTypeEXT::eBool32;
|
||||
layerSetting.pValues = r_mvkSynchronousQueueSubmits.GetBool() ? &valueTrue : &valueFalse;
|
||||
layerSettings.push_back( layerSetting );
|
||||
|
||||
// SRS - Enable MoltenVK's image view swizzle feature in case we don't have native image view swizzle
|
||||
layerSetting.pSettingName = "MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE";
|
||||
layerSetting.type = vk::LayerSettingTypeEXT::eBool32;
|
||||
layerSetting.pValues = &valueTrue;
|
||||
layerSettings.push_back( layerSetting );
|
||||
|
||||
// SRS - Turn MoltenVK's Metal argument buffer feature on for descriptor indexing only
|
||||
layerSetting.pSettingName = "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS";
|
||||
layerSetting.type = vk::LayerSettingTypeEXT::eInt32;
|
||||
layerSetting.pValues = &useMetalArgumentBuffers;
|
||||
layerSettings.push_back( layerSetting );
|
||||
|
||||
// SRS - Disable MoltenVK's timestampPeriod filter for HUD / Optick profiler timing calibration
|
||||
layerSetting.pSettingName = "MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA";
|
||||
layerSetting.type = vk::LayerSettingTypeEXT::eFloat32;
|
||||
layerSetting.pValues = ×tampPeriodLowPassAlpha;
|
||||
layerSettings.push_back( layerSetting );
|
||||
|
||||
// SRS - Only enable MoltenVK performance tracking if using API and available based on version
|
||||
#if defined( USE_MoltenVK )
|
||||
#if MVK_VERSION >= MVK_MAKE_VERSION( 1, 2, 6 )
|
||||
// SRS - Enable MoltenVK's performance tracking for display of Metal encoding timer on macOS
|
||||
layerSetting.pSettingName = "MVK_CONFIG_PERFORMANCE_TRACKING";
|
||||
layerSetting.type = vk::LayerSettingTypeEXT::eBool32;
|
||||
layerSetting.pValues = &valueTrue;
|
||||
layerSettings.push_back( layerSetting );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
layerSettingsCreateInfo.settingCount = uint32_t( layerSettings.size() );
|
||||
layerSettingsCreateInfo.pSettings = layerSettings.data();
|
||||
|
||||
info.setPNext( &layerSettingsCreateInfo );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const vk::Result res = vk::createInstance( &info, nullptr, &m_VulkanInstance );
|
||||
|
@ -820,10 +914,17 @@ bool DeviceManager_VK::createDevice()
|
|||
auto meshletFeatures = vk::PhysicalDeviceMeshShaderFeaturesNV()
|
||||
.setTaskShader( true )
|
||||
.setMeshShader( true );
|
||||
|
||||
// SRS - get/set shading rate features which are detected individually by nvrhi (not just at extension level)
|
||||
vk::PhysicalDeviceFeatures2 actualDeviceFeatures2;
|
||||
vk::PhysicalDeviceFragmentShadingRateFeaturesKHR fragmentShadingRateFeatures;
|
||||
actualDeviceFeatures2.pNext = &fragmentShadingRateFeatures;
|
||||
m_VulkanPhysicalDevice.getFeatures2( &actualDeviceFeatures2 );
|
||||
|
||||
auto vrsFeatures = vk::PhysicalDeviceFragmentShadingRateFeaturesKHR()
|
||||
.setPipelineFragmentShadingRate( true )
|
||||
.setPrimitiveFragmentShadingRate( true )
|
||||
.setAttachmentFragmentShadingRate( true );
|
||||
.setPipelineFragmentShadingRate( fragmentShadingRateFeatures.pipelineFragmentShadingRate )
|
||||
.setPrimitiveFragmentShadingRate( fragmentShadingRateFeatures.primitiveFragmentShadingRate )
|
||||
.setAttachmentFragmentShadingRate( fragmentShadingRateFeatures.attachmentFragmentShadingRate );
|
||||
|
||||
auto sync2Features = vk::PhysicalDeviceSynchronization2FeaturesKHR()
|
||||
.setSynchronization2( true );
|
||||
|
@ -851,7 +952,7 @@ bool DeviceManager_VK::createDevice()
|
|||
|
||||
auto deviceFeatures = vk::PhysicalDeviceFeatures()
|
||||
.setShaderImageGatherExtended( true )
|
||||
.setShaderStorageImageReadWithoutFormat( true )
|
||||
.setShaderStorageImageReadWithoutFormat( actualDeviceFeatures2.features.shaderStorageImageReadWithoutFormat )
|
||||
.setSamplerAnisotropy( true )
|
||||
.setTessellationShader( true )
|
||||
.setTextureCompressionBC( true )
|
||||
|
@ -924,15 +1025,16 @@ bool DeviceManager_VK::createDevice()
|
|||
enablePModeImmediate = find( surfacePModes.begin(), surfacePModes.end(), vk::PresentModeKHR::eImmediate ) != surfacePModes.end();
|
||||
enablePModeFifoRelaxed = find( surfacePModes.begin(), surfacePModes.end(), vk::PresentModeKHR::eFifoRelaxed ) != surfacePModes.end();
|
||||
|
||||
// stash the renderer string
|
||||
// stash the device renderer string and api version
|
||||
auto prop = m_VulkanPhysicalDevice.getProperties();
|
||||
m_RendererString = std::string( prop.deviceName.data() );
|
||||
m_DeviceApiVersion = prop.apiVersion;
|
||||
|
||||
#if defined( USE_AMD_ALLOCATOR )
|
||||
// SRS - initialize the vma allocator
|
||||
VmaVulkanFunctions vulkanFunctions = {};
|
||||
vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
|
||||
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
|
||||
vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
|
||||
vulkanFunctions.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr( m_VulkanInstance, "vkGetDeviceProcAddr" );
|
||||
|
||||
VmaAllocatorCreateInfo allocatorCreateInfo = {};
|
||||
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
|
||||
|
@ -1102,7 +1204,6 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain()
|
|||
{
|
||||
enabledExtensions.instance.insert( VK_EXT_DEBUG_REPORT_EXTENSION_NAME );
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
enabledExtensions.layers.insert( "MoltenVK" );
|
||||
}
|
||||
|
||||
// SRS - when USE_MoltenVK defined, load libMoltenVK vs. the default libvulkan
|
||||
|
@ -1114,8 +1215,7 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain()
|
|||
// SRS - make static so ~DynamicLoader() does not prematurely unload vulkan dynamic lib
|
||||
static const vk::DynamicLoader dl;
|
||||
#endif
|
||||
const PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = // NOLINT(misc-misplaced-const)
|
||||
dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
|
||||
vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
|
||||
|
||||
#define CHECK(a) if (!(a)) { return false; }
|
||||
|
@ -1150,37 +1250,70 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain()
|
|||
CHECK( pickPhysicalDevice() );
|
||||
CHECK( findQueueFamilies( m_VulkanPhysicalDevice, m_WindowSurface ) );
|
||||
|
||||
// SRS - when USE_MoltenVK defined, set MoltenVK runtime configuration parameters on macOS
|
||||
// SRS - when USE_MoltenVK defined, set MoltenVK runtime configuration parameters on macOS (deprecated version)
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
vk::PhysicalDeviceFeatures2 deviceFeatures2;
|
||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
|
||||
deviceFeatures2.setPNext( &portabilityFeatures );
|
||||
m_VulkanPhysicalDevice.getFeatures2( &deviceFeatures2 );
|
||||
|
||||
MVKConfiguration pConfig;
|
||||
size_t pConfigSize = sizeof( pConfig );
|
||||
|
||||
vkGetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize );
|
||||
|
||||
// SRS - Set MoltenVK's synchronous queue submit option for vkQueueSubmit() & vkQueuePresentKHR()
|
||||
pConfig.synchronousQueueSubmits = r_mvkSynchronousQueueSubmits.GetBool() ? VK_TRUE : VK_FALSE;
|
||||
vkSetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize );
|
||||
|
||||
// SRS - If we don't have native image view swizzle, enable MoltenVK's image view swizzle feature
|
||||
if( portabilityFeatures.imageViewFormatSwizzle == VK_FALSE )
|
||||
#if defined( VK_EXT_layer_settings )
|
||||
// SRS - for backwards compatibility at runtime: execute only if we can't find the VK_EXT_layer_settings extension
|
||||
if( enabledExtensions.instance.find( VK_EXT_LAYER_SETTINGS_EXTENSION_NAME ) == enabledExtensions.instance.end() )
|
||||
#endif
|
||||
{
|
||||
idLib::Printf( "Enabling MoltenVK's image view swizzle...\n" );
|
||||
pConfig.fullImageViewSwizzle = VK_TRUE;
|
||||
vkSetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize );
|
||||
// SRS - vkSetMoltenVKConfigurationMVK() now deprecated, but retained for MoltenVK < 1.2.7 / SDK < 1.3.275.0
|
||||
const PFN_vkGetMoltenVKConfigurationMVK vkGetMoltenVKConfigurationMVK = // NOLINT(misc-misplaced-const)
|
||||
(PFN_vkGetMoltenVKConfigurationMVK)vkGetInstanceProcAddr( m_VulkanInstance, "vkGetMoltenVKConfigurationMVK" );
|
||||
const PFN_vkSetMoltenVKConfigurationMVK vkSetMoltenVKConfigurationMVK = // NOLINT(misc-misplaced-const)
|
||||
(PFN_vkSetMoltenVKConfigurationMVK)vkGetInstanceProcAddr( m_VulkanInstance, "vkSetMoltenVKConfigurationMVK" );
|
||||
|
||||
vk::PhysicalDeviceFeatures2 deviceFeatures2;
|
||||
vk::PhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
|
||||
deviceFeatures2.setPNext( &portabilityFeatures );
|
||||
m_VulkanPhysicalDevice.getFeatures2( &deviceFeatures2 );
|
||||
|
||||
MVKConfiguration mvkConfig;
|
||||
size_t mvkConfigSize = sizeof( mvkConfig );
|
||||
|
||||
vkGetMoltenVKConfigurationMVK( m_VulkanInstance, &mvkConfig, &mvkConfigSize );
|
||||
|
||||
// SRS - Set MoltenVK's synchronous queue submit option for vkQueueSubmit() & vkQueuePresentKHR()
|
||||
if( mvkConfig.synchronousQueueSubmits == VK_TRUE && !r_mvkSynchronousQueueSubmits.GetBool() )
|
||||
{
|
||||
idLib::Printf( "Disabled MoltenVK's synchronous queue submits...\n" );
|
||||
mvkConfig.synchronousQueueSubmits = VK_FALSE;
|
||||
}
|
||||
|
||||
// SRS - If we don't have native image view swizzle, enable MoltenVK's image view swizzle feature
|
||||
if( portabilityFeatures.imageViewFormatSwizzle == VK_FALSE )
|
||||
{
|
||||
idLib::Printf( "Enabled MoltenVK's image view swizzle...\n" );
|
||||
mvkConfig.fullImageViewSwizzle = VK_TRUE;
|
||||
}
|
||||
|
||||
// SRS - Set MoltenVK's Metal argument buffer option for descriptor resource scaling
|
||||
// - Also needed for Vulkan SDK 1.3.268.1 to work around SPIRV-Cross issue for Metal conversion.
|
||||
// - See https://github.com/KhronosGroup/MoltenVK/issues/2016 and https://github.com/goki/vgpu/issues/9
|
||||
// - Issue solved in Vulkan SDK >= 1.3.275.0, but config uses VK_EXT_layer_settings instead of this code.
|
||||
if( mvkConfig.useMetalArgumentBuffers == MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER && r_mvkUseMetalArgumentBuffers.GetInteger() )
|
||||
{
|
||||
idLib::Printf( "Enabled MoltenVK's Metal argument buffers...\n" );
|
||||
mvkConfig.useMetalArgumentBuffers = MVKUseMetalArgumentBuffers( r_mvkUseMetalArgumentBuffers.GetInteger() );
|
||||
}
|
||||
|
||||
#if MVK_VERSION >= MVK_MAKE_VERSION( 1, 2, 6 )
|
||||
if( mvkConfig.apiVersionToAdvertise >= VK_MAKE_API_VERSION( 0, 1, 2, 268 ) )
|
||||
{
|
||||
// SRS - Disable MoltenVK's timestampPeriod filter for HUD / Optick profiler timing calibration
|
||||
mvkConfig.timestampPeriodLowPassAlpha = 1.0;
|
||||
// SRS - Enable MoltenVK's performance tracking for display of Metal encoding timer on macOS
|
||||
mvkConfig.performanceTracking = VK_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
vkSetMoltenVKConfigurationMVK( m_VulkanInstance, &mvkConfig, &mvkConfigSize );
|
||||
}
|
||||
|
||||
// SRS - Turn MoltenVK's Metal argument buffer feature on for descriptor indexing only
|
||||
if( pConfig.useMetalArgumentBuffers == MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_NEVER )
|
||||
{
|
||||
idLib::Printf( "Enabling MoltenVK's Metal argument buffers for descriptor indexing...\n" );
|
||||
pConfig.useMetalArgumentBuffers = MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS_DESCRIPTOR_INDEXING;
|
||||
vkSetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize );
|
||||
}
|
||||
#if MVK_VERSION >= MVK_MAKE_VERSION( 1, 2, 6 )
|
||||
// SRS - Get function pointer for retrieving MoltenVK advanced performance statistics in DeviceManager_VK::BeginFrame()
|
||||
vkGetPerformanceStatisticsMVK = (PFN_vkGetPerformanceStatisticsMVK)vkGetInstanceProcAddr( m_VulkanInstance, "vkGetPerformanceStatisticsMVK" );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CHECK( createDevice() );
|
||||
|
@ -1220,7 +1353,7 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain()
|
|||
|
||||
CHECK( createSwapChain() );
|
||||
|
||||
m_BarrierCommandList = m_NvrhiDevice->createCommandList();
|
||||
//m_BarrierCommandList = m_NvrhiDevice->createCommandList(); // SRS - no longer needed
|
||||
|
||||
// SRS - Give each swapchain image its own semaphore in case of overlap (e.g. MoltenVK async queue submit)
|
||||
for( int i = 0; i < m_SwapChainImages.size(); i++ )
|
||||
|
@ -1234,7 +1367,11 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain()
|
|||
|
||||
#undef CHECK
|
||||
|
||||
OPTICK_GPU_INIT_VULKAN( ( VkDevice* )&m_VulkanDevice, ( VkPhysicalDevice* )&m_VulkanPhysicalDevice, ( VkQueue* )&m_GraphicsQueue, ( uint32_t* )&m_GraphicsQueueFamily, 1, nullptr );
|
||||
#if USE_OPTICK
|
||||
const Optick::VulkanFunctions optickVulkanFunctions = { (PFN_vkGetInstanceProcAddr_)vkGetInstanceProcAddr };
|
||||
#endif
|
||||
|
||||
OPTICK_GPU_INIT_VULKAN( ( VkInstance )m_VulkanInstance, ( VkDevice* )&m_VulkanDevice, ( VkPhysicalDevice* )&m_VulkanPhysicalDevice, ( VkQueue* )&m_GraphicsQueue, ( uint32_t* )&m_GraphicsQueueFamily, 1, &optickVulkanFunctions );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1257,7 +1394,7 @@ void DeviceManager_VK::DestroyDeviceAndSwapChain()
|
|||
}
|
||||
m_PresentSemaphore = vk::Semaphore();
|
||||
|
||||
m_BarrierCommandList = nullptr;
|
||||
//m_BarrierCommandList = nullptr; // SRS - no longer needed
|
||||
|
||||
destroySwapChain();
|
||||
|
||||
|
@ -1305,6 +1442,43 @@ void DeviceManager_VK::DestroyDeviceAndSwapChain()
|
|||
|
||||
void DeviceManager_VK::BeginFrame()
|
||||
{
|
||||
OPTICK_CATEGORY( "Vulkan_BeginFrame", Optick::Category::Wait );
|
||||
|
||||
#if defined(__APPLE__) && defined( USE_MoltenVK )
|
||||
#if MVK_VERSION >= MVK_MAKE_VERSION( 1, 2, 6 )
|
||||
if( vkGetPerformanceStatisticsMVK && m_DeviceApiVersion >= VK_MAKE_API_VERSION( 0, 1, 2, 268 ) )
|
||||
{
|
||||
// SRS - get MoltenVK's Metal encoding time and GPU memory usage for display in statistics overlay HUD
|
||||
MVKPerformanceStatistics mvkPerfStats;
|
||||
size_t mvkPerfStatsSize = sizeof( mvkPerfStats );
|
||||
vkGetPerformanceStatisticsMVK( m_VulkanDevice, &mvkPerfStats, &mvkPerfStatsSize );
|
||||
commonLocal.SetRendererMvkEncodeMicroseconds( uint64( Max( 0.0, mvkPerfStats.queue.submitCommandBuffers.latest - mvkPerfStats.queue.retrieveCAMetalDrawable.latest ) * 1000.0 ) );
|
||||
commonLocal.SetRendererGpuMemoryMB( int( mvkPerfStats.device.gpuMemoryAllocated.latest / 1024.0 ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
// SRS - get Vulkan GPU memory usage for display in statistics overlay HUD
|
||||
vk::PhysicalDeviceMemoryProperties2 memoryProperties2;
|
||||
vk::PhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget;
|
||||
memoryProperties2.pNext = &memoryBudget;
|
||||
m_VulkanPhysicalDevice.getMemoryProperties2( &memoryProperties2 );
|
||||
|
||||
VkDeviceSize gpuMemoryAllocated = 0;
|
||||
for( uint32_t i = 0; i < memoryProperties2.memoryProperties.memoryHeapCount; i++ )
|
||||
{
|
||||
gpuMemoryAllocated += memoryBudget.heapUsage[i];
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// SRS - macOS Vulkan API <= 1.2.268 has heap reporting defect, use heapUsage[0] only
|
||||
if( m_DeviceApiVersion <= VK_MAKE_API_VERSION( 0, 1, 2, 268 ) )
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
commonLocal.SetRendererGpuMemoryMB( int( gpuMemoryAllocated / 1024 / 1024 ) );
|
||||
}
|
||||
|
||||
const vk::Result res = m_VulkanDevice.acquireNextImageKHR( m_SwapChain,
|
||||
std::numeric_limits<uint64_t>::max(), // timeout
|
||||
m_PresentSemaphore,
|
||||
|
@ -1320,9 +1494,10 @@ void DeviceManager_VK::EndFrame()
|
|||
{
|
||||
m_NvrhiDevice->queueSignalSemaphore( nvrhi::CommandQueue::Graphics, m_PresentSemaphore, 0 );
|
||||
|
||||
m_BarrierCommandList->open(); // umm...
|
||||
m_BarrierCommandList->close();
|
||||
m_NvrhiDevice->executeCommandList( m_BarrierCommandList );
|
||||
// SRS - Don't need barrier commandlist if EndFrame() is called before executeCommandList() in idRenderBackend::GL_EndFrame()
|
||||
//m_BarrierCommandList->open(); // umm...
|
||||
//m_BarrierCommandList->close();
|
||||
//m_NvrhiDevice->executeCommandList( m_BarrierCommandList );
|
||||
}
|
||||
|
||||
void DeviceManager_VK::Present()
|
||||
|
|
|
@ -452,6 +452,8 @@ main
|
|||
*/
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
extern idCVar r_useGPUSkinning;
|
||||
|
||||
// DG: needed for Sys_ReLaunch()
|
||||
cmdargc = argc;
|
||||
cmdargv = argv;
|
||||
|
@ -481,6 +483,21 @@ int main( int argc, const char** argv )
|
|||
common->Init( 0, NULL, NULL );
|
||||
}
|
||||
|
||||
// SRS - Determine the machine name, e.g. "x86_64" or "arm64"
|
||||
// Might be cleaner in posix Sys_Init(), but only needed on
|
||||
// macOS and all the required sys includes are located here.
|
||||
size_t size;
|
||||
sysctlbyname( "hw.machine", NULL, &size, NULL, 0 );
|
||||
char* machineName = ( char* )Mem_Alloc( size, TAG_SYSTEM );
|
||||
sysctlbyname( "hw.machine", machineName, &size, NULL, 0 );
|
||||
|
||||
// FIXME: On Apple Silicon disable GPU skinning to eliminate rendering artifacts
|
||||
if( strcmp( machineName, "arm64" ) == 0 )
|
||||
{
|
||||
r_useGPUSkinning.SetInteger( 0 );
|
||||
}
|
||||
Mem_Free( machineName );
|
||||
|
||||
Posix_LateInit();
|
||||
|
||||
while( 1 )
|
||||
|
|
Loading…
Reference in a new issue