blob: e0d68793cfc1b7e165533f8596b93d659a30377f [file] [log] [blame]
Karl Schultz7b024b42018-08-30 16:18:18 -06001/* Copyright (c) 2018-2019 The Khronos Group Inc.
2 * Copyright (c) 2018-2019 Valve Corporation
3 * Copyright (c) 2018-2019 LunarG, Inc.
4 * Copyright (C) 2018-2019 Google Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#ifndef VULKAN_GPU_VALIDATION_H
21#define VULKAN_GPU_VALIDATION_H
22
23// Class to encapsulate Vulkan Device Memory allocations.
24// It allocates device memory in large chunks for efficiency and to avoid
25// hitting the device limit of the number of allocations.
26// This manager handles only fixed-sized blocks of "data_size" bytes.
27// The interface allows the caller to "get" and "put back" blocks.
28// The manager allocates and frees chunks as needed.
29
30class GpuDeviceMemoryManager {
31 public:
32 GpuDeviceMemoryManager(layer_data *dev_data, uint32_t data_size) {
33 uint32_t align = static_cast<uint32_t>(GetPhysicalDeviceProperties(dev_data)->limits.minStorageBufferOffsetAlignment);
34 if (0 == align) {
35 align = 1;
36 }
37 record_size_ = data_size;
38 // Round the requested size up to the next multiple of the storage buffer offset alignment
39 // so that we can address each block in the storage buffer using the offset.
40 block_size_ = ((record_size_ + align - 1) / align) * align;
41 blocks_per_chunk_ = kItemsPerChunk;
42 chunk_size_ = blocks_per_chunk_ * block_size_;
43 dev_data_ = dev_data;
44 }
45
46 ~GpuDeviceMemoryManager() {
47 for (auto &chunk : chunk_list_) {
48 FreeMemoryChunk(chunk);
49 }
50 chunk_list_.clear();
51 }
52
53 uint32_t GetBlockSize() { return block_size_; }
54
55 VkResult GetBlock(GpuDeviceMemoryBlock *block);
56 void PutBackBlock(VkBuffer buffer, VkDeviceMemory memory, uint32_t offset);
57 void PutBackBlock(GpuDeviceMemoryBlock &block);
58
59 private:
60 // Define allocation granularity of Vulkan resources.
61 // Things like device memory and descriptors are allocated in "chunks".
62 // This number should be chosen to try to avoid too many chunk allocations
63 // and chunk allocations that are too large.
64 static const uint32_t kItemsPerChunk = 512;
65
66 struct MemoryChunk {
67 VkBuffer buffer;
68 VkDeviceMemory memory;
69 std::vector<uint32_t> available_offsets;
70 };
71
72 layer_data *dev_data_;
73 uint32_t record_size_;
74 uint32_t block_size_;
75 uint32_t blocks_per_chunk_;
76 uint32_t chunk_size_;
77 std::list<MemoryChunk> chunk_list_;
78
79 bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex);
80 VkResult AllocMemoryChunk(MemoryChunk &chunk);
81 void FreeMemoryChunk(MemoryChunk &chunk);
82};
83
84// Class to encapsulate Descriptor Set allocation. This manager creates and destroys Descriptor Pools
85// as needed to satisfy requests for descriptor sets.
86class GpuDescriptorSetManager {
87 public:
88 GpuDescriptorSetManager(layer_data *dev_data) { dev_data_ = dev_data; }
89
90 ~GpuDescriptorSetManager() {
91 for (auto &pool : desc_pool_map_) {
92 GetDispatchTable(dev_data_)->DestroyDescriptorPool(GetDevice(dev_data_), pool.first, NULL);
93 }
94 desc_pool_map_.clear();
95 }
96
97 VkResult GetDescriptorSets(uint32_t count, VkDescriptorPool *pool, std::vector<VkDescriptorSet> *desc_sets);
98 void PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set);
99
100 private:
101 static const uint32_t kItemsPerChunk = 512;
102 struct PoolTracker {
103 uint32_t size;
104 uint32_t used;
105 };
106
107 layer_data *dev_data_;
108 std::unordered_map<VkDescriptorPool, struct PoolTracker> desc_pool_map_;
109};
110
111using mutex_t = std::mutex;
112using lock_guard_t = std::lock_guard<mutex_t>;
113using unique_lock_t = std::unique_lock<mutex_t>;
114
115std::unique_ptr<safe_VkDeviceCreateInfo> GpuPreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
116 VkPhysicalDeviceFeatures *supported_features);
117void GpuPostCallRecordCreateDevice(layer_data *dev_data);
118void GpuPreCallRecordDestroyDevice(layer_data *dev_data);
119void GpuPostCallRecordAllocateCommandBuffers(layer_data *dev_data, const VkCommandBufferAllocateInfo *pCreateInfo,
120 VkCommandBuffer *pCommandBuffer);
121void GpuPreCallRecordFreeCommandBuffers(layer_data *dev_data, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers);
122VkResult GpuOverrideDispatchCreateShaderModule(layer_data *dev_data, const VkShaderModuleCreateInfo *pCreateInfo,
123 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
124 uint32_t *unique_shader_id);
125VkResult GpuOverrideDispatchCreatePipelineLayout(layer_data *dev_data, const VkPipelineLayoutCreateInfo *pCreateInfo,
126 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout);
127void GpuPostCallDispatchCmdBindPipeline(layer_data *dev_data, VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
128 VkPipeline pipeline);
129void GpuPostCallQueueSubmit(const layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
130 VkFence fence, mutex_t &global_lock);
131void GpuPreCallValidateCmdWaitEvents(layer_data *dev_data, VkPipelineStageFlags sourceStageMask);
132std::vector<safe_VkGraphicsPipelineCreateInfo> GpuPreCallRecordCreateGraphicsPipelines(
133 layer_data *dev_data, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo *pCreateInfos,
134 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines, std::vector<std::unique_ptr<PIPELINE_STATE>> &pipe_state);
135void GpuPostCallRecordCreateGraphicsPipelines(layer_data *dev_data, const uint32_t count,
136 const VkGraphicsPipelineCreateInfo *pCreateInfos,
137 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines);
138void GpuPreCallRecordDestroyPipeline(layer_data *dev_data, const VkPipeline pipeline);
139
140#endif // VULKAN_GPU_VALIDATION_H