Get timestamp period from device

- Get timestamp period on each backend
  D3D12: Get GPU frequency(HZ) from queue and calculate the period in ns
  Vulkan: Get timestampPeriod from device properties
  Metal and others: don't need the period

Bug: dawn:434
Change-Id: Ia5588a3dccadfe92d7384b9fdf1e6848c6e5c6e2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/36220
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index f089c76..c4a49e1 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -249,6 +249,8 @@
         virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0;
         virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0;
 
+        virtual float GetTimestampPeriodInNS() const = 0;
+
       protected:
         void SetToggle(Toggle toggle, bool isEnabled);
         void ForceSetToggle(Toggle toggle, bool isEnabled);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index d28767c..1d15eb5 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -77,6 +77,15 @@
             CheckHRESULT(mD3d12Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)),
                          "D3D12 create command queue"));
 
+        // Get GPU timestamp counter frequency (in ticks/second). This fails if the specified
+        // command queue doesn't support timestamps, D3D12_COMMAND_LIST_TYPE_DIRECT always support
+        // timestamps.
+        uint64_t frequency;
+        DAWN_TRY(CheckHRESULT(mCommandQueue->GetTimestampFrequency(&frequency),
+                              "D3D12 get timestamp frequency"));
+        // Calculate the period in nanoseconds by the frequency.
+        mTimestampPeriod = static_cast<float>(1e9) / frequency;
+
         // If PIX is not attached, the QueryInterface fails. Hence, no need to check the return
         // value.
         mCommandQueue.As(&mD3d12SharingContract);
@@ -655,4 +664,8 @@
         return 1;
     }
 
+    float Device::GetTimestampPeriodInNS() const {
+        return mTimestampPeriod;
+    }
+
 }}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index dc41448..732e187 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -141,6 +141,8 @@
         uint32_t GetOptimalBytesPerRowAlignment() const override;
         uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
 
+        float GetTimestampPeriodInNS() const override;
+
       private:
         using DeviceBase::DeviceBase;
 
@@ -236,6 +238,9 @@
         // Sampler cache needs to be destroyed before the CPU sampler allocator to ensure the final
         // release is called.
         std::unique_ptr<SamplerHeapCache> mSamplerHeapCache;
+
+        // The number of nanoseconds required for a timestamp query to be incremented by 1
+        float mTimestampPeriod = 1.0f;
     };
 
 }}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 53da499..f886fcd 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -71,6 +71,8 @@
         uint32_t GetOptimalBytesPerRowAlignment() const override;
         uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
 
+        float GetTimestampPeriodInNS() const override;
+
       private:
         Device(AdapterBase* adapter,
                NSPRef<id<MTLDevice>> mtlDevice,
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 37df56a..e570639 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -402,4 +402,8 @@
         return 1;
     }
 
+    float Device::GetTimestampPeriodInNS() const {
+        return 1.0f;
+    }
+
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index a821acf..5f5a283 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -470,4 +470,8 @@
         return 1;
     }
 
+    float Device::GetTimestampPeriodInNS() const {
+        return 1.0f;
+    }
+
 }}  // namespace dawn_native::null
diff --git a/src/dawn_native/null/DeviceNull.h b/src/dawn_native/null/DeviceNull.h
index 9a73a9b..7cc08df 100644
--- a/src/dawn_native/null/DeviceNull.h
+++ b/src/dawn_native/null/DeviceNull.h
@@ -116,6 +116,8 @@
         uint32_t GetOptimalBytesPerRowAlignment() const override;
         uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
 
+        float GetTimestampPeriodInNS() const override;
+
       private:
         using DeviceBase::DeviceBase;
 
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index 5ae56b8..1d81932 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -228,4 +228,8 @@
         return 1;
     }
 
+    float Device::GetTimestampPeriodInNS() const {
+        return 1.0f;
+    }
+
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h
index 1d1f087..f463aff 100644
--- a/src/dawn_native/opengl/DeviceGL.h
+++ b/src/dawn_native/opengl/DeviceGL.h
@@ -70,6 +70,8 @@
         uint32_t GetOptimalBytesPerRowAlignment() const override;
         uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
 
+        float GetTimestampPeriodInNS() const override;
+
       private:
         Device(AdapterBase* adapter,
                const DeviceDescriptor* descriptor,
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 398cc57..3096ce4 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -945,4 +945,8 @@
         return mDeviceInfo.properties.limits.optimalBufferCopyOffsetAlignment;
     }
 
+    float Device::GetTimestampPeriodInNS() const {
+        return mDeviceInfo.properties.limits.timestampPeriod;
+    }
+
 }}  // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 40b11f7..2a62779 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -108,6 +108,8 @@
         uint32_t GetOptimalBytesPerRowAlignment() const override;
         uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
 
+        float GetTimestampPeriodInNS() const override;
+
       private:
         Device(Adapter* adapter, const DeviceDescriptor* descriptor);