1 // Copyright 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <cstdint> 18 #include <memory> 19 #include <unordered_map> 20 21 #include "goldfish_vk_dispatch.h" 22 #include "vulkan/vulkan.h" 23 24 namespace gfxstream { 25 namespace vk { 26 27 struct ShaderData { 28 const uint32_t* code; // Pointer to shader's compiled spir-v code 29 const size_t size; // size of the code in bytes 30 }; 31 32 struct Etc2PushConstant { 33 uint32_t compFormat; 34 uint32_t baseLayer; 35 }; 36 37 struct AstcPushConstant { 38 uint32_t blockSize[2]; 39 uint32_t baseLayer; 40 uint32_t smallBlock; 41 }; 42 43 // Holds the Vulkan resources for the GPU decompression pipeline of a given emulated texture format. 44 // GpuDecompressionPipeline should be reused, use GpuDecompressionPipelineManager for that. 45 class GpuDecompressionPipeline { 46 public: 47 // Factory method. Returns null if pipeline initialization failed. 48 static std::unique_ptr<GpuDecompressionPipeline> create( 49 VulkanDispatch* vk, VkDevice device, VkFormat compressedFormat, 50 VkImageType imageType, VkDescriptorSetLayout descriptorSetLayout, 51 VkPipelineLayout pipelineLayout); 52 53 // GpuDecompressionPipeline is neither copyable nor movable. 54 // This allows us to safely release Vulkan resources in the destructor 55 GpuDecompressionPipeline(const GpuDecompressionPipeline&) = delete; 56 GpuDecompressionPipeline& operator=(const GpuDecompressionPipeline&) = delete; 57 58 // Destructor, will release any Vulkan resource we hold 59 ~GpuDecompressionPipeline(); 60 61 // Accessors pipeline()62 VkPipeline pipeline() const { return mPipeline; } pipelineLayout()63 VkPipelineLayout pipelineLayout() const { return mPipelineLayout; } descriptorSetLayout()64 VkDescriptorSetLayout descriptorSetLayout() const { return mDescriptorSetLayout; } 65 66 private: 67 GpuDecompressionPipeline(VulkanDispatch* vk, VkDevice device, 68 VkFormat compressedFormat, VkImageType imageType, 69 VkDescriptorSetLayout descriptorSetLayout, 70 VkPipelineLayout pipelineLayout); 71 72 // Initializes the compute shader pipeline 73 bool initialize(); 74 75 // Member variables set in the constructor 76 VulkanDispatch* mVk; 77 VkDevice mDevice; 78 VkFormat mCompressedFormat; 79 VkImageType mImageType; 80 VkDescriptorSetLayout mDescriptorSetLayout; 81 VkPipelineLayout mPipelineLayout; 82 83 // Member variables set by initialize() 84 VkPipeline mPipeline = VK_NULL_HANDLE; 85 }; 86 87 enum class AstcDecoder{Old, NewRgb, NewBc3}; 88 89 // Acts as a cache for GpuDecompressionPipeline objects 90 // Currently no eviction strategy, but the maximum number of entries is bounded by the number of 91 // compressed formats that we emulate. 92 // Thread-safety: not thread safe. Access to members of this class must be synchronized externally. 93 class GpuDecompressionPipelineManager { 94 public: 95 // TODO(gregschlom) remove this once we fully remove the old decoder 96 static void setAstcDecoder(AstcDecoder value); 97 static AstcDecoder astcDecoder(); 98 99 GpuDecompressionPipelineManager(VulkanDispatch* vk, VkDevice device); 100 101 // Returns the cached pipeline for the decompression of a given image format and type. 102 // If the pipeline doesn't exist yet, it will be created and initialized. 103 // Returns null if initialization of the pipeline failed. 104 GpuDecompressionPipeline* get(VkFormat compressedFormat, VkImageType imageType); 105 106 // Erases everything from the cache 107 void clear(); 108 109 ~GpuDecompressionPipelineManager(); 110 111 // GpuDecompressionPipelineManager is neither copyable nor movable. 112 // This allows us to safely release Vulkan resources in the destructor 113 GpuDecompressionPipelineManager(const GpuDecompressionPipelineManager&) = delete; 114 GpuDecompressionPipelineManager& operator=(const GpuDecompressionPipelineManager&) = delete; 115 116 private: 117 VkDescriptorSetLayout getDescriptorSetLayout(); 118 VkPipelineLayout getPipelineLayout(VkFormat format); 119 120 std::unordered_map<const ShaderData*, std::unique_ptr<GpuDecompressionPipeline>> mPipelines; 121 122 VulkanDispatch* mVk = nullptr; 123 VkDevice mDevice = VK_NULL_HANDLE; 124 VkDescriptorSetLayout mDescriptorSetLayout = VK_NULL_HANDLE; 125 VkPipelineLayout mAstcPipelineLayout = VK_NULL_HANDLE; 126 VkPipelineLayout mEtc2PipelineLayout = VK_NULL_HANDLE; 127 }; 128 129 } // namespace vk 130 } // namespace gfxstream 131