Fix timestamp queries on Android

It appears that timestamps in Vulkan behave much better if they are
written outside of render passes. This resolves issues seen on various
Android devices where timestamps for render passes were reporting 0 or
suspiciously low values. It also appears to have resolved an older
Qualcomm issue regarding resolving timestamp queries.

Because the issue is resolved, also re-enables the feature on Android.

Fixed: chromium:1504013, dawn:1559
Change-Id: I49769fd8bbd68b60e76f66ad80781affd8afb64f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162080
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/vulkan/CommandBufferVk.cpp b/src/dawn/native/vulkan/CommandBufferVk.cpp
index 1da153b..3391b44 100644
--- a/src/dawn/native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn/native/vulkan/CommandBufferVk.cpp
@@ -441,7 +441,8 @@
                              Device* device,
                              QuerySetBase* querySet,
                              uint32_t queryIndex,
-                             bool isRenderPass) {
+                             bool isRenderPass,
+                             VkPipelineStageFlagBits pipelineStage) {
     VkCommandBuffer commands = recordingContext->commandBuffer;
 
     // The queries must be reset between uses, and the reset command cannot be called in render
@@ -450,8 +451,8 @@
         device->fn.CmdResetQueryPool(commands, ToBackend(querySet)->GetHandle(), queryIndex, 1);
     }
 
-    device->fn.CmdWriteTimestamp(commands, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
-                                 ToBackend(querySet)->GetHandle(), queryIndex);
+    device->fn.CmdWriteTimestamp(commands, pipelineStage, ToBackend(querySet)->GetHandle(),
+                                 queryIndex);
 }
 
 void RecordResolveQuerySetCmd(VkCommandBuffer commands,
@@ -869,7 +870,7 @@
                 WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
 
                 RecordWriteTimestampCmd(recordingContext, device, cmd->querySet.Get(),
-                                        cmd->queryIndex, false);
+                                        cmd->queryIndex, false, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
                 break;
             }
 
@@ -974,7 +975,8 @@
         wgpu::kQuerySetIndexUndefined) {
         RecordWriteTimestampCmd(recordingContext, device,
                                 computePassCmd->timestampWrites.querySet.Get(),
-                                computePassCmd->timestampWrites.beginningOfPassWriteIndex, false);
+                                computePassCmd->timestampWrites.beginningOfPassWriteIndex, false,
+                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
     }
 
     VkCommandBuffer commands = recordingContext->commandBuffer;
@@ -991,9 +993,10 @@
                 // Write timestamp at the end of compute pass if it's set.
                 if (computePassCmd->timestampWrites.endOfPassWriteIndex !=
                     wgpu::kQuerySetIndexUndefined) {
-                    RecordWriteTimestampCmd(
-                        recordingContext, device, computePassCmd->timestampWrites.querySet.Get(),
-                        computePassCmd->timestampWrites.endOfPassWriteIndex, false);
+                    RecordWriteTimestampCmd(recordingContext, device,
+                                            computePassCmd->timestampWrites.querySet.Get(),
+                                            computePassCmd->timestampWrites.endOfPassWriteIndex,
+                                            false, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
                 }
                 return {};
             }
@@ -1102,7 +1105,7 @@
                 WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
 
                 RecordWriteTimestampCmd(recordingContext, device, cmd->querySet.Get(),
-                                        cmd->queryIndex, false);
+                                        cmd->queryIndex, false, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
                 break;
             }
 
@@ -1120,15 +1123,18 @@
     Device* device = ToBackend(GetDevice());
     VkCommandBuffer commands = recordingContext->commandBuffer;
 
-    DAWN_TRY(RecordBeginRenderPass(recordingContext, device, renderPassCmd));
-
     // Write timestamp at the beginning of render pass if it's set.
+    // We've observed that this must be called before the render pass or the timestamps produced
+    // are nonsensical on multiple Android devices.
     if (renderPassCmd->timestampWrites.beginningOfPassWriteIndex != wgpu::kQuerySetIndexUndefined) {
         RecordWriteTimestampCmd(recordingContext, device,
                                 renderPassCmd->timestampWrites.querySet.Get(),
-                                renderPassCmd->timestampWrites.beginningOfPassWriteIndex, true);
+                                renderPassCmd->timestampWrites.beginningOfPassWriteIndex, true,
+                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
     }
 
+    DAWN_TRY(RecordBeginRenderPass(recordingContext, device, renderPassCmd));
+
     // Set the default value for the dynamic state
     {
         device->fn.CmdSetLineWidth(commands, 1.0f);
@@ -1333,15 +1339,19 @@
             case Command::EndRenderPass: {
                 mCommands.NextCommand<EndRenderPassCmd>();
 
+                device->fn.CmdEndRenderPass(commands);
+
                 // Write timestamp at the end of render pass if it's set.
+                // We've observed that this must be called after the render pass ends or the
+                // timestamps produced are nonsensical on multiple Android devices.
                 if (renderPassCmd->timestampWrites.endOfPassWriteIndex !=
                     wgpu::kQuerySetIndexUndefined) {
-                    RecordWriteTimestampCmd(
-                        recordingContext, device, renderPassCmd->timestampWrites.querySet.Get(),
-                        renderPassCmd->timestampWrites.endOfPassWriteIndex, true);
+                    RecordWriteTimestampCmd(recordingContext, device,
+                                            renderPassCmd->timestampWrites.querySet.Get(),
+                                            renderPassCmd->timestampWrites.endOfPassWriteIndex,
+                                            true, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
                 }
 
-                device->fn.CmdEndRenderPass(commands);
                 return {};
             }
 
@@ -1435,7 +1445,7 @@
                 WriteTimestampCmd* cmd = mCommands.NextCommand<WriteTimestampCmd>();
 
                 RecordWriteTimestampCmd(recordingContext, device, cmd->querySet.Get(),
-                                        cmd->queryIndex, true);
+                                        cmd->queryIndex, true, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
                 break;
             }
 
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index 8f75ccc..19a1867 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -216,15 +216,10 @@
         EnableFeature(Feature::TextureCompressionASTC);
     }
 
-    // TODO(dawn:1559) Resolving timestamp queries after a render pass is failing on Qualcomm-based
-    // Android devices.
-    // TODO(crbug.com/1504013) Timestamp queries on Android do not return expected values.
-#if !DAWN_PLATFORM_IS(ANDROID)
     if (mDeviceInfo.properties.limits.timestampComputeAndGraphics == VK_TRUE) {
         EnableFeature(Feature::TimestampQuery);
         EnableFeature(Feature::ChromiumExperimentalTimestampQueryInsidePasses);
     }
-#endif
 
     if (IsDepthStencilFormatSupported(VK_FORMAT_D32_SFLOAT_S8_UINT)) {
         EnableFeature(Feature::Depth32FloatStencil8);