vulkan_texture.h (6478B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #pragma once 5 6 #include "gpu_device.h" 7 #include "gpu_texture.h" 8 #include "vulkan_loader.h" 9 #include "vulkan_stream_buffer.h" 10 11 #include <limits> 12 #include <memory> 13 14 class VulkanDevice; 15 16 class VulkanTexture final : public GPUTexture 17 { 18 public: 19 enum class Layout : u32 20 { 21 Undefined, 22 Preinitialized, 23 ColorAttachment, 24 DepthStencilAttachment, 25 ShaderReadOnly, 26 ClearDst, 27 TransferSrc, 28 TransferDst, 29 TransferSelf, 30 PresentSrc, 31 FeedbackLoop, 32 ReadWriteImage, 33 ComputeReadWriteImage, 34 General, 35 Count 36 }; 37 38 ~VulkanTexture() override; 39 40 static std::unique_ptr<VulkanTexture> Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, 41 Format format, VkFormat vk_format); 42 void Destroy(bool defer); 43 44 ALWAYS_INLINE VkImage GetImage() const { return m_image; } 45 ALWAYS_INLINE VkImageView GetView() const { return m_view; } 46 ALWAYS_INLINE Layout GetLayout() const { return m_layout; } 47 ALWAYS_INLINE VkFormat GetVkFormat() const { return m_vk_format; } 48 49 VkImageLayout GetVkLayout() const; 50 VkClearColorValue GetClearColorValue() const; 51 VkClearDepthStencilValue GetClearDepthValue() const; 52 53 bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override; 54 bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override; 55 void Unmap() override; 56 void MakeReadyForSampling() override; 57 58 void SetDebugName(std::string_view name) override; 59 60 void TransitionToLayout(Layout layout); 61 void CommitClear(); 62 void CommitClear(VkCommandBuffer cmdbuf); 63 64 // Used when the render pass is changing the image layout, or to force it to 65 // VK_IMAGE_LAYOUT_UNDEFINED, if the existing contents of the image is 66 // irrelevant and will not be loaded. 67 void OverrideImageLayout(Layout new_layout); 68 69 void TransitionToLayout(VkCommandBuffer command_buffer, Layout new_layout); 70 void TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, u32 start_layer, u32 num_layers, u32 start_level, 71 u32 num_levels, Layout old_layout, Layout new_layout); 72 73 static void TransitionSubresourcesToLayout(VkCommandBuffer command_buffer, VkImage image, Type type, u32 start_layer, 74 u32 num_layers, u32 start_level, u32 num_levels, Layout old_layout, 75 Layout new_layout); 76 77 // Call when the texture is bound to the pipeline, or read from in a copy. 78 ALWAYS_INLINE void SetUseFenceCounter(u64 counter) { m_use_fence_counter = counter; } 79 80 VkDescriptorSet GetDescriptorSetWithSampler(VkSampler sampler); 81 82 private: 83 VulkanTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type, Format format, VkImage image, 84 VmaAllocation allocation, VkImageView view, VkFormat vk_format); 85 86 VkCommandBuffer GetCommandBufferForUpdate(); 87 void CopyTextureDataForUpload(void* dst, const void* src, u32 width, u32 height, u32 pitch, u32 upload_pitch) const; 88 VkBuffer AllocateUploadStagingBuffer(const void* data, u32 pitch, u32 upload_pitch, u32 width, u32 height) const; 89 void UpdateFromBuffer(VkCommandBuffer cmdbuf, u32 x, u32 y, u32 width, u32 height, u32 layer, u32 level, u32 pitch, 90 VkBuffer buffer, u32 buffer_offset); 91 92 VkImage m_image = VK_NULL_HANDLE; 93 VmaAllocation m_allocation = VK_NULL_HANDLE; 94 VkImageView m_view = VK_NULL_HANDLE; 95 VkFormat m_vk_format = VK_FORMAT_UNDEFINED; 96 Layout m_layout = Layout::Undefined; 97 98 // Contains the fence counter when the texture was last used. 99 // When this matches the current fence counter, the texture was used this command buffer. 100 u64 m_use_fence_counter = 0; 101 102 // Single-bind-point descriptor/sampler pairs. 103 std::vector<std::pair<VkSampler, VkDescriptorSet>> m_descriptor_sets; 104 105 u16 m_map_x = 0; 106 u16 m_map_y = 0; 107 u16 m_map_width = 0; 108 u16 m_map_height = 0; 109 u8 m_map_layer = 0; 110 u8 m_map_level = 0; 111 }; 112 113 class VulkanSampler final : public GPUSampler 114 { 115 friend VulkanDevice; 116 117 public: 118 ~VulkanSampler() override; 119 120 ALWAYS_INLINE VkSampler GetSampler() const { return m_sampler; } 121 122 void SetDebugName(std::string_view name) override; 123 124 private: 125 VulkanSampler(VkSampler sampler); 126 127 VkSampler m_sampler; 128 }; 129 130 class VulkanTextureBuffer final : public GPUTextureBuffer 131 { 132 friend VulkanDevice; 133 134 public: 135 VulkanTextureBuffer(Format format, u32 size_in_elements); 136 ~VulkanTextureBuffer() override; 137 138 ALWAYS_INLINE VkBuffer GetBuffer() const { return m_buffer.GetBuffer(); } 139 ALWAYS_INLINE VkDescriptorSet GetDescriptorSet() const { return m_descriptor_set; } 140 141 bool CreateBuffer(bool ssbo); 142 void Destroy(bool defer); 143 144 // Inherited via GPUTextureBuffer 145 void* Map(u32 required_elements) override; 146 void Unmap(u32 used_elements) override; 147 148 void SetDebugName(std::string_view name) override; 149 150 private: 151 VulkanStreamBuffer m_buffer; 152 VkBufferView m_buffer_view = VK_NULL_HANDLE; 153 VkDescriptorSet m_descriptor_set = VK_NULL_HANDLE; 154 }; 155 156 class VulkanDownloadTexture final : public GPUDownloadTexture 157 { 158 public: 159 ~VulkanDownloadTexture() override; 160 161 static std::unique_ptr<VulkanDownloadTexture> Create(u32 width, u32 height, GPUTexture::Format format, void* memory, 162 size_t memory_size, u32 memory_stride); 163 164 void CopyFromTexture(u32 dst_x, u32 dst_y, GPUTexture* src, u32 src_x, u32 src_y, u32 width, u32 height, 165 u32 src_layer, u32 src_level, bool use_transfer_pitch) override; 166 167 bool Map(u32 x, u32 y, u32 width, u32 height) override; 168 void Unmap() override; 169 170 void Flush() override; 171 172 void SetDebugName(std::string_view name) override; 173 174 private: 175 VulkanDownloadTexture(u32 width, u32 height, GPUTexture::Format format, VmaAllocation allocation, 176 VkDeviceMemory memory, VkBuffer buffer, VkDeviceSize memory_offset, VkDeviceSize buffer_size, 177 const u8* map_ptr, u32 map_pitch); 178 179 VmaAllocation m_allocation = VK_NULL_HANDLE; 180 VkDeviceMemory m_memory = VK_NULL_HANDLE; 181 VkBuffer m_buffer = VK_NULL_HANDLE; 182 183 u64 m_copy_fence_counter = 0; 184 VkDeviceSize m_memory_offset = 0; 185 VkDeviceSize m_buffer_size = 0; 186 187 bool m_needs_cache_invalidate = false; 188 };