1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
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 
16 #ifndef VULKAN_DEVICE_VK_H
17 #define VULKAN_DEVICE_VK_H
18 
19 #include <cstdint>
20 #include <vulkan/vulkan_core.h>
21 
22 #include <base/containers/unordered_map.h>
23 #include <base/containers/vector.h>
24 #include <base/util/formats.h>
25 #include <render/device/intf_device.h>
26 #include <render/device/pipeline_state_desc.h>
27 #include <render/namespace.h>
28 #include <render/vulkan/intf_device_vk.h>
29 
30 #include "device/device.h"
31 #include "platform_vk.h"
32 #include "vulkan/swapchain_vk.h"
33 
34 RENDER_BEGIN_NAMESPACE()
35 class ComputePipelineStateObject;
36 class GraphicsPipelineStateObject;
37 class GpuBuffer;
38 class GpuComputeProgram;
39 class GpuImage;
40 class GpuResourceManager;
41 class GpuSemaphore;
42 class GpuSampler;
43 class GpuShaderProgram;
44 class LowLevelDeviceVk;
45 class NodeContextDescriptorSetManager;
46 class NodeContextPoolManager;
47 class PlatformGpuMemoryAllocator;
48 class RenderFrameSync;
49 class RenderBackend;
50 class RenderContext;
51 class ShaderModule;
52 class Swapchain;
53 
54 struct GpuImagePlatformData;
55 struct SwapchainCreateInfo;
56 struct BackendSpecificImageDesc;
57 struct GpuAccelerationStructureDesc;
58 struct GpuBufferDesc;
59 struct GpuComputeProgramCreateData;
60 struct GpuImageDesc;
61 struct GpuSamplerDesc;
62 struct GpuShaderProgramCreateData;
63 struct PipelineLayout;
64 struct RenderHandle;
65 struct ShaderModuleCreateInfo;
66 struct QueueProperties;
67 
68 struct LowLevelQueueInfo {
69     VkQueueFlags queueFlags { 0 };
70     uint32_t queueFamilyIndex { ~0u };
71     uint32_t queueCount { 0 };
72     float priority { 1.0f };
73 };
74 
75 struct LowLevelGpuQueueVk {
76     VkQueue queue { VK_NULL_HANDLE };
77 
78     LowLevelQueueInfo queueInfo;
79 };
80 
81 struct DevicePlatformInternalDataVk {
82     BASE_NS::vector<BASE_NS::Format> supportedDepthFormats;
83 };
84 
85 struct DebugFunctionUtilitiesVk {
86     PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT { nullptr };
87     PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT { nullptr };
88     PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT { nullptr };
89 
90     VkDebugUtilsMessengerEXT debugMessenger { VK_NULL_HANDLE };
91     VkDebugReportCallbackEXT debugCallback { VK_NULL_HANDLE };
92 };
93 
94 class DeviceVk final : public Device {
95 public:
96     DeviceVk(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
97     ~DeviceVk() override;
98 
99     // From IDevice
100     DeviceBackendType GetBackendType() const override;
101     const DevicePlatformData& GetPlatformData() const override;
102     FormatProperties GetFormatProperties(const BASE_NS::Format format) const override;
103     AccelerationStructureBuildSizes GetAccelerationStructureBuildSizes(
104         const AccelerationStructureBuildGeometryInfo& geometry,
105         BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,
106         BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,
107         BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const override;
108     ILowLevelDevice& GetLowLevelDevice() const override;
109     void WaitForIdle() override;
110 
111     const DevicePlatformInternalDataVk& GetPlatformInternalDataVk() const;
112     const DevicePlatformDataVk& GetPlatformDataVk() const;
113 
114     PlatformGpuMemoryAllocator* GetPlatformGpuMemoryAllocator() override;
115 
116     BASE_NS::unique_ptr<Swapchain> CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo) override;
117     void DestroyDeviceSwapchain() override;
118 
119     void Activate() override;
120     void Deactivate() override;
121 
122     bool AllowThreadedProcessing() const override;
123 
124     GpuQueue GetValidGpuQueue(const GpuQueue& gpuQueue) const override;
125     uint32_t GetGpuQueueCount() const override;
126 
127     void InitializePipelineCache(BASE_NS::array_view<const uint8_t> initialData) override;
128     BASE_NS::vector<uint8_t> GetPipelineCache() const override;
129 
130     LowLevelGpuQueueVk GetGpuQueue(const GpuQueue& gpuQueue) const;
131     LowLevelGpuQueueVk GetPresentationGpuQueue() const;
132     BASE_NS::vector<LowLevelGpuQueueVk> GetLowLevelGpuQueues() const;
133 
134     BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuBufferDesc& desc) override;
135     BASE_NS::unique_ptr<GpuBuffer> CreateGpuBuffer(const GpuAccelerationStructureDesc& desc) override;
136 
137     BASE_NS::unique_ptr<GpuImage> CreateGpuImage(const GpuImageDesc& desc) override;
138     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
139         const GpuImageDesc& desc, const GpuImagePlatformData& platformData) override;
140     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
141         const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData) override;
142     BASE_NS::unique_ptr<GpuImage> CreateGpuImageView(
143         const GpuImageDesc& desc, const GpuImagePlatformData& platformData, const uintptr_t hwBuffer);
144     BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>> CreateGpuImageViews(const Swapchain& platformData) override;
145 
146     BASE_NS::unique_ptr<GpuSampler> CreateGpuSampler(const GpuSamplerDesc& desc) override;
147 
148     BASE_NS::unique_ptr<RenderFrameSync> CreateRenderFrameSync() override;
149 
150     BASE_NS::unique_ptr<RenderBackend> CreateRenderBackend(
151         GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr& queue) override;
152 
153     BASE_NS::unique_ptr<ShaderModule> CreateShaderModule(const ShaderModuleCreateInfo& data) override;
154     BASE_NS::unique_ptr<ShaderModule> CreateComputeShaderModule(const ShaderModuleCreateInfo& data) override;
155     BASE_NS::unique_ptr<GpuShaderProgram> CreateGpuShaderProgram(const GpuShaderProgramCreateData& data) override;
156     BASE_NS::unique_ptr<GpuComputeProgram> CreateGpuComputeProgram(const GpuComputeProgramCreateData& data) override;
157 
158     BASE_NS::unique_ptr<NodeContextDescriptorSetManager> CreateNodeContextDescriptorSetManager() override;
159     BASE_NS::unique_ptr<NodeContextPoolManager> CreateNodeContextPoolManager(
160         class GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue) override;
161 
162     BASE_NS::unique_ptr<GraphicsPipelineStateObject> CreateGraphicsPipelineStateObject(
163         const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
164         const VertexInputDeclarationView& vertexInputDeclaration,
165         const ShaderSpecializationConstantDataView& specializationConstants,
166         const BASE_NS::array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
167         const BASE_NS::array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
168         const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData) override;
169 
170     BASE_NS::unique_ptr<ComputePipelineStateObject> CreateComputePipelineStateObject(
171         const GpuComputeProgram& gpuProgram, const PipelineLayout& pipelineLayout,
172         const ShaderSpecializationConstantDataView& specializationConstants,
173         const LowLevelPipelineLayoutData* pipelineLayoutData) override;
174 
175     BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphore() override;
176     BASE_NS::unique_ptr<GpuSemaphore> CreateGpuSemaphoreView(const uint64_t handle) override;
177 
178     struct FeatureConfigurations {
179         float minSampleShading { 0.25f };
180     };
181     const FeatureConfigurations& GetFeatureConfigurations() const;
182 
183     struct CommonDeviceExtensions {
184         bool swapchain { false };
185 
186         // external_memory and external_memory_capabilities
187         bool externalMemory { false };
188         bool getMemoryRequirements2 { false };
189         bool samplerYcbcrConversion { false };
190         bool queueFamilyForeign { false };
191 
192         bool renderPass2 { false };
193         bool fragmentShadingRate { false };
194         bool multiView { false };
195         bool descriptorIndexing { false };
196     };
197     const CommonDeviceExtensions& GetCommonDeviceExtensions() const;
198     const PlatformDeviceExtensions& GetPlatformDeviceExtensions() const;
199     bool HasDeviceExtension(const BASE_NS::string_view extensionName) const;
200 
201     const DebugFunctionUtilitiesVk& GetDebugFunctionUtilities() const;
202     void CreateDebugFunctions();
203 
204     struct ExtFunctions {
205         // VK_KHR_sampler_ycbcr_conversion or Vulkan 1.1
206         PFN_vkCreateSamplerYcbcrConversion vkCreateSamplerYcbcrConversion { nullptr };
207         PFN_vkDestroySamplerYcbcrConversion vkDestroySamplerYcbcrConversion { nullptr };
208 
209         // VK_KHR_get_memory_requirements2 or Vulkan 1.1
210         PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2 { nullptr };
211         // VK_KHR_get_physical_device_properties2 or Vulkan 1.1
212         PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2 { nullptr };
213         PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2 { nullptr };
214 
215         // VK_KHR_create_renderpass2 or Vulkan 1.2
216         PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR { nullptr };
217 
218         // VK_KHR_swapchain
219         PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR { nullptr };
220 
221 #if (RENDER_VULKAN_FSR_ENABLED == 1)
222         // VK_KHR_fragment_shading_rate
223         PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR { nullptr };
224 #endif
225 
226 #if (RENDER_VULKAN_RT_ENABLED == 1)
227         // VK_KHR_acceleration_structure
228         PFN_vkGetAccelerationStructureBuildSizesKHR vkGetAccelerationStructureBuildSizesKHR { nullptr };
229         PFN_vkCmdBuildAccelerationStructuresKHR vkCmdBuildAccelerationStructuresKHR { nullptr };
230         PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR { nullptr };
231         PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR { nullptr };
232         PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR { nullptr };
233 #endif
234     };
235     const ExtFunctions& GetExtFunctions() const;
236     void CreateExtFunctions();
237 
238     const PlatformExtFunctions& GetPlatformExtFunctions() const;
239     void CreatePlatformExtFunctions();
240 
241 private:
242     BASE_NS::vector<QueueProperties> CheckExternalConfig(const BackendExtraVk* backendConfiguration);
243     void CreateInstance();
244     void CreatePhysicalDevice();
245     void CreateDevice(const BackendExtraVk* backendExtra, const BASE_NS::vector<LowLevelQueueInfo>& availableQueues);
246     void SortAvailableQueues(const BASE_NS::vector<LowLevelQueueInfo>& availableQueues);
247 
248     BASE_NS::unique_ptr<PlatformGpuMemoryAllocator> platformGpuMemoryAllocator_;
249 
250     DevicePlatformDataVk plat_;
251     bool ownInstanceAndDevice_ { true };
252     DevicePlatformInternalDataVk platInternal_;
253 
254     FeatureConfigurations featureConfigurations_;
255 
256     struct LowLevelGpuQueues {
257         BASE_NS::vector<LowLevelGpuQueueVk> graphicsQueues;
258         BASE_NS::vector<LowLevelGpuQueueVk> computeQueues;
259         BASE_NS::vector<LowLevelGpuQueueVk> transferQueues;
260 
261         LowLevelGpuQueueVk defaultQueue;
262     };
263     LowLevelGpuQueues lowLevelGpuQueues_;
264 
265     uint32_t gpuQueueCount_ { 0 };
266 
267     BASE_NS::unordered_map<BASE_NS::string, uint32_t> extensions_;
268     CommonDeviceExtensions commonDeviceExtensions_;
269     PlatformDeviceExtensions platformDeviceExtensions_;
270     BASE_NS::unique_ptr<LowLevelDeviceVk> lowLevelDevice_;
271 
272     BASE_NS::vector<FormatProperties> formatProperties_;
273 
274     DebugFunctionUtilitiesVk debugFunctionUtilities_;
275     ExtFunctions extFunctions_;
276     PlatformExtFunctions platformExtFunctions_;
277 };
278 
279 BASE_NS::unique_ptr<Device> CreateDeviceVk(RenderContext& renderContext, DeviceCreateInfo const& createInfo);
280 
281 // Wrapper for low level device access
282 class LowLevelDeviceVk final : public ILowLevelDeviceVk {
283 public:
284     explicit LowLevelDeviceVk(DeviceVk& deviceVk);
285     ~LowLevelDeviceVk() = default;
286 
287     DeviceBackendType GetBackendType() const override;
288     const DevicePlatformDataVk& GetPlatformDataVk() const override;
289 
290     GpuBufferPlatformDataVk GetBuffer(RenderHandle handle) const override;
291     GpuImagePlatformDataVk GetImage(RenderHandle handle) const override;
292     GpuSamplerPlatformDataVk GetSampler(RenderHandle handle) const override;
293 
294 private:
295     DeviceVk& deviceVk_;
296     GpuResourceManager& gpuResourceMgr_;
297 };
298 RENDER_END_NAMESPACE()
299 
300 #endif // VULKAN_DEVICE_VK_H
301