duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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 };