1 // Copyright 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <vulkan/vulkan.h>
18 
19 #include <memory>
20 #include <mutex>
21 #include <vector>
22 #include <unordered_set>
23 
24 #include "vulkan/cereal/common/goldfish_vk_dispatch.h"
25 
26 namespace gfxstream {
27 namespace vk {
28 
29 // TODO: Support VK_AMD_buffer_marker.
30 class DeviceLostHelper {
31    public:
DeviceLostHelper()32     DeviceLostHelper() : mEnabled(false) {};
33 
34     DeviceLostHelper(const DeviceLostHelper&) = delete;
35     DeviceLostHelper& operator=(const DeviceLostHelper&) = delete;
36 
37     DeviceLostHelper(DeviceLostHelper&&) = delete;
38     DeviceLostHelper& operator=(const DeviceLostHelper&&) = delete;
39 
40     void enableWithNvidiaDeviceDiagnosticCheckpoints();
41 
42     void addNeededDeviceExtensions(std::vector<const char*>* deviceExtensions);
43 
44     void onBeginCommandBuffer(const VkCommandBuffer& commandBuffer, const VulkanDispatch* vk);
45     void onEndCommandBuffer(const VkCommandBuffer& commandBuffer, const VulkanDispatch* vk);
46 
47     void onResetCommandBuffer(const VkCommandBuffer& commandBuffer);
48     void onFreeCommandBuffer(const VkCommandBuffer& commandBuffer);
49 
50     struct DeviceWithQueues {
51         VkDevice device;
52         const VulkanDispatch* deviceDispatch;
53         std::vector<VkQueue> queues;
54     };
55     void onDeviceLost(const std::vector<DeviceWithQueues>& devicesWithQueues);
56 
57    private:
58     enum class MarkerType { kBegin, kEnd };
59 
60     struct CheckpointMarker {
61         VkCommandBuffer commandBuffer;
62         MarkerType type;
63     };
64 
65     struct CheckpointMarkerEq {
operatorCheckpointMarkerEq66         bool operator()(const CheckpointMarker& lhs, const CheckpointMarker& rhs) const {
67             return lhs.commandBuffer == rhs.commandBuffer && lhs.type == rhs.type;
68         }
69     };
70 
71     struct CheckpointMarkerHash {
operatorCheckpointMarkerHash72         size_t operator()(const CheckpointMarker& marker) const {
73             std::size_t h1 = (std::size_t)(marker.commandBuffer);
74             std::size_t h2 = (std::size_t)(marker.type);
75             return h1 ^ (h2 << 1);
76         }
77     };
78 
79     const void* createMarkerForCommandBuffer(const VkCommandBuffer& commandBuffer, MarkerType type);
80     void removeMarkersForCommandBuffer(const VkCommandBuffer& commandBuffer);
81 
82     bool mEnabled = false;
83 
84     std::mutex mMarkersMutex;
85     std::unordered_set<CheckpointMarker, CheckpointMarkerHash, CheckpointMarkerEq> mMarkers;
86 };
87 
88 }  // namespace vk
89 }  // namespace gfxstream
90