huangcm
2025-09-01 53d8e046ac1bf2ebe94f671983e3d3be059df91a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
 
#include <vulkan/vulkan_core.h>
 
#include <memory>
#include <vector>
 
class Driver;
 
// Device provides a wrapper around a VkDevice with a number of helper functions
// for common test operations.
class Device
{
public:
   Device();
   ~Device();
 
   // CreateComputeDevice enumerates the physical devices, looking for a device
   // that supports compute.
   // If a compatible physical device is found, then a device is created and
   // assigned to out.
   // If a compatible physical device is not found, VK_SUCCESS will still be
   // returned (as there was no Vulkan error), but calling Device::IsValid()
   // on this device will return false.
   static VkResult CreateComputeDevice(
           Driver const *driver, VkInstance instance, std::unique_ptr<Device>& out);
 
   // IsValid returns true if the Device is initialized and can be used.
   bool IsValid() const;
 
   // CreateBuffer creates a new buffer with the
   // VK_BUFFER_USAGE_STORAGE_BUFFER_BIT usage, and
   // VK_SHARING_MODE_EXCLUSIVE sharing mode.
   VkResult CreateStorageBuffer(VkDeviceMemory memory, VkDeviceSize size,
           VkDeviceSize offset, VkBuffer *out) const;
 
   // CreateShaderModule creates a new shader module with the given SPIR-V
   // code.
   VkResult CreateShaderModule(const std::vector<uint32_t> &spirv,
           VkShaderModule *out) const;
 
   // CreateDescriptorSetLayout creates a new descriptor set layout with the
   // given bindings.
   VkResult CreateDescriptorSetLayout(
           const std::vector<VkDescriptorSetLayoutBinding> &bindings,
           VkDescriptorSetLayout *out) const;
 
   // CreatePipelineLayout creates a new single set descriptor set layout.
   VkResult CreatePipelineLayout(VkDescriptorSetLayout layout,
           VkPipelineLayout *out) const;
 
   // CreateComputePipeline creates a new compute pipeline with the entry point
   // "main".
   VkResult CreateComputePipeline(VkShaderModule module,
           VkPipelineLayout pipelineLayout,
           VkPipeline *out) const;
 
   // CreateStorageBufferDescriptorPool creates a new descriptor pool that can
   // hold descriptorCount storage buffers.
   VkResult CreateStorageBufferDescriptorPool(uint32_t descriptorCount,
           VkDescriptorPool *out) const;
 
   // AllocateDescriptorSet allocates a single descriptor set with the given
   // layout from pool.
   VkResult AllocateDescriptorSet(VkDescriptorPool pool,
           VkDescriptorSetLayout layout,
           VkDescriptorSet *out) const;
 
   // UpdateStorageBufferDescriptorSets updates the storage buffers in
   // descriptorSet with the given list of VkDescriptorBufferInfos.
   void UpdateStorageBufferDescriptorSets(VkDescriptorSet descriptorSet,
       const std::vector<VkDescriptorBufferInfo> &bufferInfos) const;
 
   // AllocateMemory allocates size bytes from a memory heap that has all the
   // given flag bits set.
   // If memory could not be allocated from any heap then
   // VK_ERROR_OUT_OF_DEVICE_MEMORY is returned.
   VkResult AllocateMemory(size_t size, VkMemoryPropertyFlags flags, VkDeviceMemory* out) const;
 
   // MapMemory wraps vkMapMemory, supplying the first VkDevice parameter.
   VkResult MapMemory(VkDeviceMemory memory, VkDeviceSize offset,
           VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) const;
 
   // UnmapMemory wraps vkUnmapMemory, supplying the first VkDevice parameter.
   void UnmapMemory(VkDeviceMemory memory) const;
 
   // CreateCommandPool creates a new command pool.
   VkResult CreateCommandPool(VkCommandPool* out) const;
 
   // AllocateCommandBuffer creates a new command buffer with a primary level.
   VkResult AllocateCommandBuffer(VkCommandPool pool, VkCommandBuffer* out) const;
 
   // BeginCommandBuffer begins writing to commandBuffer.
   VkResult BeginCommandBuffer(VkCommandBufferUsageFlags usage, VkCommandBuffer commandBuffer) const;
 
   // QueueSubmitAndWait submits the given command buffer and waits for it to
   // complete.
   VkResult QueueSubmitAndWait(VkCommandBuffer commandBuffer) const;
 
private:
   Device(Driver const *driver, VkDevice device, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
 
   static VkResult GetPhysicalDevices(
           Driver const *driver, VkInstance instance,
           std::vector<VkPhysicalDevice> &out);
 
   static int GetComputeQueueFamilyIndex(
           Driver const *driver, VkPhysicalDevice device);
 
   static std::vector<VkQueueFamilyProperties>
       GetPhysicalDeviceQueueFamilyProperties(
           Driver const *driver, VkPhysicalDevice device);
 
   Driver const *driver;
   VkDevice device;
   VkPhysicalDevice physicalDevice;
   uint32_t queueFamilyIndex;
};