1 /* 2 * Copyright (c) 2015-2016 The Khronos Group Inc. 3 * Copyright (c) 2015-2016 Valve Corporation 4 * Copyright (c) 2015-2016 LunarG, 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 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 19 * Author: Cody Northrop <cody (at) lunarg.com> 20 * Author: John Zulauf <jzulauf (at) lunarg.com> 21 */ 22 23 #ifndef VKTESTBINDING_H 24 #define VKTESTBINDING_H 25 26 #include <algorithm> 27 #include <assert.h> 28 #include <iterator> 29 #include <vector> 30 31 #include "vulkan/vulkan.h" 32 33 namespace vk_testing { 34 35 template <class Dst, class Src> 36 std::vector<Dst> MakeVkHandles(const std::vector<Src> &v) { 37 std::vector<Dst> handles; 38 handles.reserve(v.size()); 39 std::transform(v.begin(), v.end(), std::back_inserter(handles), [](const Src &o) { return o.handle(); }); 40 return handles; 41 } 42 43 template <class Dst, class Src> 44 std::vector<Dst> MakeVkHandles(const std::vector<Src *> &v) { 45 std::vector<Dst> handles; 46 handles.reserve(v.size()); 47 std::transform(v.begin(), v.end(), std::back_inserter(handles), [](const Src *o) { return o->handle(); }); 48 return handles; 49 } 50 51 typedef void (*ErrorCallback)(const char *expr, const char *file, unsigned int line, const char *function); 52 void set_error_callback(ErrorCallback callback); 53 54 class PhysicalDevice; 55 class Device; 56 class Queue; 57 class DeviceMemory; 58 class Fence; 59 class Semaphore; 60 class Event; 61 class QueryPool; 62 class Buffer; 63 class BufferView; 64 class Image; 65 class ImageView; 66 class DepthStencilView; 67 class Shader; 68 class Pipeline; 69 class PipelineDelta; 70 class Sampler; 71 class DescriptorSetLayout; 72 class PipelineLayout; 73 class DescriptorSetPool; 74 class DescriptorSet; 75 class CommandBuffer; 76 class CommandPool; 77 78 std::vector<VkLayerProperties> GetGlobalLayers(); 79 std::vector<VkExtensionProperties> GetGlobalExtensions(); 80 std::vector<VkExtensionProperties> GetGlobalExtensions(const char *pLayerName); 81 82 namespace internal { 83 84 template <typename T> 85 class Handle { 86 public: 87 const T &handle() const { return handle_; } 88 bool initialized() const { return (handle_ != T{}); } 89 90 protected: 91 typedef T handle_type; 92 93 explicit Handle() : handle_{} {} 94 explicit Handle(T handle) : handle_(handle) {} 95 96 // handles are non-copyable 97 Handle(const Handle &) = delete; 98 Handle &operator=(const Handle &) = delete; 99 100 // handles can be moved out 101 Handle(Handle &&src) NOEXCEPT : handle_{src.handle_} { src.handle_ = {}; } 102 Handle &operator=(Handle &&src) NOEXCEPT { 103 handle_ = src.handle_; 104 src.handle_ = {}; 105 return *this; 106 } 107 108 void init(T handle) { 109 assert(!initialized()); 110 handle_ = handle; 111 } 112 113 private: 114 T handle_; 115 }; 116 117 template <typename T> 118 class NonDispHandle : public Handle<T> { 119 protected: 120 explicit NonDispHandle() : Handle<T>(), dev_handle_(VK_NULL_HANDLE) {} 121 explicit NonDispHandle(VkDevice dev, T handle) : Handle<T>(handle), dev_handle_(dev) {} 122 123 NonDispHandle(NonDispHandle &&src) : Handle<T>(std::move(src)) { 124 dev_handle_ = src.dev_handle_; 125 src.dev_handle_ = VK_NULL_HANDLE; 126 } 127 NonDispHandle &operator=(NonDispHandle &&src) { 128 Handle<T>::operator=(std::move(src)); 129 dev_handle_ = src.dev_handle_; 130 src.dev_handle_ = VK_NULL_HANDLE; 131 return *this; 132 } 133 134 const VkDevice &device() const { return dev_handle_; } 135 136 void init(VkDevice dev, T handle) { 137 assert(!Handle<T>::initialized() && dev_handle_ == VK_NULL_HANDLE); 138 Handle<T>::init(handle); 139 dev_handle_ = dev; 140 } 141 142 private: 143 VkDevice dev_handle_; 144 }; 145 146 } // namespace internal 147 148 class PhysicalDevice : public internal::Handle<VkPhysicalDevice> { 149 public: 150 explicit PhysicalDevice(VkPhysicalDevice phy) : Handle(phy) { 151 memory_properties_ = memory_properties(); 152 device_properties_ = properties(); 153 } 154 155 VkPhysicalDeviceProperties properties() const; 156 VkPhysicalDeviceMemoryProperties memory_properties() const; 157 std::vector<VkQueueFamilyProperties> queue_properties() const; 158 VkPhysicalDeviceFeatures features() const; 159 160 bool set_memory_type(const uint32_t type_bits, VkMemoryAllocateInfo *info, const VkMemoryPropertyFlags properties, 161 const VkMemoryPropertyFlags forbid = 0) const; 162 163 // vkEnumerateDeviceExtensionProperties() 164 std::vector<VkExtensionProperties> extensions() const; 165 std::vector<VkExtensionProperties> extensions(const char *pLayerName) const; 166 167 // vkEnumerateLayers() 168 std::vector<VkLayerProperties> layers() const; 169 170 private: 171 void add_extension_dependencies(uint32_t dependency_count, VkExtensionProperties *depencency_props, 172 std::vector<VkExtensionProperties> &ext_list); 173 174 VkPhysicalDeviceMemoryProperties memory_properties_; 175 176 VkPhysicalDeviceProperties device_properties_; 177 }; 178 179 class QueueCreateInfoArray { 180 private: 181 std::vector<VkDeviceQueueCreateInfo> queue_info_; 182 std::vector<std::vector<float>> queue_priorities_; 183 184 public: 185 QueueCreateInfoArray(const std::vector<VkQueueFamilyProperties> &queue_props); 186 size_t size() const { return queue_info_.size(); } 187 const VkDeviceQueueCreateInfo *data() const { return queue_info_.data(); } 188 }; 189 190 class Device : public internal::Handle<VkDevice> { 191 public: 192 explicit Device(VkPhysicalDevice phy) : phy_(phy) {} 193 ~Device(); 194 195 // vkCreateDevice() 196 void init(const VkDeviceCreateInfo &info); 197 void init(std::vector<const char *> &extensions, 198 VkPhysicalDeviceFeatures *features = nullptr); // all queues, all extensions, etc 199 void init() { 200 std::vector<const char *> extensions; 201 init(extensions); 202 }; 203 204 const PhysicalDevice &phy() const { return phy_; } 205 206 std::vector<const char *> GetEnabledExtensions() { return enabled_extensions_; } 207 bool IsEnbledExtension(const char *extension); 208 209 // vkGetDeviceProcAddr() 210 PFN_vkVoidFunction get_proc(const char *name) const { return vkGetDeviceProcAddr(handle(), name); } 211 212 // vkGetDeviceQueue() 213 const std::vector<Queue *> &graphics_queues() const { return queues_[GRAPHICS]; } 214 const std::vector<Queue *> &compute_queues() { return queues_[COMPUTE]; } 215 const std::vector<Queue *> &dma_queues() { return queues_[DMA]; } 216 uint32_t queue_family_without_capabilities(VkQueueFlags capabilities); 217 uint32_t graphics_queue_node_index_; 218 219 struct Format { 220 VkFormat format; 221 VkImageTiling tiling; 222 VkFlags features; 223 }; 224 // vkGetFormatInfo() 225 VkFormatProperties format_properties(VkFormat format); 226 const std::vector<Format> &formats() const { return formats_; } 227 228 // vkDeviceWaitIdle() 229 void wait(); 230 231 // vkWaitForFences() 232 VkResult wait(const std::vector<const Fence *> &fences, bool wait_all, uint64_t timeout); 233 VkResult wait(const Fence &fence) { return wait(std::vector<const Fence *>(1, &fence), true, (uint64_t)-1); } 234 235 // vkUpdateDescriptorSets() 236 void update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes, const std::vector<VkCopyDescriptorSet> &copies); 237 void update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes) { 238 return update_descriptor_sets(writes, std::vector<VkCopyDescriptorSet>()); 239 } 240 241 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 242 VkDescriptorType type, uint32_t count, 243 const VkDescriptorImageInfo *image_info); 244 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 245 VkDescriptorType type, uint32_t count, 246 const VkDescriptorBufferInfo *buffer_info); 247 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 248 VkDescriptorType type, uint32_t count, const VkBufferView *buffer_views); 249 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 250 VkDescriptorType type, const std::vector<VkDescriptorImageInfo> &image_info); 251 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 252 VkDescriptorType type, const std::vector<VkDescriptorBufferInfo> &buffer_info); 253 static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 254 VkDescriptorType type, const std::vector<VkBufferView> &buffer_views); 255 256 static VkCopyDescriptorSet copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding, uint32_t src_array_element, 257 const DescriptorSet &dst_set, uint32_t dst_binding, uint32_t dst_array_element, 258 uint32_t count); 259 260 private: 261 enum QueueIndex { 262 GRAPHICS, 263 COMPUTE, 264 DMA, 265 QUEUE_COUNT, 266 }; 267 268 void init_queues(); 269 void init_formats(); 270 271 PhysicalDevice phy_; 272 273 std::vector<const char *> enabled_extensions_; 274 275 std::vector<Queue *> queues_[QUEUE_COUNT]; 276 std::vector<Format> formats_; 277 }; 278 279 class Queue : public internal::Handle<VkQueue> { 280 public: 281 explicit Queue(VkQueue queue, int index) : Handle(queue) { family_index_ = index; } 282 283 // vkQueueSubmit() 284 void submit(const std::vector<const CommandBuffer *> &cmds, Fence &fence); 285 void submit(const CommandBuffer &cmd, Fence &fence); 286 void submit(const CommandBuffer &cmd); 287 288 // vkQueueWaitIdle() 289 void wait(); 290 291 int get_family_index() { return family_index_; } 292 293 private: 294 int family_index_; 295 }; 296 297 class DeviceMemory : public internal::NonDispHandle<VkDeviceMemory> { 298 public: 299 ~DeviceMemory(); 300 301 // vkAllocateMemory() 302 void init(const Device &dev, const VkMemoryAllocateInfo &info); 303 304 // vkMapMemory() 305 const void *map(VkFlags flags) const; 306 void *map(VkFlags flags); 307 const void *map() const { return map(0); } 308 void *map() { return map(0); } 309 310 // vkUnmapMemory() 311 void unmap() const; 312 313 static VkMemoryAllocateInfo alloc_info(VkDeviceSize size, uint32_t memory_type_index); 314 static VkMemoryAllocateInfo get_resource_alloc_info(const vk_testing::Device &dev, const VkMemoryRequirements &reqs, 315 VkMemoryPropertyFlags mem_props); 316 }; 317 318 class Fence : public internal::NonDispHandle<VkFence> { 319 public: 320 ~Fence(); 321 322 // vkCreateFence() 323 void init(const Device &dev, const VkFenceCreateInfo &info); 324 325 // vkGetFenceStatus() 326 VkResult status() const { return vkGetFenceStatus(device(), handle()); } 327 328 static VkFenceCreateInfo create_info(VkFenceCreateFlags flags); 329 static VkFenceCreateInfo create_info(); 330 }; 331 332 class Semaphore : public internal::NonDispHandle<VkSemaphore> { 333 public: 334 ~Semaphore(); 335 336 // vkCreateSemaphore() 337 void init(const Device &dev, const VkSemaphoreCreateInfo &info); 338 339 static VkSemaphoreCreateInfo create_info(VkFlags flags); 340 }; 341 342 class Event : public internal::NonDispHandle<VkEvent> { 343 public: 344 ~Event(); 345 346 // vkCreateEvent() 347 void init(const Device &dev, const VkEventCreateInfo &info); 348 349 // vkGetEventStatus() 350 // vkSetEvent() 351 // vkResetEvent() 352 VkResult status() const { return vkGetEventStatus(device(), handle()); } 353 void set(); 354 void reset(); 355 356 static VkEventCreateInfo create_info(VkFlags flags); 357 }; 358 359 class QueryPool : public internal::NonDispHandle<VkQueryPool> { 360 public: 361 ~QueryPool(); 362 363 // vkCreateQueryPool() 364 void init(const Device &dev, const VkQueryPoolCreateInfo &info); 365 366 // vkGetQueryPoolResults() 367 VkResult results(uint32_t first, uint32_t count, size_t size, void *data, size_t stride); 368 369 static VkQueryPoolCreateInfo create_info(VkQueryType type, uint32_t slot_count); 370 }; 371 372 class Buffer : public internal::NonDispHandle<VkBuffer> { 373 public: 374 explicit Buffer() : NonDispHandle() {} 375 explicit Buffer(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info); } 376 explicit Buffer(const Device &dev, VkDeviceSize size) { init(dev, size); } 377 378 ~Buffer(); 379 380 // vkCreateBuffer() 381 void init(const Device &dev, const VkBufferCreateInfo &info, VkMemoryPropertyFlags mem_props); 382 void init(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info, 0); } 383 void init(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags mem_props) { init(dev, create_info(size, 0), mem_props); } 384 void init(const Device &dev, VkDeviceSize size) { init(dev, size, 0); } 385 void init_as_src(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs, 386 const std::vector<uint32_t> *queue_families = nullptr) { 387 init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, queue_families), reqs); 388 } 389 void init_as_dst(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs, 390 const std::vector<uint32_t> *queue_families = nullptr) { 391 init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queue_families), reqs); 392 } 393 void init_as_src_and_dst(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs, 394 const std::vector<uint32_t> *queue_families = nullptr) { 395 init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, queue_families), reqs); 396 } 397 void init_no_mem(const Device &dev, const VkBufferCreateInfo &info); 398 399 // get the internal memory 400 const DeviceMemory &memory() const { return internal_mem_; } 401 DeviceMemory &memory() { return internal_mem_; } 402 403 // vkGetObjectMemoryRequirements() 404 VkMemoryRequirements memory_requirements() const; 405 406 // vkBindObjectMemory() 407 void bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset); 408 409 static VkBufferCreateInfo create_info(VkDeviceSize size, VkFlags usage, const std::vector<uint32_t> *queue_families = nullptr); 410 411 VkBufferMemoryBarrier buffer_memory_barrier(VkFlags output_mask, VkFlags input_mask, VkDeviceSize offset, 412 VkDeviceSize size) const { 413 VkBufferMemoryBarrier barrier = {}; 414 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 415 barrier.buffer = handle(); 416 barrier.srcAccessMask = output_mask; 417 barrier.dstAccessMask = input_mask; 418 barrier.offset = offset; 419 barrier.size = size; 420 if (create_info_.sharingMode == VK_SHARING_MODE_CONCURRENT) { 421 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 422 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 423 } 424 return barrier; 425 } 426 427 private: 428 VkBufferCreateInfo create_info_; 429 430 DeviceMemory internal_mem_; 431 }; 432 433 class BufferView : public internal::NonDispHandle<VkBufferView> { 434 public: 435 ~BufferView(); 436 437 // vkCreateBufferView() 438 void init(const Device &dev, const VkBufferViewCreateInfo &info); 439 static VkBufferViewCreateInfo createInfo(VkBuffer buffer, VkFormat format, VkDeviceSize offset = 0, 440 VkDeviceSize range = VK_WHOLE_SIZE); 441 }; 442 443 inline VkBufferViewCreateInfo BufferView::createInfo(VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize range) { 444 VkBufferViewCreateInfo info = {}; 445 info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; 446 info.pNext = nullptr; 447 info.flags = VkFlags(0); 448 info.buffer = buffer; 449 info.format = format; 450 info.offset = offset; 451 info.range = range; 452 return info; 453 } 454 455 class Image : public internal::NonDispHandle<VkImage> { 456 public: 457 explicit Image() : NonDispHandle(), format_features_(0) {} 458 explicit Image(const Device &dev, const VkImageCreateInfo &info) : format_features_(0) { init(dev, info); } 459 460 ~Image(); 461 462 // vkCreateImage() 463 void init(const Device &dev, const VkImageCreateInfo &info, VkMemoryPropertyFlags mem_props); 464 void init(const Device &dev, const VkImageCreateInfo &info) { init(dev, info, 0); } 465 void init_no_mem(const Device &dev, const VkImageCreateInfo &info); 466 467 // get the internal memory 468 const DeviceMemory &memory() const { return internal_mem_; } 469 DeviceMemory &memory() { return internal_mem_; } 470 471 // vkGetObjectMemoryRequirements() 472 VkMemoryRequirements memory_requirements() const; 473 474 // vkBindObjectMemory() 475 void bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset); 476 477 // vkGetImageSubresourceLayout() 478 VkSubresourceLayout subresource_layout(const VkImageSubresource &subres) const; 479 VkSubresourceLayout subresource_layout(const VkImageSubresourceLayers &subres) const; 480 481 bool transparent() const; 482 bool copyable() const { return (format_features_ & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); } 483 484 VkImageSubresourceRange subresource_range(VkImageAspectFlagBits aspect) const { 485 return subresource_range(create_info_, aspect); 486 } 487 VkExtent3D extent() const { return create_info_.extent; } 488 VkExtent3D extent(uint32_t mip_level) const { return extent(create_info_.extent, mip_level); } 489 VkFormat format() const { return create_info_.format; } 490 VkImageUsageFlags usage() const { return create_info_.usage; } 491 VkSharingMode sharing_mode() const { return create_info_.sharingMode; } 492 VkImageMemoryBarrier image_memory_barrier(VkFlags output_mask, VkFlags input_mask, VkImageLayout old_layout, 493 VkImageLayout new_layout, const VkImageSubresourceRange &range) const { 494 VkImageMemoryBarrier barrier = {}; 495 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 496 barrier.srcAccessMask = output_mask; 497 barrier.dstAccessMask = input_mask; 498 barrier.oldLayout = old_layout; 499 barrier.newLayout = new_layout; 500 barrier.image = handle(); 501 barrier.subresourceRange = range; 502 503 if (sharing_mode() == VK_SHARING_MODE_CONCURRENT) { 504 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 505 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 506 } 507 return barrier; 508 } 509 510 static VkImageCreateInfo create_info(); 511 static VkImageSubresource subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer); 512 static VkImageSubresource subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer); 513 static VkImageSubresourceLayers subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer, 514 uint32_t array_size); 515 static VkImageSubresourceLayers subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer, 516 uint32_t array_size); 517 static VkImageSubresourceRange subresource_range(VkImageAspectFlags aspect_mask, uint32_t base_mip_level, uint32_t mip_levels, 518 uint32_t base_array_layer, uint32_t num_layers); 519 static VkImageSubresourceRange subresource_range(const VkImageCreateInfo &info, VkImageAspectFlags aspect_mask); 520 static VkImageSubresourceRange subresource_range(const VkImageSubresource &subres); 521 522 static VkExtent2D extent(int32_t width, int32_t height); 523 static VkExtent2D extent(const VkExtent2D &extent, uint32_t mip_level); 524 static VkExtent2D extent(const VkExtent3D &extent); 525 526 static VkExtent3D extent(int32_t width, int32_t height, int32_t depth); 527 static VkExtent3D extent(const VkExtent3D &extent, uint32_t mip_level); 528 529 private: 530 void init_info(const Device &dev, const VkImageCreateInfo &info); 531 532 VkImageCreateInfo create_info_; 533 VkFlags format_features_; 534 535 DeviceMemory internal_mem_; 536 }; 537 538 class ImageView : public internal::NonDispHandle<VkImageView> { 539 public: 540 ~ImageView(); 541 542 // vkCreateImageView() 543 void init(const Device &dev, const VkImageViewCreateInfo &info); 544 }; 545 546 class ShaderModule : public internal::NonDispHandle<VkShaderModule> { 547 public: 548 ~ShaderModule(); 549 550 // vkCreateShaderModule() 551 void init(const Device &dev, const VkShaderModuleCreateInfo &info); 552 VkResult init_try(const Device &dev, const VkShaderModuleCreateInfo &info); 553 554 static VkShaderModuleCreateInfo create_info(size_t code_size, const uint32_t *code, VkFlags flags); 555 }; 556 557 class Pipeline : public internal::NonDispHandle<VkPipeline> { 558 public: 559 ~Pipeline(); 560 561 // vkCreateGraphicsPipeline() 562 void init(const Device &dev, const VkGraphicsPipelineCreateInfo &info); 563 // vkCreateGraphicsPipelineDerivative() 564 void init(const Device &dev, const VkGraphicsPipelineCreateInfo &info, const VkPipeline basePipeline); 565 // vkCreateComputePipeline() 566 void init(const Device &dev, const VkComputePipelineCreateInfo &info); 567 // vkLoadPipeline() 568 void init(const Device &dev, size_t size, const void *data); 569 // vkLoadPipelineDerivative() 570 void init(const Device &dev, size_t size, const void *data, VkPipeline basePipeline); 571 572 // vkCreateGraphicsPipeline with error return 573 VkResult init_try(const Device &dev, const VkGraphicsPipelineCreateInfo &info); 574 575 // vkStorePipeline() 576 size_t store(size_t size, void *data); 577 }; 578 579 class PipelineLayout : public internal::NonDispHandle<VkPipelineLayout> { 580 public: 581 PipelineLayout() NOEXCEPT : NonDispHandle(){}; 582 ~PipelineLayout(); 583 584 // Move constructor for Visual Studio 2013 585 PipelineLayout(PipelineLayout &&src) : NonDispHandle(std::move(src)){}; 586 587 PipelineLayout &operator=(PipelineLayout &&src) { 588 this->~PipelineLayout(); 589 this->NonDispHandle::operator=(std::move(src)); 590 return *this; 591 }; 592 593 // vCreatePipelineLayout() 594 void init(const Device &dev, VkPipelineLayoutCreateInfo &info, const std::vector<const DescriptorSetLayout *> &layouts); 595 }; 596 597 class Sampler : public internal::NonDispHandle<VkSampler> { 598 public: 599 ~Sampler(); 600 601 // vkCreateSampler() 602 void init(const Device &dev, const VkSamplerCreateInfo &info); 603 }; 604 605 class DescriptorSetLayout : public internal::NonDispHandle<VkDescriptorSetLayout> { 606 public: 607 DescriptorSetLayout() NOEXCEPT : NonDispHandle(){}; 608 ~DescriptorSetLayout(); 609 610 // Move constructor for Visual Studio 2013 611 DescriptorSetLayout(DescriptorSetLayout &&src) : NonDispHandle(std::move(src)){}; 612 613 DescriptorSetLayout &operator=(DescriptorSetLayout &&src) NOEXCEPT { 614 this->~DescriptorSetLayout(); 615 this->NonDispHandle::operator=(std::move(src)); 616 return *this; 617 } 618 619 // vkCreateDescriptorSetLayout() 620 void init(const Device &dev, const VkDescriptorSetLayoutCreateInfo &info); 621 }; 622 623 class DescriptorPool : public internal::NonDispHandle<VkDescriptorPool> { 624 public: 625 ~DescriptorPool(); 626 627 // Descriptor sets allocated from this pool will need access to the original 628 // object 629 VkDescriptorPool GetObj() { return pool_; } 630 631 // vkCreateDescriptorPool() 632 void init(const Device &dev, const VkDescriptorPoolCreateInfo &info); 633 634 // vkResetDescriptorPool() 635 void reset(); 636 637 // vkFreeDescriptorSet() 638 void setDynamicUsage(bool isDynamic) { dynamic_usage_ = isDynamic; } 639 bool getDynamicUsage() { return dynamic_usage_; } 640 641 // vkAllocateDescriptorSets() 642 std::vector<DescriptorSet *> alloc_sets(const Device &dev, const std::vector<const DescriptorSetLayout *> &layouts); 643 std::vector<DescriptorSet *> alloc_sets(const Device &dev, const DescriptorSetLayout &layout, uint32_t count); 644 DescriptorSet *alloc_sets(const Device &dev, const DescriptorSetLayout &layout); 645 646 template <typename PoolSizes> 647 static VkDescriptorPoolCreateInfo create_info(VkDescriptorPoolCreateFlags flags, uint32_t max_sets, 648 const PoolSizes &pool_sizes); 649 650 private: 651 VkDescriptorPool pool_; 652 653 // Track whether this pool's usage is VK_DESCRIPTOR_POOL_USAGE_DYNAMIC 654 bool dynamic_usage_; 655 }; 656 657 template <typename PoolSizes> 658 inline VkDescriptorPoolCreateInfo DescriptorPool::create_info(VkDescriptorPoolCreateFlags flags, uint32_t max_sets, 659 const PoolSizes &pool_sizes) { 660 VkDescriptorPoolCreateInfo info{}; 661 info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 662 info.pNext = nullptr; 663 info.flags = flags; 664 info.maxSets = max_sets; 665 info.poolSizeCount = pool_sizes.size(); 666 info.pPoolSizes = (info.poolSizeCount) ? pool_sizes.data() : nullptr; 667 return info; 668 } 669 670 class DescriptorSet : public internal::NonDispHandle<VkDescriptorSet> { 671 public: 672 ~DescriptorSet(); 673 674 explicit DescriptorSet() : NonDispHandle() {} 675 explicit DescriptorSet(const Device &dev, DescriptorPool *pool, VkDescriptorSet set) : NonDispHandle(dev.handle(), set) { 676 containing_pool_ = pool; 677 } 678 679 private: 680 DescriptorPool *containing_pool_; 681 }; 682 683 class CommandPool : public internal::NonDispHandle<VkCommandPool> { 684 public: 685 ~CommandPool(); 686 687 explicit CommandPool() : NonDispHandle() {} 688 explicit CommandPool(const Device &dev, const VkCommandPoolCreateInfo &info) { init(dev, info); } 689 690 void init(const Device &dev, const VkCommandPoolCreateInfo &info); 691 692 static VkCommandPoolCreateInfo create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags); 693 }; 694 695 inline VkCommandPoolCreateInfo CommandPool::create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags) { 696 VkCommandPoolCreateInfo info = {}; 697 info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 698 info.queueFamilyIndex = queue_family_index; 699 info.flags = flags; 700 return info; 701 } 702 703 class CommandBuffer : public internal::Handle<VkCommandBuffer> { 704 public: 705 ~CommandBuffer(); 706 707 explicit CommandBuffer() : Handle() {} 708 explicit CommandBuffer(const Device &dev, const VkCommandBufferAllocateInfo &info) { init(dev, info); } 709 710 // vkAllocateCommandBuffers() 711 void init(const Device &dev, const VkCommandBufferAllocateInfo &info); 712 713 // vkBeginCommandBuffer() 714 void begin(const VkCommandBufferBeginInfo *info); 715 void begin(); 716 717 // vkEndCommandBuffer() 718 // vkResetCommandBuffer() 719 void end(); 720 void reset(VkCommandBufferResetFlags flags); 721 void reset() { reset(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); } 722 723 static VkCommandBufferAllocateInfo create_info(VkCommandPool const &pool); 724 725 private: 726 VkDevice dev_handle_; 727 VkCommandPool cmd_pool_; 728 }; 729 730 inline VkMemoryAllocateInfo DeviceMemory::alloc_info(VkDeviceSize size, uint32_t memory_type_index) { 731 VkMemoryAllocateInfo info = {}; 732 info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 733 info.allocationSize = size; 734 info.memoryTypeIndex = memory_type_index; 735 return info; 736 } 737 738 inline VkBufferCreateInfo Buffer::create_info(VkDeviceSize size, VkFlags usage, const std::vector<uint32_t> *queue_families) { 739 VkBufferCreateInfo info = {}; 740 info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 741 info.size = size; 742 info.usage = usage; 743 744 if (queue_families && queue_families->size() > 1) { 745 info.sharingMode = VK_SHARING_MODE_CONCURRENT; 746 info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families->size()); 747 info.pQueueFamilyIndices = queue_families->data(); 748 } 749 750 return info; 751 } 752 753 inline VkFenceCreateInfo Fence::create_info(VkFenceCreateFlags flags) { 754 VkFenceCreateInfo info = {}; 755 info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 756 info.flags = flags; 757 return info; 758 } 759 760 inline VkFenceCreateInfo Fence::create_info() { 761 VkFenceCreateInfo info = {}; 762 info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 763 return info; 764 } 765 766 inline VkSemaphoreCreateInfo Semaphore::create_info(VkFlags flags) { 767 VkSemaphoreCreateInfo info = {}; 768 info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 769 info.flags = flags; 770 return info; 771 } 772 773 inline VkEventCreateInfo Event::create_info(VkFlags flags) { 774 VkEventCreateInfo info = {}; 775 info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; 776 info.flags = flags; 777 return info; 778 } 779 780 inline VkQueryPoolCreateInfo QueryPool::create_info(VkQueryType type, uint32_t slot_count) { 781 VkQueryPoolCreateInfo info = {}; 782 info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; 783 info.queryType = type; 784 info.queryCount = slot_count; 785 return info; 786 } 787 788 inline VkImageCreateInfo Image::create_info() { 789 VkImageCreateInfo info = {}; 790 info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 791 info.extent.width = 1; 792 info.extent.height = 1; 793 info.extent.depth = 1; 794 info.mipLevels = 1; 795 info.arrayLayers = 1; 796 info.samples = VK_SAMPLE_COUNT_1_BIT; 797 return info; 798 } 799 800 inline VkImageSubresource Image::subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer) { 801 VkImageSubresource subres = {}; 802 if (aspect == 0) { 803 assert(!"Invalid VkImageAspectFlags"); 804 } 805 subres.aspectMask = aspect; 806 subres.mipLevel = mip_level; 807 subres.arrayLayer = array_layer; 808 return subres; 809 } 810 811 inline VkImageSubresource Image::subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer) { 812 return subresource(range.aspectMask, range.baseMipLevel + mip_level, range.baseArrayLayer + array_layer); 813 } 814 815 inline VkImageSubresourceLayers Image::subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer, 816 uint32_t array_size) { 817 VkImageSubresourceLayers subres = {}; 818 switch (aspect) { 819 case VK_IMAGE_ASPECT_COLOR_BIT: 820 case VK_IMAGE_ASPECT_DEPTH_BIT: 821 case VK_IMAGE_ASPECT_STENCIL_BIT: 822 case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT: 823 /* valid */ 824 break; 825 default: 826 assert(!"Invalid VkImageAspectFlags"); 827 } 828 subres.aspectMask = aspect; 829 subres.mipLevel = mip_level; 830 subres.baseArrayLayer = array_layer; 831 subres.layerCount = array_size; 832 return subres; 833 } 834 835 inline VkImageSubresourceLayers Image::subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer, 836 uint32_t array_size) { 837 return subresource(range.aspectMask, range.baseMipLevel + mip_level, range.baseArrayLayer + array_layer, array_size); 838 } 839 840 inline VkImageSubresourceRange Image::subresource_range(VkImageAspectFlags aspect_mask, uint32_t base_mip_level, 841 uint32_t mip_levels, uint32_t base_array_layer, uint32_t num_layers) { 842 VkImageSubresourceRange range = {}; 843 if (aspect_mask == 0) { 844 assert(!"Invalid VkImageAspectFlags"); 845 } 846 range.aspectMask = aspect_mask; 847 range.baseMipLevel = base_mip_level; 848 range.levelCount = mip_levels; 849 range.baseArrayLayer = base_array_layer; 850 range.layerCount = num_layers; 851 return range; 852 } 853 854 inline VkImageSubresourceRange Image::subresource_range(const VkImageCreateInfo &info, VkImageAspectFlags aspect_mask) { 855 return subresource_range(aspect_mask, 0, info.mipLevels, 0, info.arrayLayers); 856 } 857 858 inline VkImageSubresourceRange Image::subresource_range(const VkImageSubresource &subres) { 859 return subresource_range(subres.aspectMask, subres.mipLevel, 1, subres.arrayLayer, 1); 860 } 861 862 inline VkExtent2D Image::extent(int32_t width, int32_t height) { 863 VkExtent2D extent = {}; 864 extent.width = width; 865 extent.height = height; 866 return extent; 867 } 868 869 inline VkExtent2D Image::extent(const VkExtent2D &extent, uint32_t mip_level) { 870 const int32_t width = (extent.width >> mip_level) ? extent.width >> mip_level : 1; 871 const int32_t height = (extent.height >> mip_level) ? extent.height >> mip_level : 1; 872 return Image::extent(width, height); 873 } 874 875 inline VkExtent2D Image::extent(const VkExtent3D &extent) { return Image::extent(extent.width, extent.height); } 876 877 inline VkExtent3D Image::extent(int32_t width, int32_t height, int32_t depth) { 878 VkExtent3D extent = {}; 879 extent.width = width; 880 extent.height = height; 881 extent.depth = depth; 882 return extent; 883 } 884 885 inline VkExtent3D Image::extent(const VkExtent3D &extent, uint32_t mip_level) { 886 const int32_t width = (extent.width >> mip_level) ? extent.width >> mip_level : 1; 887 const int32_t height = (extent.height >> mip_level) ? extent.height >> mip_level : 1; 888 const int32_t depth = (extent.depth >> mip_level) ? extent.depth >> mip_level : 1; 889 return Image::extent(width, height, depth); 890 } 891 892 inline VkShaderModuleCreateInfo ShaderModule::create_info(size_t code_size, const uint32_t *code, VkFlags flags) { 893 VkShaderModuleCreateInfo info = {}; 894 info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 895 info.codeSize = code_size; 896 info.pCode = code; 897 info.flags = flags; 898 return info; 899 } 900 901 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 902 VkDescriptorType type, uint32_t count, 903 const VkDescriptorImageInfo *image_info) { 904 VkWriteDescriptorSet write = {}; 905 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 906 write.dstSet = set.handle(); 907 write.dstBinding = binding; 908 write.dstArrayElement = array_element; 909 write.descriptorCount = count; 910 write.descriptorType = type; 911 write.pImageInfo = image_info; 912 return write; 913 } 914 915 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 916 VkDescriptorType type, uint32_t count, 917 const VkDescriptorBufferInfo *buffer_info) { 918 VkWriteDescriptorSet write = {}; 919 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 920 write.dstSet = set.handle(); 921 write.dstBinding = binding; 922 write.dstArrayElement = array_element; 923 write.descriptorCount = count; 924 write.descriptorType = type; 925 write.pBufferInfo = buffer_info; 926 return write; 927 } 928 929 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 930 VkDescriptorType type, uint32_t count, const VkBufferView *buffer_views) { 931 VkWriteDescriptorSet write = {}; 932 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 933 write.dstSet = set.handle(); 934 write.dstBinding = binding; 935 write.dstArrayElement = array_element; 936 write.descriptorCount = count; 937 write.descriptorType = type; 938 write.pTexelBufferView = buffer_views; 939 return write; 940 } 941 942 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 943 VkDescriptorType type, 944 const std::vector<VkDescriptorImageInfo> &image_info) { 945 return write_descriptor_set(set, binding, array_element, type, image_info.size(), &image_info[0]); 946 } 947 948 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 949 VkDescriptorType type, 950 const std::vector<VkDescriptorBufferInfo> &buffer_info) { 951 return write_descriptor_set(set, binding, array_element, type, buffer_info.size(), &buffer_info[0]); 952 } 953 954 inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element, 955 VkDescriptorType type, const std::vector<VkBufferView> &buffer_views) { 956 return write_descriptor_set(set, binding, array_element, type, buffer_views.size(), &buffer_views[0]); 957 } 958 959 inline VkCopyDescriptorSet Device::copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding, 960 uint32_t src_array_element, const DescriptorSet &dst_set, 961 uint32_t dst_binding, uint32_t dst_array_element, uint32_t count) { 962 VkCopyDescriptorSet copy = {}; 963 copy.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; 964 copy.srcSet = src_set.handle(); 965 copy.srcBinding = src_binding; 966 copy.srcArrayElement = src_array_element; 967 copy.dstSet = dst_set.handle(); 968 copy.dstBinding = dst_binding; 969 copy.dstArrayElement = dst_array_element; 970 copy.descriptorCount = count; 971 972 return copy; 973 } 974 975 inline VkCommandBufferAllocateInfo CommandBuffer::create_info(VkCommandPool const &pool) { 976 VkCommandBufferAllocateInfo info = {}; 977 info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 978 info.commandPool = pool; 979 info.commandBufferCount = 1; 980 return info; 981 } 982 983 } // namespace vk_testing 984 985 #endif // VKTESTBINDING_H 986