mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-10-25 10:20:52 +00:00
NVIDIA Reflex integration. (#4029)
* Integrated NVIDIA Reflex. * Generated bindings and replaced bools with enum. * Merged upstream master. * Addressed review feedback.
This commit is contained in:
@@ -147,6 +147,19 @@ namespace bgfx { namespace vk
|
||||
{ VK_PRESENT_MODE_IMMEDIATE_KHR, false, "VK_PRESENT_MODE_IMMEDIATE_KHR" },
|
||||
};
|
||||
|
||||
static const VkLatencyMarkerNV s_latencyMarker[] =
|
||||
{
|
||||
VK_LATENCY_MARKER_SIMULATION_START_NV,
|
||||
VK_LATENCY_MARKER_SIMULATION_END_NV,
|
||||
VK_LATENCY_MARKER_RENDERSUBMIT_START_NV,
|
||||
VK_LATENCY_MARKER_RENDERSUBMIT_END_NV,
|
||||
VK_LATENCY_MARKER_PRESENT_START_NV,
|
||||
VK_LATENCY_MARKER_PRESENT_END_NV,
|
||||
};
|
||||
static_assert(LatencyMarker::Count == BX_COUNTOF(s_latencyMarker) );
|
||||
|
||||
static constexpr uint64_t kLowLatencySleepTimeout = UINT64_C(500000000);
|
||||
|
||||
#define VK_IMPORT_FUNC(_optional, _func) PFN_##_func _func
|
||||
#define VK_IMPORT_INSTANCE_FUNC VK_IMPORT_FUNC
|
||||
#define VK_IMPORT_DEVICE_FUNC VK_IMPORT_FUNC
|
||||
@@ -383,12 +396,14 @@ VK_IMPORT_DEVICE
|
||||
KHR_fragment_shading_rate,
|
||||
KHR_get_physical_device_properties2,
|
||||
KHR_get_surface_capabilities2,
|
||||
KHR_present_id,
|
||||
KHR_shader_float16_int8,
|
||||
KHR_video_queue,
|
||||
KHR_video_decode_queue,
|
||||
KHR_video_decode_h264,
|
||||
KHR_video_decode_h265,
|
||||
KHR_video_decode_av1,
|
||||
NV_low_latency2,
|
||||
|
||||
# if BX_PLATFORM_ANDROID
|
||||
KHR_android_surface,
|
||||
@@ -433,12 +448,14 @@ VK_IMPORT_DEVICE
|
||||
{ "VK_KHR_fragment_shading_rate", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_get_physical_device_properties2", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_get_surface_capabilities2", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_present_id", 1, false, false, false, Layer::Count },
|
||||
{ "VK_KHR_shader_float16_int8", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_video_queue", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_video_decode_queue", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_video_decode_h264", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_video_decode_h265", 1, false, false, true, Layer::Count },
|
||||
{ "VK_KHR_video_decode_av1", 1, false, false, true, Layer::Count },
|
||||
{ "VK_NV_low_latency2", 2, false, false, false, Layer::Count },
|
||||
# if BX_PLATFORM_ANDROID
|
||||
{ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 1, false, false, true, Layer::Count },
|
||||
# elif BX_PLATFORM_LINUX
|
||||
@@ -1307,6 +1324,7 @@ VK_IMPORT_DEVICE
|
||||
, m_captureMemory()
|
||||
, m_captureSize(0)
|
||||
, m_variableRateShadingSupported(false)
|
||||
, m_lowLatencySupported(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1343,6 +1361,8 @@ VK_IMPORT_DEVICE
|
||||
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchainMaintenance1Features = {};
|
||||
VkPhysicalDeviceShaderFloat16Int8Features shaderFloat16Int8Features = {};
|
||||
VkPhysicalDevice16BitStorageFeatures storage16BitFeatures = {};
|
||||
VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures = {};
|
||||
VkPhysicalDevicePresentIdFeaturesKHR presentIdFeatures = {};
|
||||
|
||||
m_fbh = BGFX_INVALID_HANDLE;
|
||||
m_readOnlyDepthLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@@ -1354,6 +1374,13 @@ VK_IMPORT_DEVICE
|
||||
m_videoDecodeQueueFamily = UINT32_MAX;
|
||||
m_videoDecodeQueue = VK_NULL_HANDLE;
|
||||
|
||||
m_lowLatencySupported = false;
|
||||
m_lowLatencyMode = getLatencyMode(_init.reset);
|
||||
m_lowLatencySwapChain = VK_NULL_HANDLE;
|
||||
m_lowLatencySemaphore = VK_NULL_HANDLE;
|
||||
m_lowLatencySemaphoreValue = 0;
|
||||
m_lowLatencyPresentId = 0;
|
||||
|
||||
if (_init.debug
|
||||
|| _init.profile)
|
||||
{
|
||||
@@ -1413,6 +1440,20 @@ VK_IMPORT
|
||||
s_extension[Extension::KHR_draw_indirect_count ].m_initialize = !!(_init.capabilities & BGFX_CAPS_DRAW_INDIRECT_COUNT );
|
||||
s_extension[Extension::KHR_fragment_shading_rate ].m_initialize = !!(_init.capabilities & BGFX_CAPS_VARIABLE_RATE_SHADING);
|
||||
|
||||
// NVIDIA Reflex is Windows only.
|
||||
const bool lowLatency = true
|
||||
&& BX_ENABLED(BX_PLATFORM_WINDOWS)
|
||||
&& 0 != (_init.capabilities & BGFX_CAPS_LOW_LATENCY)
|
||||
&& !headless
|
||||
&& NULL == g_platformData.context
|
||||
;
|
||||
|
||||
s_extension[Extension::KHR_present_id ].m_initialize = lowLatency;
|
||||
s_extension[Extension::NV_low_latency2].m_initialize = lowLatency;
|
||||
|
||||
s_extension[Extension::KHR_present_id ].m_supported = false;
|
||||
s_extension[Extension::NV_low_latency2].m_supported = false;
|
||||
|
||||
dumpExtensions(VK_NULL_HANDLE, s_extension);
|
||||
|
||||
if (s_layer[Layer::VK_LAYER_KHRONOS_validation].m_device.m_supported
|
||||
@@ -1851,6 +1892,45 @@ VK_IMPORT_INSTANCE
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool lowLatencySupported = true
|
||||
&& s_extension[Extension::NV_low_latency2].m_supported
|
||||
&& s_extension[Extension::KHR_present_id ].m_supported
|
||||
&& VK_API_VERSION_1_2 <= m_instanceApiVersion
|
||||
&& VK_API_VERSION_1_2 <= m_deviceProperties.apiVersion
|
||||
&& NULL != vkGetPhysicalDeviceFeatures2KHR
|
||||
;
|
||||
|
||||
if (lowLatencySupported)
|
||||
{
|
||||
VkPhysicalDeviceFeatures2KHR deviceFeatures2;
|
||||
deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
|
||||
deviceFeatures2.pNext = &timelineSemaphoreFeatures;
|
||||
|
||||
timelineSemaphoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES;
|
||||
timelineSemaphoreFeatures.pNext = &presentIdFeatures;
|
||||
|
||||
presentIdFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR;
|
||||
presentIdFeatures.pNext = NULL;
|
||||
|
||||
vkGetPhysicalDeviceFeatures2KHR(m_physicalDevice, &deviceFeatures2);
|
||||
|
||||
lowLatencySupported = true
|
||||
&& timelineSemaphoreFeatures.timelineSemaphore
|
||||
&& presentIdFeatures.presentId
|
||||
;
|
||||
}
|
||||
|
||||
if (lowLatencySupported)
|
||||
{
|
||||
presentIdFeatures.pNext = (VkBaseOutStructure*)nextFeatures;
|
||||
nextFeatures = &timelineSemaphoreFeatures;
|
||||
}
|
||||
|
||||
s_extension[Extension::KHR_present_id ].m_supported = lowLatencySupported;
|
||||
s_extension[Extension::NV_low_latency2].m_supported = lowLatencySupported;
|
||||
}
|
||||
|
||||
m_deviceFeatures =
|
||||
{
|
||||
.robustBufferAccess = true
|
||||
@@ -2277,6 +2357,34 @@ VK_IMPORT_DEVICE
|
||||
vkGetDeviceQueue(m_device, m_globalQueueFamily, 0, &m_globalQueue);
|
||||
vkGetDeviceQueue(m_device, m_videoDecodeQueueFamily, 0, &m_videoDecodeQueue);
|
||||
|
||||
m_lowLatencySupported = true
|
||||
&& s_extension[Extension::NV_low_latency2].m_supported
|
||||
&& NULL != vkSetLatencySleepModeNV
|
||||
&& NULL != vkLatencySleepNV
|
||||
&& NULL != vkSetLatencyMarkerNV
|
||||
&& NULL != vkGetLatencyTimingsNV
|
||||
&& NULL != vkWaitSemaphores
|
||||
;
|
||||
|
||||
if (m_lowLatencySupported)
|
||||
{
|
||||
VkSemaphoreTypeCreateInfo stci;
|
||||
stci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
|
||||
stci.pNext = NULL;
|
||||
stci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
|
||||
stci.initialValue = 0;
|
||||
|
||||
VkSemaphoreCreateInfo sci;
|
||||
sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
sci.pNext = &stci;
|
||||
sci.flags = 0;
|
||||
|
||||
result = vkCreateSemaphore(m_device, &sci, m_allocatorCb, &m_lowLatencySemaphore);
|
||||
BX_WARN(VK_SUCCESS == result, "vkCreateSemaphore failed %d: %s.", result, getName(result) );
|
||||
|
||||
m_lowLatencySupported = VK_SUCCESS == result;
|
||||
}
|
||||
|
||||
if (_init.videoDecode)
|
||||
{
|
||||
initVideoDecoder(this
|
||||
@@ -2338,6 +2446,11 @@ VK_IMPORT_DEVICE
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (m_lowLatencySupported)
|
||||
{
|
||||
g_caps.supported |= BGFX_CAPS_LOW_LATENCY;
|
||||
}
|
||||
|
||||
m_windows[0] = BGFX_INVALID_HANDLE;
|
||||
m_numWindows++;
|
||||
|
||||
@@ -2503,6 +2616,7 @@ VK_IMPORT_DEVICE
|
||||
[[fallthrough]];
|
||||
|
||||
case ErrorState::DeviceCreated:
|
||||
vkDestroy(m_lowLatencySemaphore);
|
||||
vkDestroyDevice(m_device, m_allocatorCb);
|
||||
[[fallthrough]];
|
||||
|
||||
@@ -2574,6 +2688,7 @@ VK_IMPORT_DEVICE
|
||||
m_memoryLru.evictAll();
|
||||
|
||||
vkDestroy(m_pipelineCache);
|
||||
vkDestroy(m_lowLatencySemaphore);
|
||||
|
||||
for (uint32_t ii = 0; ii < m_maxFrameLatency; ++ii)
|
||||
{
|
||||
@@ -2992,6 +3107,159 @@ VK_IMPORT_DEVICE
|
||||
}
|
||||
}
|
||||
|
||||
void latencySleep() override
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
{
|
||||
bx::MutexScope scope(m_lowLatencyMutex);
|
||||
|
||||
if (VK_NULL_HANDLE == m_lowLatencySwapChain)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
value = ++m_lowLatencySemaphoreValue;
|
||||
|
||||
VkLatencySleepInfoNV lsi;
|
||||
lsi.sType = VK_STRUCTURE_TYPE_LATENCY_SLEEP_INFO_NV;
|
||||
lsi.pNext = NULL;
|
||||
lsi.signalSemaphore = m_lowLatencySemaphore;
|
||||
lsi.value = value;
|
||||
|
||||
const VkResult result = vkLatencySleepNV(m_device, m_lowLatencySwapChain, &lsi);
|
||||
|
||||
if (VK_SUCCESS != result)
|
||||
{
|
||||
BX_TRACE("vkLatencySleepNV failed %d: %s.", result, getName(result) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VkSemaphoreWaitInfo swi;
|
||||
swi.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
|
||||
swi.pNext = NULL;
|
||||
swi.flags = 0;
|
||||
swi.semaphoreCount = 1;
|
||||
swi.pSemaphores = &m_lowLatencySemaphore;
|
||||
swi.pValues = &value;
|
||||
|
||||
const VkResult result = vkWaitSemaphores(m_device, &swi, kLowLatencySleepTimeout);
|
||||
BX_WARN(VK_SUCCESS == result, "vkWaitSemaphores failed %d: %s.", result, getName(result) ); BX_UNUSED(result);
|
||||
}
|
||||
|
||||
void setLatencyMarker(LatencyMarker::Enum _marker, uint64_t _frameId) override
|
||||
{
|
||||
bx::MutexScope scope(m_lowLatencyMutex);
|
||||
|
||||
if (LatencyMarker::PresentStart == _marker)
|
||||
{
|
||||
m_lowLatencyPresentId = _frameId;
|
||||
}
|
||||
|
||||
if (VK_NULL_HANDLE != m_lowLatencySwapChain)
|
||||
{
|
||||
VkSetLatencyMarkerInfoNV slmi;
|
||||
slmi.sType = VK_STRUCTURE_TYPE_SET_LATENCY_MARKER_INFO_NV;
|
||||
slmi.pNext = NULL;
|
||||
slmi.presentID = _frameId;
|
||||
slmi.marker = s_latencyMarker[_marker];
|
||||
|
||||
vkSetLatencyMarkerNV(m_device, m_lowLatencySwapChain, &slmi);
|
||||
}
|
||||
}
|
||||
|
||||
void setLowLatencySwapChain(VkSwapchainKHR _swapChain)
|
||||
{
|
||||
bx::MutexScope scope(m_lowLatencyMutex);
|
||||
|
||||
m_lowLatencySwapChain = _swapChain;
|
||||
|
||||
if (VK_NULL_HANDLE != m_lowLatencySwapChain)
|
||||
{
|
||||
setLowLatencySleepMode();
|
||||
}
|
||||
}
|
||||
|
||||
void setLowLatencyMode(LatencyMode::Enum _mode)
|
||||
{
|
||||
bx::MutexScope scope(m_lowLatencyMutex);
|
||||
|
||||
m_lowLatencyMode = _mode;
|
||||
|
||||
if (VK_NULL_HANDLE != m_lowLatencySwapChain)
|
||||
{
|
||||
setLowLatencySleepMode();
|
||||
}
|
||||
}
|
||||
|
||||
void setLowLatencySleepMode()
|
||||
{
|
||||
VkLatencySleepModeInfoNV lsmi;
|
||||
lsmi.sType = VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV;
|
||||
lsmi.pNext = NULL;
|
||||
lsmi.lowLatencyMode = LatencyMode::Off != m_lowLatencyMode;
|
||||
lsmi.lowLatencyBoost = LatencyMode::Boost == m_lowLatencyMode;
|
||||
lsmi.minimumIntervalUs = 0;
|
||||
|
||||
VK_CHECK(vkSetLatencySleepModeNV(m_device, m_lowLatencySwapChain, &lsmi) );
|
||||
}
|
||||
|
||||
bool getLatencyReport(LatencyReport& _report)
|
||||
{
|
||||
bx::MutexScope scope(m_lowLatencyMutex);
|
||||
|
||||
if (VK_NULL_HANDLE == m_lowLatencySwapChain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
VkLatencyTimingsFrameReportNV* timings = m_lowLatencyTimings;
|
||||
|
||||
for (uint32_t ii = 0; ii < BX_COUNTOF(m_lowLatencyTimings); ++ii)
|
||||
{
|
||||
timings[ii].sType = VK_STRUCTURE_TYPE_LATENCY_TIMINGS_FRAME_REPORT_NV;
|
||||
timings[ii].pNext = NULL;
|
||||
}
|
||||
|
||||
VkGetLatencyMarkerInfoNV glmi;
|
||||
glmi.sType = VK_STRUCTURE_TYPE_GET_LATENCY_MARKER_INFO_NV;
|
||||
glmi.pNext = NULL;
|
||||
glmi.timingCount = BX_COUNTOF(m_lowLatencyTimings);
|
||||
glmi.pTimings = timings;
|
||||
|
||||
vkGetLatencyTimingsNV(m_device, m_lowLatencySwapChain, &glmi);
|
||||
|
||||
const VkLatencyTimingsFrameReportNV* newest = NULL;
|
||||
|
||||
for (uint32_t ii = 0, num = bx::min<uint32_t>(glmi.timingCount, BX_COUNTOF(m_lowLatencyTimings) ); ii < num; ++ii)
|
||||
{
|
||||
const VkLatencyTimingsFrameReportNV& timing = timings[ii];
|
||||
|
||||
if (0 != timing.simStartTimeUs
|
||||
&& timing.gpuRenderEndTimeUs > timing.simStartTimeUs
|
||||
&& (NULL == newest || timing.presentID > newest->presentID) )
|
||||
{
|
||||
newest = &timing;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == newest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_report.simulationStart = newest->simStartTimeUs;
|
||||
_report.simulationEnd = newest->simEndTimeUs;
|
||||
_report.renderSubmitStart = newest->renderSubmitStartTimeUs;
|
||||
_report.renderSubmitEnd = newest->renderSubmitEndTimeUs;
|
||||
_report.presentStart = newest->presentStartTimeUs;
|
||||
_report.presentEnd = newest->presentEndTimeUs;
|
||||
_report.gpuRenderStart = newest->gpuRenderStartTimeUs;
|
||||
_report.gpuRenderEnd = newest->gpuRenderEndTimeUs;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setName(Handle _handle, const char* _name, uint16_t _len) override
|
||||
{
|
||||
switch (_handle.type)
|
||||
@@ -3251,8 +3519,17 @@ VK_IMPORT_DEVICE
|
||||
uint32_t maskFlags = ~(0
|
||||
| BGFX_RESET_SUSPEND
|
||||
| BGFX_RESET_MAXANISOTROPY
|
||||
| BGFX_RESET_LOW_LATENCY_MASK
|
||||
);
|
||||
|
||||
const LatencyMode::Enum lowLatencyMode = getLatencyMode(_reset);
|
||||
|
||||
if (m_lowLatencySupported
|
||||
&& m_lowLatencyMode != lowLatencyMode)
|
||||
{
|
||||
setLowLatencyMode(lowLatencyMode);
|
||||
}
|
||||
|
||||
if (m_swapchainMaintenance1Supported
|
||||
&& !!((_reset ^ m_reset) & BGFX_RESET_VSYNC) )
|
||||
{
|
||||
@@ -5283,6 +5560,16 @@ VK_IMPORT_DEVICE
|
||||
|
||||
bool m_variableRateShadingSupported;
|
||||
|
||||
bool m_lowLatencySupported;
|
||||
LatencyMode::Enum m_lowLatencyMode;
|
||||
VkSwapchainKHR m_lowLatencySwapChain;
|
||||
VkSemaphore m_lowLatencySemaphore;
|
||||
uint64_t m_lowLatencySemaphoreValue;
|
||||
uint64_t m_lowLatencyPresentId;
|
||||
bx::Mutex m_lowLatencyMutex;
|
||||
|
||||
VkLatencyTimingsFrameReportNV m_lowLatencyTimings[64];
|
||||
|
||||
TextVideoMem m_textVideoMem;
|
||||
|
||||
uint8_t m_fsScratch[64<<10];
|
||||
@@ -8119,6 +8406,37 @@ VK_DESTROY
|
||||
}
|
||||
}
|
||||
|
||||
bool SwapChainVK::isLowLatency() const
|
||||
{
|
||||
// Reflex paces the main swap chain only.
|
||||
return true
|
||||
&& s_renderVK->m_lowLatencySupported
|
||||
&& this == &s_renderVK->m_backBuffer.m_swapChain
|
||||
;
|
||||
}
|
||||
|
||||
struct LowLatencyScope
|
||||
{
|
||||
LowLatencyScope(const SwapChainVK& _swapChain)
|
||||
: m_mutex(_swapChain.isLowLatency() ? &s_renderVK->m_lowLatencyMutex : NULL)
|
||||
{
|
||||
if (NULL != m_mutex)
|
||||
{
|
||||
m_mutex->lock();
|
||||
}
|
||||
}
|
||||
|
||||
~LowLatencyScope()
|
||||
{
|
||||
if (NULL != m_mutex)
|
||||
{
|
||||
m_mutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bx::Mutex* m_mutex;
|
||||
};
|
||||
|
||||
VkResult SwapChainVK::create(VkCommandBuffer _commandBuffer, void* _nwh, const SwapChain& _desc)
|
||||
{
|
||||
struct ErrorState
|
||||
@@ -8717,6 +9035,19 @@ VK_DESTROY
|
||||
m_sci.pNext = &modesInfo;
|
||||
}
|
||||
|
||||
const bool lowLatency = isLowLatency();
|
||||
|
||||
VkSwapchainLatencyCreateInfoNV latencyInfo;
|
||||
|
||||
if (lowLatency)
|
||||
{
|
||||
latencyInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV;
|
||||
latencyInfo.pNext = m_sci.pNext;
|
||||
latencyInfo.latencyModeEnable = VK_TRUE;
|
||||
|
||||
m_sci.pNext = &latencyInfo;
|
||||
}
|
||||
|
||||
result = vkCreateSwapchainKHR(device, &m_sci, allocatorCb, &m_swapChain);
|
||||
if (VK_SUCCESS != result)
|
||||
{
|
||||
@@ -8828,6 +9159,11 @@ VK_DESTROY
|
||||
m_needPresent = false;
|
||||
m_needToRecreateSwapchain = false;
|
||||
|
||||
if (lowLatency)
|
||||
{
|
||||
s_renderVK->setLowLatencySwapChain(m_swapChain);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8835,6 +9171,11 @@ VK_DESTROY
|
||||
{
|
||||
BGFX_PROFILER_SCOPE("SwapChainVK::releaseSwapChain", kColorFrame);
|
||||
|
||||
if (isLowLatency() )
|
||||
{
|
||||
s_renderVK->setLowLatencySwapChain(VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
for (uint32_t ii = 0; ii < BX_COUNTOF(m_backBufferColorImageView); ++ii)
|
||||
{
|
||||
release(m_backBufferColorImageView[ii]);
|
||||
@@ -9128,6 +9469,7 @@ VK_DESTROY
|
||||
VkResult result;
|
||||
{
|
||||
BGFX_PROFILER_SCOPE("vkAcquireNextImageKHR", kColorFrame);
|
||||
LowLatencyScope lowLatencyScope(*this);
|
||||
|
||||
result = vkAcquireNextImageKHR(
|
||||
device
|
||||
@@ -9238,9 +9580,25 @@ VK_DESTROY
|
||||
pi.pNext = &presentModeInfo;
|
||||
}
|
||||
|
||||
VkPresentIdKHR presentId;
|
||||
const uint64_t lowLatencyPresentId = s_renderVK->m_lowLatencyPresentId;
|
||||
|
||||
if (isLowLatency()
|
||||
&& 0 != lowLatencyPresentId)
|
||||
{
|
||||
presentId.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR;
|
||||
presentId.pNext = pi.pNext;
|
||||
presentId.swapchainCount = 1;
|
||||
presentId.pPresentIds = &lowLatencyPresentId;
|
||||
|
||||
pi.pNext = &presentId;
|
||||
s_renderVK->m_lowLatencyPresentId = 0;
|
||||
}
|
||||
|
||||
VkResult result;
|
||||
{
|
||||
BGFX_PROFILER_SCOPE("vkQueuePresentHKR", kColorFrame);
|
||||
LowLatencyScope lowLatencyScope(*this);
|
||||
|
||||
result = vkQueuePresentKHR(m_queue, &pi);
|
||||
}
|
||||
@@ -11567,6 +11925,12 @@ VK_DESTROY
|
||||
perfStats.gpuMemoryMax = gpuMemoryAvailable;
|
||||
perfStats.gpuMemoryUsed = gpuMemoryUsed;
|
||||
|
||||
LatencyReport latencyReport;
|
||||
if (getLatencyReport(latencyReport) )
|
||||
{
|
||||
setLatencyStats(perfStats, latencyReport);
|
||||
}
|
||||
|
||||
if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
|
||||
{
|
||||
BGFX_VK_PROFILER_BEGIN_LITERAL("debugstats", kColorFrame);
|
||||
|
||||
Reference in New Issue
Block a user