summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ian Elliott <ianelliott@google.com> 2016-12-29 11:07:26 -0700
committer Ian Elliott <ianelliott@google.com> 2017-01-09 09:26:43 -0700
commit4c8bb2a95d7849c79dea889f1be59281f4e374bf (patch)
treefb3f78bfb6a3945cbd5067f935aadc1ba11101c4
parent4b002d8fceb8129cb398c63d437324ed36db385d (diff)
Stubbed implementation of VK_GOOGLE_display_timing extension.
This provides the header changes and most of the "boilerplate" changes to add the VK_GOOGLE_display_timing extension to Vulkan. Future changes will modify and integrate with the Surface, FrameEvents, and SurfaceFlinger code. Test: Manually tested that existing apps won't tickle the new-extension paths. Change-Id: Iec46b1cab4b2561702ebac9a4ae7587584793192
-rw-r--r--vulkan/api/vulkan.api69
-rw-r--r--vulkan/include/vulkan/vulkan.h47
-rw-r--r--vulkan/libvulkan/api_gen.cpp10
-rw-r--r--vulkan/libvulkan/api_gen.h2
-rw-r--r--vulkan/libvulkan/code-generator.tmpl3
-rw-r--r--vulkan/libvulkan/driver_gen.cpp33
-rw-r--r--vulkan/libvulkan/driver_gen.h1
-rw-r--r--vulkan/libvulkan/swapchain.cpp80
-rw-r--r--vulkan/libvulkan/swapchain.h2
9 files changed, 242 insertions, 5 deletions
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 1264a4e56c..ed89fc6241 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -81,6 +81,9 @@ define NULL_HANDLE 0
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 6
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
+@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
+@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_NAME "VK_GOOGLE_display_timing"
+
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 4
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
@@ -753,6 +756,9 @@ enum VkStructureType {
VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000,
VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID = 1000010001,
+ //@extension("VK_GOOGLE_display_timing")
+ VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE = 1000092000,
+
//@extension("VK_EXT_debug_report")
VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
@@ -2916,6 +2922,34 @@ class VkSwapchainImageCreateInfoANDROID {
VkStructureType sType
const void* pNext
VkSwapchainImageUsageFlagBitsANDROID flags
+
+@extension("VK_GOOGLE_display_timing")
+class VkRefreshCycleDurationGOOGLE {
+ uint64_t minRefreshDuration
+ uint64_t maxRefreshDuration
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPastPresentationTimingGOOGLE {
+ uint32_t presentID
+ uint64_t desiredPresentTime
+ uint64_t actualPresentTime
+ uint64_t earliestPresentTime
+ uint64_t presentMargin
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPresentTimeGOOGLE {
+ uint32_t presentID
+ uint64_t desiredPresentTime
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPresentTimesInfoGOOGLE {
+ VkStructureType sType
+ const void* pNext
+ uint32_t swapchainCount
+ const VkPresentTimeGOOGLE* pTimes
}
@extension("VK_EXT_debug_report")
@@ -5835,6 +5869,41 @@ cmd VkResult vkQueueSignalReleaseImageANDROID(
return ?
}
+@extension("VK_GOOGLE_display_timing")
+cmd VkResult vkGetRefreshCycleDurationGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ deviceObject := GetDevice(device)
+ swapchainObject := GetSwapchain(swapchain)
+
+ displayTimingProperties := ?
+ pDisplayTimingProperties[0] = displayTimingProperties
+
+ return ?
+}
+
+@extension("VK_GOOGLE_display_timing")
+cmd VkResult vkGetPastPresentationTimingGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ u32* pPresentationTimingCount,
+ VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+ deviceObject := GetDevice(device)
+
+ count := as!u32(?)
+ pPresentationTimingCount[0] = count
+ presentationTimings := pPresentationTimings[0:count]
+
+ for i in (0 .. count) {
+ presentationTiming := ?
+ presentationTimings[i] = presentationTiming
+ State.Timings[presentationTiming] = new!PresentationTiming(device: device)
+ }
+
+ return ?
+}
+
@extension("VK_EXT_debug_report")
@external type void* PFN_vkDebugReportCallbackEXT
@extension("VK_EXT_debug_report")
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 6a02b9b9bc..6ddce8ff84 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -242,6 +242,7 @@ typedef enum VkStructureType {
VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
+ VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE = 1000092000,
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@@ -4126,6 +4127,52 @@ typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
} VkDedicatedAllocationMemoryAllocateInfoNV;
+#define VK_GOOGLE_display_timing 1
+#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
+#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
+
+typedef struct VkRefreshCycleDurationGOOGLE {
+ uint64_t minRefreshDuration;
+ uint64_t maxRefreshDuration;
+} VkRefreshCycleDurationGOOGLE;
+
+typedef struct VkPastPresentationTimingGOOGLE {
+ uint32_t presentID;
+ uint64_t desiredPresentTime;
+ uint64_t actualPresentTime;
+ uint64_t earliestPresentTime;
+ uint64_t presentMargin;
+} VkPastPresentationTimingGOOGLE;
+
+typedef struct VkPresentTimeGOOGLE {
+ uint32_t presentID;
+ uint64_t desiredPresentTime;
+} VkPresentTimeGOOGLE;
+
+typedef struct VkPresentTimesInfoGOOGLE {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentTimeGOOGLE* pTimes;
+} VkPresentTimesInfoGOOGLE;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t* pPresentationTimingCount,
+ VkPastPresentationTimingGOOGLE* pPresentationTimings);
+#endif
+
#define VK_AMD_draw_indirect_count 1
#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index ca2a579b64..b4e256a8e8 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -425,6 +425,8 @@ VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapch
VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
return GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
@@ -1208,6 +1210,14 @@ VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroid
return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
}
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ return GetData(device).dispatch.GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
+}
+
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+ return GetData(device).dispatch.GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+}
+
} // anonymous namespace
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 7f8d274b60..918c1f5e07 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -177,6 +177,8 @@ struct DeviceDispatchTable {
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
PFN_vkQueuePresentKHR QueuePresentKHR;
+ PFN_vkGetRefreshCycleDurationGOOGLE GetRefreshCycleDurationGOOGLE;
+ PFN_vkGetPastPresentationTimingGOOGLE GetPastPresentationTimingGOOGLE;
// clang-format on
};
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index b27b36c2b3..2c70d465cc 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -700,6 +700,8 @@ VK_KHR_android_surface
VK_KHR_incremental_present
VK_KHR_surface
VK_KHR_swapchain
+VK_KHR_incremental_present
+VK_GOOGLE_display_timing
{{end}}
@@ -1147,6 +1149,7 @@ VK_KHR_swapchain
{{else if eq $ext "VK_KHR_swapchain"}}true
{{else if eq $ext "VK_KHR_android_surface"}}true
{{else if eq $ext "VK_KHR_incremental_present"}}true
+ {{else if eq $ext "VK_GOOGLE_display_timing"}}true
{{end}}
{{end}}
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index c59ba2488b..e27b3d17ca 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -73,6 +73,24 @@ VKAPI_ATTR VkResult checkedQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR
}
}
+VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+ return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
+ } else {
+ Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetRefreshCycleDurationGOOGLE not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult checkedGetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+ if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+ return GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+ } else {
+ Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetPastPresentationTimingGOOGLE not executed.");
+ return VK_SUCCESS;
+ }
+}
+
// clang-format on
const ProcHook g_proc_hooks[] = {
@@ -218,6 +236,13 @@ const ProcHook g_proc_hooks[] = {
nullptr,
},
{
+ "vkGetPastPresentationTimingGOOGLE",
+ ProcHook::DEVICE,
+ ProcHook::GOOGLE_display_timing,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPastPresentationTimingGOOGLE),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
+ },
+ {
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
ProcHook::INSTANCE,
ProcHook::KHR_surface,
@@ -246,6 +271,13 @@ const ProcHook g_proc_hooks[] = {
nullptr,
},
{
+ "vkGetRefreshCycleDurationGOOGLE",
+ ProcHook::DEVICE,
+ ProcHook::GOOGLE_display_timing,
+ reinterpret_cast<PFN_vkVoidFunction>(GetRefreshCycleDurationGOOGLE),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetRefreshCycleDurationGOOGLE),
+ },
+ {
"vkGetSwapchainGrallocUsage2ANDROID",
ProcHook::DEVICE,
ProcHook::ANDROID_native_buffer,
@@ -302,6 +334,7 @@ ProcHook::Extension GetProcHookExtension(const char* name) {
if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
+ if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
// clang-format on
return ProcHook::EXTENSION_UNKNOWN;
}
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 0228ef252d..167f88cc3b 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -38,6 +38,7 @@ struct ProcHook {
KHR_android_surface,
KHR_surface,
KHR_swapchain,
+ GOOGLE_display_timing,
EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3e87abf3c8..807b81a8ed 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -122,10 +122,13 @@ Surface* SurfaceFromHandle(VkSurfaceKHR handle) {
struct Swapchain {
Swapchain(Surface& surface_, uint32_t num_images_)
- : surface(surface_), num_images(num_images_) {}
+ : surface(surface_),
+ num_images(num_images_),
+ frame_timestamps_enabled(false) {}
Surface& surface;
uint32_t num_images;
+ bool frame_timestamps_enabled;
struct Image {
Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
@@ -728,6 +731,9 @@ void DestroySwapchainKHR(VkDevice device,
bool active = swapchain->surface.swapchain_handle == swapchain_handle;
ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
+ if (swapchain->frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, false);
+ }
for (uint32_t i = 0; i < swapchain->num_images; i++)
ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
if (active)
@@ -868,7 +874,8 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
VkResult final_result = VK_SUCCESS;
// Look at the pNext chain for supported extension structs:
- const VkPresentRegionsKHR* present_regions = NULL;
+ const VkPresentRegionsKHR* present_regions = nullptr;
+ const VkPresentTimesInfoGOOGLE* present_times = nullptr;
const VkPresentRegionsKHR* next =
reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
while (next) {
@@ -876,6 +883,10 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
present_regions = next;
break;
+ case VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE:
+ present_times =
+ reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
+ break;
default:
ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
next->sType);
@@ -887,10 +898,16 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
present_regions &&
present_regions->swapchainCount != present_info->swapchainCount,
"VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
+ ALOGV_IF(present_times &&
+ present_times->swapchainCount != present_info->swapchainCount,
+ "VkPresentTimesInfoGOOGLE::swapchainCount != "
+ "VkPresentInfo::swapchainCount");
const VkPresentRegionKHR* regions =
- (present_regions) ? present_regions->pRegions : NULL;
+ (present_regions) ? present_regions->pRegions : nullptr;
+ const VkPresentTimeGOOGLE* times =
+ (present_times) ? present_times->pTimes : nullptr;
const VkAllocationCallbacks* allocator = &GetData(device).allocator;
- android_native_rect_t* rects = NULL;
+ android_native_rect_t* rects = nullptr;
uint32_t nrects = 0;
for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
@@ -898,7 +915,8 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
*SwapchainFromHandle(present_info->pSwapchains[sc]);
uint32_t image_idx = present_info->pImageIndices[sc];
Swapchain::Image& img = swapchain.images[image_idx];
- const VkPresentRegionKHR* region = (regions) ? &regions[sc] : NULL;
+ const VkPresentRegionKHR* region = (regions) ? &regions[sc] : nullptr;
+ const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
VkResult swapchain_result = VK_SUCCESS;
VkResult result;
int err;
@@ -955,6 +973,19 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
}
native_window_set_surface_damage(window, rects, rcount);
}
+ if (time) {
+ if (!swapchain.frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, true);
+ swapchain.frame_timestamps_enabled = true;
+ }
+ // TODO(ianelliott): need to store the presentID (and
+ // desiredPresentTime), so it can be later correlated to
+ // this present. Probably modify the following function
+ // (and below) to plumb a path to store it in FrameEvents
+ // code, on the producer side.
+ native_window_set_buffers_timestamp(
+ window, static_cast<int64_t>(time->desiredPresentTime));
+ }
err = window->queueBuffer(window, img.buffer.get(), fence);
// queueBuffer always closes fence, even on error
if (err != 0) {
@@ -992,5 +1023,44 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
return final_result;
}
+VKAPI_ATTR
+VkResult GetRefreshCycleDurationGOOGLE(
+ VkDevice,
+ VkSwapchainKHR,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ VkResult result = VK_SUCCESS;
+
+ // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+ pDisplayTimingProperties->minRefreshDuration = 16666666666;
+ pDisplayTimingProperties->maxRefreshDuration = 16666666666;
+
+ return result;
+}
+
+VKAPI_ATTR
+VkResult GetPastPresentationTimingGOOGLE(
+ VkDevice,
+ VkSwapchainKHR swapchain_handle,
+ uint32_t* count,
+ VkPastPresentationTimingGOOGLE* timings) {
+ Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+ ANativeWindow* window = swapchain.surface.window.get();
+ VkResult result = VK_SUCCESS;
+
+ if (!swapchain.frame_timestamps_enabled) {
+ native_window_enable_frame_timestamps(window, true);
+ swapchain.frame_timestamps_enabled = true;
+ }
+
+ // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+ if (timings) {
+ *count = 0;
+ } else {
+ *count = 0;
+ }
+
+ return result;
+}
+
} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index 2c60c496c4..8aac427b7f 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -34,6 +34,8 @@ VKAPI_ATTR void DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain_ha
VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
// clang-format on
} // namespace driver