/* * Vulkan Example - Sparse texture residency example * * Copyright (C) 2016-2020 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ /* * Note : This sample is work-in-progress and works basically, but it's not yet finished */ #include "vulkanexamplebase.h" #include "VulkanglTFModel.h" #define ENABLE_VALIDATION false // Virtual texture page as a part of the partially resident texture // Contains memory bindings, offsets and status information struct VirtualTexturePage { VkOffset3D offset; VkExtent3D extent; VkSparseImageMemoryBind imageMemoryBind; // Sparse image memory bind for this page VkDeviceSize size; // Page (memory) size in bytes uint32_t mipLevel; // Mip level that this page belongs to uint32_t layer; // Array layer that this page belongs to uint32_t index; VirtualTexturePage(); bool resident(); void allocate(VkDevice device, uint32_t memoryTypeIndex); void release(VkDevice device); }; // Virtual texture object containing all pages struct VirtualTexture { VkDevice device; VkImage image; // Texture image handle VkBindSparseInfo bindSparseInfo; // Sparse queue binding information std::vector pages; // Contains all virtual pages of the texture std::vector sparseImageMemoryBinds; // Sparse image memory bindings of all memory-backed virtual tables std::vector opaqueMemoryBinds; // Sparse ópaque memory bindings for the mip tail (if present) VkSparseImageMemoryBindInfo imageMemoryBindInfo; // Sparse image memory bind info VkSparseImageOpaqueMemoryBindInfo opaqueMemoryBindInfo; // Sparse image opaque memory bind info (mip tail) uint32_t mipTailStart; // First mip level in mip tail VkSparseImageMemoryRequirements sparseImageMemoryRequirements; // @todo: Comment uint32_t memoryTypeIndex; // @todo: Comment // @todo: comment struct MipTailInfo { bool singleMipTail; bool alingedMipSize; } mipTailInfo; VirtualTexturePage *addPage(VkOffset3D offset, VkExtent3D extent, const VkDeviceSize size, const uint32_t mipLevel, uint32_t layer); void updateSparseBindInfo(); // @todo: replace with dtor? void destroy(); }; class VulkanExample : public VulkanExampleBase { public: //todo: comments struct SparseTexture : VirtualTexture { VkSampler sampler; VkImageLayout imageLayout; VkImageView view; VkDescriptorImageInfo descriptor; VkFormat format; uint32_t width, height; uint32_t mipLevels; uint32_t layerCount; } texture; vkglTF::Model plane; struct UboVS { glm::mat4 projection; glm::mat4 model; glm::vec4 viewPos; float lodBias = 0.0f; } uboVS; vks::Buffer uniformBufferVS; VkPipeline pipeline; VkPipelineLayout pipelineLayout; VkDescriptorSet descriptorSet; VkDescriptorSetLayout descriptorSetLayout; //todo: comment VkSemaphore bindSparseSemaphore = VK_NULL_HANDLE; VulkanExample(); ~VulkanExample(); virtual void getEnabledFeatures(); glm::uvec3 alignedDivision(const VkExtent3D& extent, const VkExtent3D& granularity); void prepareSparseTexture(uint32_t width, uint32_t height, uint32_t layerCount, VkFormat format); // @todo: move to dtor of texture void destroyTextureImage(SparseTexture texture); void buildCommandBuffers(); void draw(); void loadAssets(); void setupDescriptorPool(); void setupDescriptorSetLayout(); void setupDescriptorSet(); void preparePipelines(); void prepareUniformBuffers(); void updateUniformBuffers(); void prepare(); virtual void render(); void uploadContent(VirtualTexturePage page, VkImage image); void fillRandomPages(); void fillMipTail(); void flushRandomPages(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); };