Metal sync interval support (#2187)

* Metal sync interval support
Add shader name to SRGPool for debugging purposes
Set default value of rpi_vsync_interval to 1

Signed-off-by: moudgils <moudgils@amazon.com>
This commit is contained in:
moudgils
2021-07-15 11:50:19 -07:00
committed by GitHub
parent d1227d1836
commit 7ef383580e
6 changed files with 57 additions and 16 deletions
@@ -43,11 +43,36 @@ namespace Platform
}
return physicalDeviceList;
}
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval)
float GetRefreshRate()
{
AZ_UNUSED(syncInterval);
[mtlCommandBuffer presentDrawable:drawable];
CGDirectDisplayID display = CGMainDisplayID();
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display);
return CGDisplayModeGetRefreshRate(currentMode);
}
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate)
{
bool framePresented = false;
//seconds per frame (1/refreshrate) * num frames (sync interval)
float presentAfterMinimumDuration = syncInterval / refreshRate;
#if defined(__MAC_10_15_4)
if(@available(macOS 10.15.4, *))
{
if(presentAfterMinimumDuration > 0.0f)
{
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:presentAfterMinimumDuration];
framePresented = true;
}
}
#endif
if(!framePresented)
{
[mtlCommandBuffer presentDrawable:drawable];
}
}
CGRect GetScreenBounds(NativeWindowType* nativeWindow)
@@ -29,13 +29,19 @@ namespace Platform
return physicalDeviceList;
}
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval)
float GetRefreshRate()
{
bool hasPresentAfterMinimumDuration = [drawable respondsToSelector:@selector(presentAfterMinimumDuration:)];
if (hasPresentAfterMinimumDuration && syncInterval > 0.0f)
NativeScreenType* nativeScreen = [NativeScreenType mainScreen];
return [nativeScreen maximumFramesPerSecond];
}
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate)
{
//seconds per frame (1/refreshrate) * num frames (sync interval)
float presentAfterMinimumDuration = syncInterval / refreshRate;
if (hasPresentAfterMinimumDuration > 0.0f)
{
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:syncInterval];
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:presentAfterMinimumDuration];
}
else
{
@@ -19,8 +19,9 @@ namespace Platform
CGFloat GetScreenScale();
void AttachViewController(NativeWindowType* nativeWindow, NativeViewControllerType* viewController, RHIMetalView* metalView);
void UnAttachViewController(NativeWindowType* nativeWindow, NativeViewControllerType* viewController);
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval);
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate);
void ResizeInternal(RHIMetalView* metalView, CGSize viewSize);
float GetRefreshRate();
RHIMetalView* GetMetalView(NativeWindowType* nativeWindow);
}
@@ -73,6 +74,15 @@ namespace AZ
AddSubView();
}
m_refreshRate = Platform::GetRefreshRate();
//Assume 60hz if 0 is returned.
//Internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz
if (m_refreshRate < 0.1f)
{
m_refreshRate = 60.0f;
}
m_drawables.resize(descriptor.m_dimensions.m_imageCount);
if (nativeDimensions)
@@ -148,10 +158,9 @@ namespace AZ
uint32_t SwapChain::PresentInternal()
{
const uint32_t currentImageIndex = GetCurrentImageIndex();
//GFX TODO][ATOM-432] - Hardcoding to 30fps for now. Only used by ios. This needs to be driven by higher level code.
float syncInterval = 1.0f/30.0f;
//Preset the drawable
Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], syncInterval);
Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval, m_refreshRate);
[m_drawables[currentImageIndex] release];
m_drawables[currentImageIndex] = nil;
@@ -52,6 +52,7 @@ namespace AZ
id<MTLDevice> m_mtlDevice = nil;
NativeWindowType* m_nativeWindow = nullptr;
AZStd::vector<id<CAMetalDrawable>> m_drawables;
float m_refreshRate = 0.0f;
};
}
}
@@ -58,8 +58,8 @@ namespace AZ
RHI::ShaderResourceGroupPoolDescriptor poolDescriptor;
poolDescriptor.m_layout = shaderAsset.FindShaderResourceGroupLayout(srgName, supervariantIndex).get();
m_pool->SetName(srgName);
m_pool->SetName(AZ::Name(AZStd::string::format("%s_%s",shaderAsset.GetName().GetCStr(),srgName.GetCStr())));
const RHI::ResultCode resultCode = m_pool->Init(*device, poolDescriptor);
return resultCode;
}
@@ -27,7 +27,7 @@ void OnVsyncIntervalChanged(uint32_t const& interval)
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
// The value of the vsync interval is constrained between 0 and 4
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
AZ_CVAR(uint32_t, rpi_vsync_interval, 0, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
AZ_CVAR(uint32_t, rpi_vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
namespace AZ
{