// Copyright 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include #include #include "goldfish_vk_dispatch.h" #include "vulkan/vulkan.h" namespace gfxstream { namespace vk { struct ShaderData { const uint32_t* code; // Pointer to shader's compiled spir-v code const size_t size; // size of the code in bytes }; struct Etc2PushConstant { uint32_t compFormat; uint32_t baseLayer; }; struct AstcPushConstant { uint32_t blockSize[2]; uint32_t baseLayer; uint32_t smallBlock; }; // Holds the Vulkan resources for the GPU decompression pipeline of a given emulated texture format. // GpuDecompressionPipeline should be reused, use GpuDecompressionPipelineManager for that. class GpuDecompressionPipeline { public: // Factory method. Returns null if pipeline initialization failed. static std::unique_ptr create( VulkanDispatch* vk, VkDevice device, VkFormat compressedFormat, VkImageType imageType, VkDescriptorSetLayout descriptorSetLayout, VkPipelineLayout pipelineLayout); // GpuDecompressionPipeline is neither copyable nor movable. // This allows us to safely release Vulkan resources in the destructor GpuDecompressionPipeline(const GpuDecompressionPipeline&) = delete; GpuDecompressionPipeline& operator=(const GpuDecompressionPipeline&) = delete; // Destructor, will release any Vulkan resource we hold ~GpuDecompressionPipeline(); // Accessors VkPipeline pipeline() const { return mPipeline; } VkPipelineLayout pipelineLayout() const { return mPipelineLayout; } VkDescriptorSetLayout descriptorSetLayout() const { return mDescriptorSetLayout; } private: GpuDecompressionPipeline(VulkanDispatch* vk, VkDevice device, VkFormat compressedFormat, VkImageType imageType, VkDescriptorSetLayout descriptorSetLayout, VkPipelineLayout pipelineLayout); // Initializes the compute shader pipeline bool initialize(); // Member variables set in the constructor VulkanDispatch* mVk; VkDevice mDevice; VkFormat mCompressedFormat; VkImageType mImageType; VkDescriptorSetLayout mDescriptorSetLayout; VkPipelineLayout mPipelineLayout; // Member variables set by initialize() VkPipeline mPipeline = VK_NULL_HANDLE; }; enum class AstcDecoder{Old, NewRgb, NewBc3}; // Acts as a cache for GpuDecompressionPipeline objects // Currently no eviction strategy, but the maximum number of entries is bounded by the number of // compressed formats that we emulate. // Thread-safety: not thread safe. Access to members of this class must be synchronized externally. class GpuDecompressionPipelineManager { public: // TODO(gregschlom) remove this once we fully remove the old decoder static void setAstcDecoder(AstcDecoder value); static AstcDecoder astcDecoder(); GpuDecompressionPipelineManager(VulkanDispatch* vk, VkDevice device); // Returns the cached pipeline for the decompression of a given image format and type. // If the pipeline doesn't exist yet, it will be created and initialized. // Returns null if initialization of the pipeline failed. GpuDecompressionPipeline* get(VkFormat compressedFormat, VkImageType imageType); // Erases everything from the cache void clear(); ~GpuDecompressionPipelineManager(); // GpuDecompressionPipelineManager is neither copyable nor movable. // This allows us to safely release Vulkan resources in the destructor GpuDecompressionPipelineManager(const GpuDecompressionPipelineManager&) = delete; GpuDecompressionPipelineManager& operator=(const GpuDecompressionPipelineManager&) = delete; private: VkDescriptorSetLayout getDescriptorSetLayout(); VkPipelineLayout getPipelineLayout(VkFormat format); std::unordered_map> mPipelines; VulkanDispatch* mVk = nullptr; VkDevice mDevice = VK_NULL_HANDLE; VkDescriptorSetLayout mDescriptorSetLayout = VK_NULL_HANDLE; VkPipelineLayout mAstcPipelineLayout = VK_NULL_HANDLE; VkPipelineLayout mEtc2PipelineLayout = VK_NULL_HANDLE; }; } // namespace vk } // namespace gfxstream