• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "device_vk.h"
17 
18 #include <cinttypes>
19 #include <cstdint>
20 #include <vulkan/vulkan_core.h>
21 
22 #include <base/containers/vector.h>
23 #include <base/math/mathf.h>
24 #include <render/intf_render_context.h>
25 #include <render/namespace.h>
26 
27 #include "device/device.h"
28 #include "device/gpu_program_util.h"
29 #include "device/gpu_resource_manager.h"
30 #include "device/shader_manager.h"
31 #include "device/shader_module.h"
32 #include "perf/cpu_perf_scope.h"
33 #include "platform_vk.h"
34 #include "render_context.h"
35 #include "util/log.h"
36 #include "vulkan/create_functions_vk.h"
37 #include "vulkan/gpu_buffer_vk.h"
38 #include "vulkan/gpu_image_vk.h"
39 #include "vulkan/gpu_memory_allocator_vk.h"
40 #include "vulkan/gpu_program_vk.h"
41 #include "vulkan/gpu_sampler_vk.h"
42 #include "vulkan/gpu_semaphore_vk.h"
43 #include "vulkan/node_context_descriptor_set_manager_vk.h"
44 #include "vulkan/node_context_pool_manager_vk.h"
45 #include "vulkan/pipeline_state_object_vk.h"
46 #include "vulkan/render_backend_vk.h"
47 #include "vulkan/render_frame_sync_vk.h"
48 #include "vulkan/shader_module_vk.h"
49 #include "vulkan/swapchain_vk.h"
50 #include "vulkan/validate_vk.h"
51 
52 using namespace BASE_NS;
53 
54 RENDER_BEGIN_NAMESPACE()
55 namespace {
56 constexpr string_view DEVICE_EXTENSION_SWAPCHAIN { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
57 
58 // promoted to 1.2, requires VK_KHR_create_renderpass2
59 constexpr string_view DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE { VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME };
60 constexpr string_view DEVICE_EXTENSION_CREATE_RENDERPASS2 { VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME };
61 
62 constexpr string_view DEVICE_EXTENSION_EXTERNAL_MEMORY { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME };
63 constexpr string_view DEVICE_EXTENSION_GET_MEMORY_REQUIREMENTS2 { VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME };
64 constexpr string_view DEVICE_EXTENSION_SAMPLER_YCBCR_CONVERSION { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME };
65 constexpr string_view DEVICE_EXTENSION_QUEUE_FAMILY_FOREIGN { VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME };
66 constexpr string_view DEVICE_EXTENSION_MULTIVIEW { VK_KHR_MULTIVIEW_EXTENSION_NAME };
67 constexpr string_view DEVICE_EXTENSION_MAINTENANCE4 = VK_KHR_MAINTENANCE_4_EXTENSION_NAME;
68 constexpr string_view DEVICE_EXTENSION_DESCRIPTOR_INDEXING = VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME;
69 
70 struct ChainWrapper {
71     void** ppNextFeatures { nullptr };
72     void** ppNextProperties { nullptr };
73 };
74 
75 struct PhysicalDeviceYcbcrStructsVk {
76     VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrConversionFeatures {};
77 };
78 
79 #if (RENDER_VULKAN_FSR_ENABLED == 1)
80 struct PhysicalDeviceFragmentShadingRateStructsVk {
81     VkPhysicalDeviceFragmentShadingRateFeaturesKHR physicalDeviceFragmentShadingRateFeatures;
82     VkPhysicalDeviceFragmentShadingRatePropertiesKHR physicalDeviceFragmentShadingRateProperties;
83 };
84 #endif
85 
86 #if (RENDER_VULKAN_RT_ENABLED == 1)
87 struct PhysicalDeviceRayTracingStructsVk {
88     VkPhysicalDeviceBufferDeviceAddressFeatures physicalDeviceBufferDeviceAddressFeatures;
89     VkPhysicalDeviceRayTracingPipelineFeaturesKHR physicalDeviceRayTracingPipelineFeatures;
90     VkPhysicalDeviceAccelerationStructureFeaturesKHR physicalDeviceAccelerationStructureFeatures;
91     VkPhysicalDeviceRayQueryFeaturesKHR physicalDeviceRayQueryFeatures;
92 };
93 #endif
94 
95 struct PhysicalDeviceMultiviewStructsVk {
96     VkPhysicalDeviceMultiviewFeaturesKHR physicalDeviceMultiviewFeatures;
97     VkPhysicalDeviceMultiviewPropertiesKHR physicalDeviceMultiviewProperties;
98 };
99 
100 struct PhysicalDeviceDesciptorIndexingStructsVk {
101     VkPhysicalDeviceDescriptorIndexingFeatures physicalDeviceDescriptorIndexingFeatures;
102     VkPhysicalDeviceDescriptorIndexingProperties physicalDeviceDescriptorIndexingProperties;
103 };
104 
105 struct PhysicalDeviceMaintenance4Vk {
106     VkPhysicalDeviceMaintenance4Features maintenance4Features {};
107 };
108 
109 struct ChainObjects {
110     unique_ptr<PhysicalDeviceYcbcrStructsVk> ycbcr;
111 #if (RENDER_VULKAN_RT_ENABLED == 1)
112     unique_ptr<PhysicalDeviceRayTracingStructsVk> rt;
113 #endif
114 #if (RENDER_VULKAN_FSR_ENABLED == 1)
115     unique_ptr<PhysicalDeviceFragmentShadingRateStructsVk> fsr;
116 #endif
117     unique_ptr<PhysicalDeviceMultiviewStructsVk> mv;
118     unique_ptr<PhysicalDeviceDesciptorIndexingStructsVk> di;
119     unique_ptr<PhysicalDeviceMaintenance4Vk> maintenance4;
120 };
121 
122 // fragment shading rate
123 #if (RENDER_VULKAN_FSR_ENABLED == 1)
124 // VK_KHR_fragment_shading_rate, requires VK_KHR_create_renderpass2, requires VK_KHR_get_physical_device_properties2
125 static constexpr string_view DEVICE_EXTENSION_FRAGMENT_SHADING_RATE { VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME };
126 
GetPhysicalDeviceFragmentShadingRateStructs(ChainObjects & co,ChainWrapper & cw)127 void GetPhysicalDeviceFragmentShadingRateStructs(ChainObjects& co, ChainWrapper& cw)
128 {
129     co.fsr = make_unique<PhysicalDeviceFragmentShadingRateStructsVk>();
130     auto& fsr = co.fsr;
131     fsr->physicalDeviceFragmentShadingRateFeatures = {
132         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, // sType
133         nullptr,                                                              // pNext
134         VK_FALSE,                                                             // pipelineFragmentShadingRate
135         VK_FALSE,                                                             // primitiveFragmentShadingRate
136         VK_FALSE,                                                             // attachmentFragmentShadingRate
137     };
138     *cw.ppNextFeatures = &fsr->physicalDeviceFragmentShadingRateFeatures;
139     cw.ppNextFeatures = &fsr->physicalDeviceFragmentShadingRateFeatures.pNext;
140 
141     fsr->physicalDeviceFragmentShadingRateProperties = {
142         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR, // sType
143         nullptr,                                                                // pNext
144     };
145     *cw.ppNextProperties = &fsr->physicalDeviceFragmentShadingRateProperties;
146     cw.ppNextProperties = &fsr->physicalDeviceFragmentShadingRateProperties.pNext;
147 }
148 #endif
149 
GetPhysicalDeviceMultiviewFeaturesStructs(ChainObjects & co,ChainWrapper & cw)150 void GetPhysicalDeviceMultiviewFeaturesStructs(ChainObjects& co, ChainWrapper& cw)
151 {
152     co.mv = make_unique<PhysicalDeviceMultiviewStructsVk>();
153     auto& mv = co.mv;
154     mv->physicalDeviceMultiviewFeatures = {
155         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR, // sType
156         nullptr,                                                  // pNext
157         VK_FALSE,                                                 // multiview
158         VK_FALSE,                                                 // multiviewGeometryShader
159         VK_FALSE,                                                 // multiviewTessellationShader
160     };
161     *cw.ppNextFeatures = &mv->physicalDeviceMultiviewFeatures;
162     cw.ppNextFeatures = &mv->physicalDeviceMultiviewFeatures.pNext;
163 
164     mv->physicalDeviceMultiviewProperties = {
165         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR, // sType
166         nullptr,                                                    // pNext
167         0,                                                          // maxMultiviewViewCount
168         0,                                                          // maxMultiviewInstanceIndex
169     };
170     *cw.ppNextProperties = &mv->physicalDeviceMultiviewProperties;
171     cw.ppNextProperties = &mv->physicalDeviceMultiviewProperties.pNext;
172 }
173 
GetPhysicalDeviceDescriptorIndexingFeaturesStructs(ChainObjects & co,ChainWrapper & cw)174 void GetPhysicalDeviceDescriptorIndexingFeaturesStructs(ChainObjects& co, ChainWrapper& cw)
175 {
176     co.di = make_unique<PhysicalDeviceDesciptorIndexingStructsVk>();
177     auto& di = co.di;
178     di->physicalDeviceDescriptorIndexingFeatures = {
179         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, // sType
180         nullptr,                                                        // pNext
181         VK_FALSE,                                                       // shaderInputAttachmentArrayDynamicIndexing
182         VK_FALSE,                                                       // shaderUniformTexelBufferArrayDynamicIndexing
183         VK_FALSE,                                                       // shaderStorageTexelBufferArrayDynamicIndexing
184         VK_FALSE,                                                       // shaderUniformBufferArrayNonUniformIndexing
185         VK_FALSE,                                                       // shaderSampledImageArrayNonUniformIndexing
186         VK_FALSE,                                                       // shaderStorageBufferArrayNonUniformIndexing
187         VK_FALSE,                                                       // shaderStorageImageArrayNonUniformIndexing
188         VK_FALSE,                                                       // shaderInputAttachmentArrayNonUniformIndexing
189         VK_FALSE, // shaderUniformTexelBufferArrayNonUniformIndexing
190         VK_FALSE, // shaderStorageTexelBufferArrayNonUniformIndexing
191         VK_FALSE, // descriptorBindingUniformBufferUpdateAfterBind
192         VK_FALSE, // descriptorBindingSampledImageUpdateAfterBind
193         VK_FALSE, // descriptorBindingStorageImageUpdateAfterBind
194         VK_FALSE, // descriptorBindingStorageBufferUpdateAfterBind
195         VK_FALSE, // descriptorBindingUniformTexelBufferUpdateAfterBind
196         VK_FALSE, // descriptorBindingStorageTexelBufferUpdateAfterBind
197         VK_FALSE, // descriptorBindingUpdateUnusedWhilePending
198         VK_FALSE, // descriptorBindingPartiallyBound
199         VK_FALSE, // descriptorBindingVariableDescriptorCount
200         VK_FALSE, // runtimeDescriptorArray
201     };
202     *cw.ppNextFeatures = &di->physicalDeviceDescriptorIndexingFeatures;
203     cw.ppNextFeatures = &di->physicalDeviceDescriptorIndexingFeatures.pNext;
204 
205     di->physicalDeviceDescriptorIndexingProperties = {
206         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES, // sType
207         nullptr,                                                          // pNext
208         0U,                                                               // maxUpdateAfterBindDescriptorsInAllPools
209         VK_FALSE, // shaderUniformBufferArrayNonUniformIndexingNative
210         VK_FALSE, // shaderSampledImageArrayNonUniformIndexingNative
211         VK_FALSE, // shaderStorageBufferArrayNonUniformIndexingNative
212         VK_FALSE, // shaderStorageImageArrayNonUniformIndexingNative
213         VK_FALSE, // shaderInputAttachmentArrayNonUniformIndexingNative
214         VK_FALSE, // robustBufferAccessUpdateAfterBind
215         VK_FALSE, // quadDivergentImplicitLod
216         0U,       // maxPerStageDescriptorUpdateAfterBindSamplers
217         0U,       // maxPerStageDescriptorUpdateAfterBindUniformBuffers
218         0U,       // maxPerStageDescriptorUpdateAfterBindStorageBuffers
219         0U,       // maxPerStageDescriptorUpdateAfterBindSampledImages
220         0U,       // maxPerStageDescriptorUpdateAfterBindStorageImages
221         0U,       // maxPerStageDescriptorUpdateAfterBindInputAttachments
222         0U,       // maxPerStageUpdateAfterBindResources
223         0U,       // maxDescriptorSetUpdateAfterBindSamplers
224         0U,       // maxDescriptorSetUpdateAfterBindUniformBuffers
225         0U,       // maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
226         0U,       // maxDescriptorSetUpdateAfterBindStorageBuffers
227         0U,       // maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
228         0U,       // maxDescriptorSetUpdateAfterBindSampledImages
229         0U,       // maxDescriptorSetUpdateAfterBindStorageImages
230         0U,       // maxDescriptorSetUpdateAfterBindInputAttachments
231     };
232     *cw.ppNextProperties = &di->physicalDeviceDescriptorIndexingProperties;
233     cw.ppNextProperties = &di->physicalDeviceDescriptorIndexingProperties.pNext;
234 }
235 
236 // ray-tracing
237 #if (RENDER_VULKAN_RT_ENABLED == 1)
FillAsBuildGeometryTriangles(const AsBuildGeometryInfo & geometry,const array_view<const AsGeometryTrianglesInfo> info,vector<VkAccelerationStructureGeometryKHR> & geometryData,vector<uint32_t> & maxPrimitiveCounts,uint32_t & arrayIndex)238 void FillAsBuildGeometryTriangles(const AsBuildGeometryInfo& geometry,
239     const array_view<const AsGeometryTrianglesInfo> info, vector<VkAccelerationStructureGeometryKHR>& geometryData,
240     vector<uint32_t>& maxPrimitiveCounts, uint32_t& arrayIndex)
241 {
242     for (const auto& ref : info) {
243         geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
244             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
245             nullptr,                                               // pNext
246             VkGeometryTypeKHR::VK_GEOMETRY_TYPE_TRIANGLES_KHR,     // geometryType
247             {},                                                    // geometry;
248             VkGeometryFlagsKHR(ref.geometryFlags),                 // flags
249         };
250         geometryData[arrayIndex].geometry.triangles = VkAccelerationStructureGeometryTrianglesDataKHR {
251             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, // sType
252             nullptr,                                                              // pNext
253             VkFormat(ref.vertexFormat),                                           // vertexFormat
254             {},                                                                   // vertexData
255             VkDeviceSize(ref.vertexStride),                                       // vertexStride
256             ref.maxVertex,                                                        // maxVertex
257             VkIndexType(ref.indexType),                                           // indexType
258             {},                                                                   // indexData
259             {},                                                                   // transformData
260         };
261         maxPrimitiveCounts[arrayIndex] = ref.indexCount / 3u; // triangles;
262         arrayIndex++;
263     }
264 }
265 
FillAsBuildGeometryAabbs(const AsBuildGeometryInfo & geometry,const array_view<const AsGeometryAabbsInfo> info,vector<VkAccelerationStructureGeometryKHR> & geometryData,vector<uint32_t> & maxPrimitiveCounts,uint32_t & arrayIndex)266 void FillAsBuildGeometryAabbs(const AsBuildGeometryInfo& geometry, const array_view<const AsGeometryAabbsInfo> info,
267     vector<VkAccelerationStructureGeometryKHR>& geometryData, vector<uint32_t>& maxPrimitiveCounts,
268     uint32_t& arrayIndex)
269 {
270     for (const auto& ref : info) {
271         geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
272             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
273             nullptr,                                               // pNext
274             VkGeometryTypeKHR::VK_GEOMETRY_TYPE_AABBS_KHR,         // geometryType
275             {},                                                    // geometry;
276             VkGeometryFlagsKHR(ref.geometryFlags),                 // flags
277         };
278         geometryData[arrayIndex].geometry.aabbs = VkAccelerationStructureGeometryAabbsDataKHR {
279             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR, // sType
280             nullptr,                                                          // pNext
281             {},                                                               // data
282             ref.stride,                                                       // stride
283         };
284         maxPrimitiveCounts[arrayIndex] = 1U;
285         arrayIndex++;
286     }
287 }
288 
FillAsBuildGeometryInstances(const AsBuildGeometryInfo & geometry,const array_view<const AsGeometryInstancesInfo> info,vector<VkAccelerationStructureGeometryKHR> & geometryData,vector<uint32_t> & maxPrimitiveCounts,uint32_t & arrayIndex)289 void FillAsBuildGeometryInstances(const AsBuildGeometryInfo& geometry,
290     const array_view<const AsGeometryInstancesInfo> info, vector<VkAccelerationStructureGeometryKHR>& geometryData,
291     vector<uint32_t>& maxPrimitiveCounts, uint32_t& arrayIndex)
292 {
293     for (const auto& ref : info) {
294         geometryData[arrayIndex] = VkAccelerationStructureGeometryKHR {
295             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, // sType
296             nullptr,                                               // pNext
297             VkGeometryTypeKHR::VK_GEOMETRY_TYPE_INSTANCES_KHR,     // geometryType
298             {},                                                    // geometry;
299             VkGeometryFlagsKHR(ref.geometryFlags),                 // flags
300         };
301         geometryData[arrayIndex].geometry.instances = VkAccelerationStructureGeometryInstancesDataKHR {
302             VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, // sType
303             nullptr,                                                              // pNext
304             ref.arrayOfPointers,                                                  // arrayOfPointers
305             {},                                                                   // data
306         };
307         maxPrimitiveCounts[arrayIndex] = ref.primitiveCount;
308         arrayIndex++;
309     }
310 }
311 
GetAsBuildGeometryCombine(const VkDevice device,const DeviceVk::ExtFunctions & extFunctions,const AsBuildGeometryInfo & geometry,const array_view<VkAccelerationStructureGeometryKHR> geometryData,const array_view<uint32_t> maxPrimitiveCounts,const uint32_t arrayIndex)312 AsBuildSizes GetAsBuildGeometryCombine(const VkDevice device, const DeviceVk::ExtFunctions& extFunctions,
313     const AsBuildGeometryInfo& geometry, const array_view<VkAccelerationStructureGeometryKHR> geometryData,
314     const array_view<uint32_t> maxPrimitiveCounts, const uint32_t arrayIndex)
315 {
316     const VkAccelerationStructureBuildGeometryInfoKHR geometryInfoVk {
317         VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, // sType
318         nullptr,                                                          // pNext
319         VkAccelerationStructureTypeKHR(geometry.type),                    // type
320         VkBuildAccelerationStructureFlagsKHR(geometry.flags),             // flags
321         VkBuildAccelerationStructureModeKHR(geometry.mode),               // mode
322         VK_NULL_HANDLE,                                                   // srcAccelerationStructure
323         VK_NULL_HANDLE,                                                   // dstAccelerationStructure
324         arrayIndex,                                                       // geometryCount
325         geometryData.data(),                                              // pGeometries
326         nullptr,                                                          // ppGeometries
327         {},                                                               // scratchData
328     };
329 
330     VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo {
331         VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR, // sType
332         nullptr,                                                       // pNext
333         0,                                                             // accelerationStructureSize
334         0,                                                             // updateScratchSize
335         0,                                                             // buildScratchSize
336     };
337     if ((arrayIndex > 0) && extFunctions.vkGetAccelerationStructureBuildSizesKHR) {
338         extFunctions.vkGetAccelerationStructureBuildSizesKHR(device, // device
339             VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,         // buildType,
340             &geometryInfoVk,                                         // pBuildInfo
341             maxPrimitiveCounts.data(),                               // pMaxPrimitiveCounts
342             &buildSizesInfo);                                        // pSizeInfo
343     }
344 
345     return AsBuildSizes {
346         static_cast<uint32_t>(buildSizesInfo.accelerationStructureSize),
347         static_cast<uint32_t>(buildSizesInfo.updateScratchSize),
348         static_cast<uint32_t>(buildSizesInfo.buildScratchSize),
349     };
350 }
351 
352 static constexpr string_view DEVICE_EXTENSION_ACCELERATION_STRUCTURE { "VK_KHR_acceleration_structure" };
353 static constexpr string_view DEVICE_EXTENSION_RAY_QUERY { "VK_KHR_ray_query" };
354 static constexpr string_view DEVICE_EXTENSION_DEFERRED_HOST_OPERATIONS { "VK_KHR_deferred_host_operations" };
355 static constexpr string_view DEVICE_EXTENSION_RAY_TRACING_PIPELINE { "VK_KHR_ray_tracing_pipeline" };
356 static constexpr string_view DEVICE_EXTENSION_PIPELINE_LIBRARY { "VK_KHR_pipeline_library" };
357 
GetPhysicalDeviceRayTracingStructs(ChainObjects & co,ChainWrapper & cw)358 void GetPhysicalDeviceRayTracingStructs(ChainObjects& co, ChainWrapper& cw)
359 {
360     co.rt = make_unique<PhysicalDeviceRayTracingStructsVk>();
361     auto& rt = co.rt;
362     rt->physicalDeviceBufferDeviceAddressFeatures = {
363         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES, // sType
364         nullptr,                                                          // pNext
365         VK_FALSE,                                                         // bufferDeviceAddress;
366         VK_FALSE,                                                         // bufferDeviceAddressCaptureReplay
367         VK_FALSE,                                                         // bufferDeviceAddressMultiDevice
368     };
369     rt->physicalDeviceRayTracingPipelineFeatures = {
370         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR, // sType
371         &rt->physicalDeviceBufferDeviceAddressFeatures,                      // pNext
372         VK_FALSE,                                                            // rayTracingPipeline;
373         VK_FALSE, // rayTracingPipelineShaderGroupHandleCaptureReplay;
374         VK_FALSE, // rayTracingPipelineShaderGroupHandleCaptureReplayMixed;
375         VK_FALSE, // rayTracingPipelineTraceRaysIndirect;
376         VK_FALSE, // rayTraversalPrimitiveCulling;
377     };
378     rt->physicalDeviceAccelerationStructureFeatures = {
379         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR, // sType
380         &rt->physicalDeviceRayTracingPipelineFeatures,                         // pNext
381         VK_FALSE,                                                              // accelerationStructure;
382         VK_FALSE,                                                              // accelerationStructureCaptureReplay
383         VK_FALSE,                                                              // accelerationStructureIndirectBuild
384         VK_FALSE,                                                              // accelerationStructureHostCommands
385         VK_FALSE, // descriptorBindingAccelerationStructureUpdateAfterBind
386     };
387     rt->physicalDeviceRayQueryFeatures = {
388         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR, // sType
389         &rt->physicalDeviceAccelerationStructureFeatures,         // pNext
390         true,                                                     // rayQuery
391     };
392 
393     *cw.ppNextFeatures = &rt->physicalDeviceRayQueryFeatures;
394     cw.ppNextFeatures = &rt->physicalDeviceBufferDeviceAddressFeatures.pNext;
395 }
396 #endif
397 
GetPhysicalDeviceYcbcrStructs(ChainObjects & co,ChainWrapper & cw)398 void GetPhysicalDeviceYcbcrStructs(ChainObjects& co, ChainWrapper& cw)
399 {
400     co.ycbcr = make_unique<PhysicalDeviceYcbcrStructsVk>();
401     auto& ycbcr = co.ycbcr;
402     ycbcr->ycbcrConversionFeatures = {
403         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, // sType
404         nullptr,                                                             // pNext
405         VK_FALSE,                                                            // samplerYcbcrConversion
406     };
407 
408     *cw.ppNextFeatures = &ycbcr->ycbcrConversionFeatures;
409     cw.ppNextFeatures = &ycbcr->ycbcrConversionFeatures.pNext;
410 }
411 
GetYcbcrExtFunctions(const VkInstance instance,DeviceVk::ExtFunctions & extFunctions)412 void GetYcbcrExtFunctions(const VkInstance instance, DeviceVk::ExtFunctions& extFunctions)
413 {
414     extFunctions.vkCreateSamplerYcbcrConversion =
415         (PFN_vkCreateSamplerYcbcrConversion)(void*)vkGetInstanceProcAddr(instance, "vkCreateSamplerYcbcrConversion");
416     if (!extFunctions.vkCreateSamplerYcbcrConversion) {
417         PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateSamplerYcbcrConversion");
418     }
419     extFunctions.vkDestroySamplerYcbcrConversion =
420         (PFN_vkDestroySamplerYcbcrConversion)vkGetInstanceProcAddr(instance, "vkDestroySamplerYcbcrConversion");
421     if (!extFunctions.vkDestroySamplerYcbcrConversion) {
422         PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkDestroySamplerYcbcrConversion");
423     }
424 }
425 
GetPhysicalDeviceMaintenance4Structs(ChainObjects & co,ChainWrapper & cw)426 void GetPhysicalDeviceMaintenance4Structs(ChainObjects& co, ChainWrapper& cw)
427 {
428     co.maintenance4 = make_unique<PhysicalDeviceMaintenance4Vk>();
429     auto& m4 = co.maintenance4;
430     m4->maintenance4Features = {
431         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, // sType
432         nullptr,                                                  // pNext
433         true,                                                     // maintenance4
434     };
435 
436     *cw.ppNextFeatures = &m4->maintenance4Features;
437     cw.ppNextFeatures = &m4->maintenance4Features.pNext;
438 }
439 
440 constexpr uint32_t MIN_ALLOCATION_BLOCK_SIZE { 4u * 1024u * 1024u };
441 constexpr uint32_t MAX_ALLOCATION_BLOCK_SIZE { 1024u * 1024u * 1024u };
442 constexpr const QueueProperties DEFAULT_QUEUE {
443     VK_QUEUE_GRAPHICS_BIT, // requiredFlags
444     1,                     // count
445     1.0f,                  // priority
446     false,                 // explicitFlags
447     true,                  // canPresent
448 };
449 
GetAllocatorCreateInfo(const uint32_t rcFlags,const BackendExtraVk * backendExtra)450 PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo GetAllocatorCreateInfo(
451     const uint32_t rcFlags, const BackendExtraVk* backendExtra)
452 {
453     // create default pools
454     PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo createInfo;
455     createInfo.createFlags =
456         ((rcFlags & RenderCreateInfo::CreateInfoFlagBits::CREATE_INFO_RAY_TRACING_BIT) > 0)
457             ? PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo::CreateInfoFlagBits::ENABLE_DEVICE_ADDRESSES_BIT
458             : 0U;
459     uint32_t dynamicUboByteSize = 16u * 1024u * 1024u;
460     if (backendExtra) {
461         const auto& sizes = backendExtra->gpuMemoryAllocatorSizes;
462         if (sizes.defaultAllocationBlockSize != ~0u) {
463             createInfo.preferredLargeHeapBlockSize = Math::min(
464                 MAX_ALLOCATION_BLOCK_SIZE, Math::max(sizes.defaultAllocationBlockSize, MIN_ALLOCATION_BLOCK_SIZE));
465         }
466         if (sizes.customAllocationDynamicUboBlockSize != ~0u) {
467             dynamicUboByteSize = Math::min(MAX_ALLOCATION_BLOCK_SIZE,
468                 Math::max(sizes.customAllocationDynamicUboBlockSize, MIN_ALLOCATION_BLOCK_SIZE));
469         }
470     }
471 
472     // staging
473     {
474         GpuBufferDesc desc;
475         desc.engineCreationFlags = EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_SINGLE_SHOT_STAGING;
476         desc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT |
477                                    MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
478         desc.usageFlags = BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT;
479         createInfo.customPools.push_back({
480             "STAGING_GPU_BUFFER",
481             PlatformGpuMemoryAllocator::MemoryAllocatorResourceType::GPU_BUFFER,
482             0u,
483             // if linear allocator is used, depending clients usage pattern, memory can be easily wasted.
484             false,
485             { move(desc) },
486         });
487     }
488     // dynamic uniform ring buffers
489     {
490         GpuBufferDesc desc;
491         desc.engineCreationFlags = EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER;
492         desc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT |
493                                    MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
494         desc.usageFlags = BufferUsageFlagBits::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
495         createInfo.customPools.push_back({
496             "DYNAMIC_UNIFORM_GPU_BUFFER",
497             PlatformGpuMemoryAllocator::MemoryAllocatorResourceType::GPU_BUFFER,
498             dynamicUboByteSize,
499             false,
500             { move(desc) },
501         });
502     }
503 
504     return createInfo;
505 }
506 
DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,VkDebugUtilsMessageTypeFlagsEXT,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)507 VkBool32 VKAPI_PTR DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
508     VkDebugUtilsMessageTypeFlagsEXT /* messageTypes */, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
509     void* pUserData)
510 {
511     if (pCallbackData && pCallbackData->pMessageIdName && pCallbackData->pMessage) {
512         uint32_t fi = 0U;
513         if (RenderContext* rc = reinterpret_cast<RenderContext*>(pUserData); rc) {
514             // might come here prior device creation
515             if (rc->ValidMembers()) {
516                 const Device& device = (const Device&)rc->GetDevice();
517                 fi = static_cast<uint32_t>(device.GetFrameCount());
518             }
519         }
520         if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
521             PLUGIN_LOG_E("FRAME: %u, %s: %s", fi, pCallbackData->pMessageIdName, pCallbackData->pMessage);
522         } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
523                    (VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)) {
524             PLUGIN_LOG_W("FRAME: %u, %s: %s", fi, pCallbackData->pMessageIdName, pCallbackData->pMessage);
525         } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
526                    VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
527             PLUGIN_LOG_I("FRAME: %u, %s: %s", fi, pCallbackData->pMessageIdName, pCallbackData->pMessage);
528         } else if ((VkDebugUtilsMessageSeverityFlagsEXT)messageSeverity &
529                    VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
530             PLUGIN_LOG_V("FRAME: %u, %s: %s", fi, pCallbackData->pMessageIdName, pCallbackData->pMessage);
531         }
532     }
533 
534     // The application should always return VK_FALSE.
535     return VK_FALSE;
536 }
537 
DebugReportCallback(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT,uint64_t,size_t,int32_t,const char *,const char * pMessage,void *)538 VkBool32 VKAPI_PTR DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT, uint64_t, size_t,
539     int32_t, const char*, const char* pMessage, void*)
540 {
541     if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
542         PLUGIN_LOG_E("%s", pMessage);
543     } else if (flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) {
544         PLUGIN_LOG_W("%s", pMessage);
545     } else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
546         PLUGIN_LOG_I("%s", pMessage);
547     } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
548         PLUGIN_LOG_D("%s", pMessage);
549     }
550     return VK_FALSE;
551 }
552 
EmplaceDeviceQueue(const VkDevice device,const LowLevelQueueInfo & aQueueInfo,vector<LowLevelGpuQueueVk> & aLowLevelQueues)553 void EmplaceDeviceQueue(
554     const VkDevice device, const LowLevelQueueInfo& aQueueInfo, vector<LowLevelGpuQueueVk>& aLowLevelQueues)
555 {
556     if (!device) {
557         return;
558     }
559 
560     for (uint32_t idx = 0; idx < aQueueInfo.queueCount; ++idx) {
561         VkQueue queue = VK_NULL_HANDLE;
562         vkGetDeviceQueue(device,         // device
563             aQueueInfo.queueFamilyIndex, // queueFamilyIndex
564             idx,                         // queueIndex
565             &queue);                     // pQueue
566         aLowLevelQueues.push_back(LowLevelGpuQueueVk { queue, aQueueInfo });
567     }
568 }
569 
CheckValidDepthFormats(const DevicePlatformDataVk & devicePlat,DevicePlatformInternalDataVk & dataInternal)570 void CheckValidDepthFormats(const DevicePlatformDataVk& devicePlat, DevicePlatformInternalDataVk& dataInternal)
571 {
572     constexpr uint32_t DEPTH_FORMAT_COUNT { 4 };
573     constexpr Format DEPTH_FORMATS[DEPTH_FORMAT_COUNT] = { BASE_FORMAT_D24_UNORM_S8_UINT, BASE_FORMAT_D32_SFLOAT,
574         BASE_FORMAT_D16_UNORM, BASE_FORMAT_X8_D24_UNORM_PACK32 };
575     for (const Format& format : DEPTH_FORMATS) {
576         VkFormatProperties formatProperties;
577         vkGetPhysicalDeviceFormatProperties(devicePlat.physicalDevice, // physicalDevice
578             (VkFormat)format,                                          // format
579             &formatProperties);                                        // pFormatProperties
580         const VkFormatFeatureFlags optimalTilingFeatureFlags = formatProperties.optimalTilingFeatures;
581         if (optimalTilingFeatureFlags & VkFormatFeatureFlagBits::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
582             dataInternal.supportedDepthFormats.push_back(format);
583         }
584     }
585 }
586 
GetPreferredDeviceExtensions(const BackendExtraVk * backendExtra,const uint32_t rcFlags,DevicePlatformDataVk & plat)587 vector<string_view> GetPreferredDeviceExtensions(
588     const BackendExtraVk* backendExtra, const uint32_t rcFlags, DevicePlatformDataVk& plat)
589 {
590     vector<string_view> extensions { DEVICE_EXTENSION_SWAPCHAIN };
591     extensions.push_back(DEVICE_EXTENSION_CREATE_RENDERPASS2);
592     extensions.push_back(DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE);
593     extensions.push_back(DEVICE_EXTENSION_MAINTENANCE4);
594     GetPlatformDeviceExtensions(extensions);
595 #if (RENDER_VULKAN_FSR_ENABLED == 1)
596     extensions.push_back(DEVICE_EXTENSION_FRAGMENT_SHADING_RATE);
597 #endif
598 #if (RENDER_VULKAN_RT_ENABLED == 1)
599     if (rcFlags & RenderCreateInfo::CreateInfoFlagBits::CREATE_INFO_RAY_TRACING_BIT) {
600         extensions.push_back(DEVICE_EXTENSION_ACCELERATION_STRUCTURE);
601         extensions.push_back(DEVICE_EXTENSION_RAY_TRACING_PIPELINE);
602         extensions.push_back(DEVICE_EXTENSION_RAY_QUERY);
603         extensions.push_back(DEVICE_EXTENSION_PIPELINE_LIBRARY);
604         extensions.push_back(DEVICE_EXTENSION_DEFERRED_HOST_OPERATIONS);
605     }
606 #endif
607     if (plat.deviceApiMinor >= 1) { // enable only for 1.1+
608         extensions.push_back(DEVICE_EXTENSION_MULTIVIEW);
609     }
610     if (plat.deviceApiMinor >= 2) { // enable only for 1.2+
611         extensions.push_back(DEVICE_EXTENSION_DESCRIPTOR_INDEXING);
612     }
613     if (backendExtra) {
614         for (const auto str : backendExtra->extensions.extensionNames) {
615             extensions.push_back(str);
616         }
617     }
618     return extensions;
619 }
620 
GetEnabledCommonDeviceExtensions(const unordered_map<string,uint32_t> & enabledDeviceExtensions)621 DeviceVk::CommonDeviceExtensions GetEnabledCommonDeviceExtensions(
622     const unordered_map<string, uint32_t>& enabledDeviceExtensions)
623 {
624     DeviceVk::CommonDeviceExtensions extensions;
625     extensions.swapchain = enabledDeviceExtensions.contains(DEVICE_EXTENSION_SWAPCHAIN);
626     // renderpass2 required on 1.2, we only use renderpass 2 when we need depth stencil resolve
627     extensions.renderPass2 = enabledDeviceExtensions.contains(DEVICE_EXTENSION_DEPTH_STENCIL_RESOLVE) &&
628                              enabledDeviceExtensions.contains(DEVICE_EXTENSION_CREATE_RENDERPASS2);
629     extensions.externalMemory = enabledDeviceExtensions.contains(DEVICE_EXTENSION_EXTERNAL_MEMORY);
630     extensions.getMemoryRequirements2 = enabledDeviceExtensions.contains(DEVICE_EXTENSION_GET_MEMORY_REQUIREMENTS2);
631     extensions.queueFamilyForeign = enabledDeviceExtensions.contains(DEVICE_EXTENSION_QUEUE_FAMILY_FOREIGN);
632     extensions.samplerYcbcrConversion = enabledDeviceExtensions.contains(DEVICE_EXTENSION_SAMPLER_YCBCR_CONVERSION);
633     extensions.multiView = enabledDeviceExtensions.contains(DEVICE_EXTENSION_MULTIVIEW);
634     extensions.descriptorIndexing = enabledDeviceExtensions.contains(DEVICE_EXTENSION_DESCRIPTOR_INDEXING);
635 #if (RENDER_VULKAN_FSR_ENABLED == 1)
636     extensions.fragmentShadingRate = enabledDeviceExtensions.contains(DEVICE_EXTENSION_FRAGMENT_SHADING_RATE);
637 #endif
638 
639     return extensions;
640 }
641 
GetCommonDevicePropertiesFunc(const ChainObjects & co)642 CommonDeviceProperties GetCommonDevicePropertiesFunc(const ChainObjects& co)
643 {
644     CommonDeviceProperties cdp;
645 #if (RENDER_VULKAN_FSR_ENABLED == 1)
646     if (co.fsr) {
647         const auto& fsrVk = co.fsr->physicalDeviceFragmentShadingRateProperties;
648         cdp.fragmentShadingRateProperties.minFragmentShadingRateAttachmentTexelSize = {
649             fsrVk.minFragmentShadingRateAttachmentTexelSize.width,
650             fsrVk.minFragmentShadingRateAttachmentTexelSize.height
651         };
652         cdp.fragmentShadingRateProperties.maxFragmentShadingRateAttachmentTexelSize = {
653             fsrVk.maxFragmentShadingRateAttachmentTexelSize.width,
654             fsrVk.maxFragmentShadingRateAttachmentTexelSize.height
655         };
656         cdp.fragmentShadingRateProperties.maxFragmentSize = { fsrVk.maxFragmentSize.width,
657             fsrVk.maxFragmentSize.height };
658     }
659 #endif
660     return cdp;
661 }
662 
PreparePhysicalDeviceFeaturesForEnabling(const BackendExtraVk * backendExtra,DevicePlatformDataVk & plat)663 void PreparePhysicalDeviceFeaturesForEnabling(const BackendExtraVk* backendExtra, DevicePlatformDataVk& plat)
664 {
665     // enable all by default and then disable few
666     plat.enabledPhysicalDeviceFeatures = plat.physicalDeviceProperties.physicalDeviceFeatures;
667     // prepare feature disable for core engine
668     plat.enabledPhysicalDeviceFeatures.geometryShader = VK_FALSE;
669     plat.enabledPhysicalDeviceFeatures.tessellationShader = VK_FALSE;
670     plat.enabledPhysicalDeviceFeatures.sampleRateShading = VK_FALSE;
671     plat.enabledPhysicalDeviceFeatures.occlusionQueryPrecise = VK_FALSE;
672     plat.enabledPhysicalDeviceFeatures.pipelineStatisticsQuery = VK_FALSE;
673     plat.enabledPhysicalDeviceFeatures.shaderTessellationAndGeometryPointSize = VK_FALSE;
674     plat.enabledPhysicalDeviceFeatures.inheritedQueries = VK_FALSE;
675     if (backendExtra) {
676         // check for support and prepare enabling
677         if (backendExtra->extensions.physicalDeviceFeaturesToEnable) {
678             const size_t valueCount = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
679             const array_view<const VkBool32> supported(
680                 reinterpret_cast<VkBool32*>(&plat.physicalDeviceProperties.physicalDeviceFeatures), valueCount);
681             VkPhysicalDeviceFeatures* wantedFeatures =
682                 (&backendExtra->extensions.physicalDeviceFeaturesToEnable->features);
683             const array_view<const VkBool32> wanted(reinterpret_cast<VkBool32*>(wantedFeatures), valueCount);
684 
685             array_view<VkBool32> enabledPhysicalDeviceFeatures(
686                 reinterpret_cast<VkBool32*>(&plat.enabledPhysicalDeviceFeatures), valueCount);
687             for (size_t idx = 0; idx < valueCount; ++idx) {
688                 if (supported[idx] && wanted[idx]) {
689                     enabledPhysicalDeviceFeatures[idx] = VK_TRUE;
690                 } else if (wanted[idx]) {
691                     PLUGIN_LOG_W(
692                         "physical device feature not supported/enabled from idx: %u", static_cast<uint32_t>(idx));
693                 }
694             }
695         }
696     }
697 }
698 
FillDeviceFormatSupport(VkPhysicalDevice physicalDevice,const Format format)699 FormatProperties FillDeviceFormatSupport(VkPhysicalDevice physicalDevice, const Format format)
700 {
701     VkFormatProperties formatProperties;
702     vkGetPhysicalDeviceFormatProperties(physicalDevice, // physicalDevice
703         (VkFormat)format,                               // format
704         &formatProperties);                             // pFormatProperties
705     return FormatProperties {
706         (FormatFeatureFlags)formatProperties.linearTilingFeatures,
707         (FormatFeatureFlags)formatProperties.optimalTilingFeatures,
708         (FormatFeatureFlags)formatProperties.bufferFeatures,
709         GpuProgramUtil::FormatByteSize(format),
710     };
711 }
712 
FillFormatSupport(VkPhysicalDevice physicalDevice,vector<FormatProperties> & formats)713 void FillFormatSupport(VkPhysicalDevice physicalDevice, vector<FormatProperties>& formats)
714 {
715     const uint32_t fullSize = DeviceFormatSupportConstants::LINEAR_FORMAT_MAX_COUNT +
716                               DeviceFormatSupportConstants::ADDITIONAL_FORMAT_MAX_COUNT;
717     formats.resize(fullSize);
718     for (uint32_t idx = 0; idx < DeviceFormatSupportConstants::LINEAR_FORMAT_MAX_COUNT; ++idx) {
719         formats[idx] = FillDeviceFormatSupport(physicalDevice, static_cast<Format>(idx));
720     }
721     // pre-build additional formats
722     for (uint32_t idx = 0; idx < DeviceFormatSupportConstants::ADDITIONAL_FORMAT_MAX_COUNT; ++idx) {
723         const uint32_t currIdx = idx + DeviceFormatSupportConstants::ADDITIONAL_FORMAT_BASE_IDX;
724         PLUGIN_ASSERT(currIdx < static_cast<uint32_t>(formats.size()));
725         const uint32_t formatIdx = idx + DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER;
726         formats[currIdx] = FillDeviceFormatSupport(physicalDevice, static_cast<Format>(formatIdx));
727     }
728 }
729 
CreateDefaultVulkanObjects(VkDevice device,DeviceVk::DefaultVulkanObjects & dvo)730 void CreateDefaultVulkanObjects(VkDevice device, DeviceVk::DefaultVulkanObjects& dvo)
731 {
732     constexpr VkDescriptorSetLayoutCreateInfo EMPTY_LAYOUT_INFO {
733         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
734         nullptr,                                             // pNext
735         0U,                                                  // flags
736         0U,                                                  // bindingCount
737         nullptr,                                             // pBindings
738     };
739 
740     PLUGIN_ASSERT(!dvo.emptyDescriptorSetLayout);
741     VALIDATE_VK_RESULT(vkCreateDescriptorSetLayout(device, // device
742         &EMPTY_LAYOUT_INFO,                                // pCreateInfo
743         nullptr,                                           // pAllocator
744         &dvo.emptyDescriptorSetLayout));                   // pSetLayout
745 }
DestroyDefaultVulkanObjects(VkDevice vkDevice,DeviceVk::DefaultVulkanObjects & dvo)746 void DestroyDefaultVulkanObjects(VkDevice vkDevice, DeviceVk::DefaultVulkanObjects& dvo)
747 {
748     if (dvo.emptyDescriptorSetLayout) {
749         vkDestroyDescriptorSetLayout(vkDevice, // device
750             dvo.emptyDescriptorSetLayout,      // descriptorSetLayout
751             nullptr);                          // pAllocator
752     }
753 }
754 } // namespace
755 
DeviceVk(RenderContext & renderContext)756 DeviceVk::DeviceVk(RenderContext& renderContext)
757     : Device(renderContext), rcFlags_(renderContext.GetCreateInfo().createFlags)
758 {
759     // assume instance and device will be created internally
760     ownInstanceAndDevice_ = true;
761 
762     const DeviceCreateInfo& createInfo = renderContext.GetCreateInfo().deviceCreateInfo;
763     const auto* backendExtra = static_cast<const BackendExtraVk*>(createInfo.backendConfiguration);
764     // update internal state based the optional backend configuration given by the client. the size of
765     // queuProperties will depend on the enableMultiQueue setting.
766     const auto queueProperties = CheckExternalConfig(backendExtra);
767 
768     // these check internally ownInstanceAndDevice_ and skip creation if provided by user
769     CreateInstance();
770     CreatePhysicalDevice();
771 
772     if ((!plat_.instance) || (!plat_.physicalDevice)) {
773         PLUGIN_LOG_E("Invalid device.");
774         SetDeviceStatus(false);
775         return;
776     }
777 
778     const auto availableQueues = CreateFunctionsVk::GetAvailableQueues(plat_.physicalDevice, queueProperties);
779 
780     // own device creation does a lot of work for figuring out what to create, but for external device
781     // CheckExternalConfig stored the enabled extensions and features, and we just need to check what is available.
782     if (ownInstanceAndDevice_) {
783         CreateDevice(backendExtra, availableQueues);
784     } else {
785         commonDeviceExtensions_ = GetEnabledCommonDeviceExtensions(extensions_);
786         platformDeviceExtensions_ = GetEnabledPlatformDeviceExtensions(extensions_);
787         // filling commonDeviceProperties_ isn't done, but at the moment that only contains fragment rate shading.
788         // should walk through BackendExtraVk::extensions::physicalDeviceFeaturesToEnable::pNext and see what's
789         // available.
790     }
791 
792     if (!plat_.device) {
793         PLUGIN_LOG_E("Invalid device.");
794         SetDeviceStatus(false);
795         return;
796     }
797 
798     CreateDebugFunctions();
799     CreateExtFunctions();
800     CreatePlatformExtFunctions();
801     SortAvailableQueues(availableQueues);
802 
803     CheckValidDepthFormats(plat_, platInternal_);
804     FillFormatSupport(plat_.physicalDevice, formatProperties_);
805 
806     if (!lowLevelGpuQueues_.graphicsQueues.empty()) {
807         lowLevelGpuQueues_.defaultQueue = lowLevelGpuQueues_.graphicsQueues[0];
808     } else {
809         PLUGIN_LOG_E("default vulkan queue not initialized");
810     }
811 
812     gpuQueueCount_ =
813         static_cast<uint32_t>(lowLevelGpuQueues_.computeQueues.size() + lowLevelGpuQueues_.graphicsQueues.size() +
814                               lowLevelGpuQueues_.transferQueues.size());
815 
816     const PlatformGpuMemoryAllocator::GpuMemoryAllocatorCreateInfo allocatorCreateInfo =
817         GetAllocatorCreateInfo(rcFlags_, backendExtra);
818     platformGpuMemoryAllocator_ = make_unique<PlatformGpuMemoryAllocator>(
819         plat_.instance, plat_.physicalDevice, plat_.device, allocatorCreateInfo);
820 
821     if (queueProperties.size() > 1) {
822         PLUGIN_LOG_I("gpu queue count: %u", gpuQueueCount_);
823     }
824 
825     SetDeviceStatus(true);
826 
827     const GpuResourceManager::CreateInfo grmCreateInfo {
828         GpuResourceManager::GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY,
829     };
830     gpuResourceMgr_ = make_unique<GpuResourceManager>(*this, grmCreateInfo);
831     shaderMgr_ = make_unique<ShaderManager>(*this);
832     globalDescriptorSetMgr_ = make_unique<DescriptorSetManagerVk>(*this);
833 
834     lowLevelDevice_ = make_unique<LowLevelDeviceVk>(*this);
835 
836     CreateDefaultVulkanObjects(plat_.device, defaultVulkanObjects_);
837 }
838 
~DeviceVk()839 DeviceVk::~DeviceVk()
840 {
841     WaitForIdle();
842 
843     DestroyDefaultVulkanObjects(plat_.device, defaultVulkanObjects_);
844 
845     globalDescriptorSetMgr_.reset();
846     // must release handles before taking down gpu resource manager.
847     swapchains_.clear();
848 
849     gpuResourceMgr_.reset();
850     shaderMgr_.reset();
851 
852     platformGpuMemoryAllocator_.reset();
853 
854     if (plat_.pipelineCache) {
855         CreateFunctionsVk::DestroyPipelineCache(plat_.device, plat_.pipelineCache);
856     }
857 
858     if (ownInstanceAndDevice_) {
859         CreateFunctionsVk::DestroyDevice(plat_.device);
860         CreateFunctionsVk::DestroyDebugMessenger(plat_.instance, debugFunctionUtilities_.debugMessenger);
861         CreateFunctionsVk::DestroyDebugCallback(plat_.instance, debugFunctionUtilities_.debugCallback);
862         CreateFunctionsVk::DestroyInstance(plat_.instance);
863     }
864 }
865 
CreateInstance()866 void DeviceVk::CreateInstance()
867 {
868     RENDER_CPU_PERF_SCOPE("CreateInstance", "");
869     const auto instanceWrapper = (plat_.instance == VK_NULL_HANDLE)
870                                      ? CreateFunctionsVk::CreateInstance(VersionInfo{"core_renderer", 0, 1, 0},
871                                                                          VersionInfo{"core_renderer_app", 0, 1, 0})
872                                      : CreateFunctionsVk::GetWrapper(plat_.instance);
873 
874     plat_.instance = instanceWrapper.instance;
875     // update with physical device creation
876     plat_.deviceApiMajor = instanceWrapper.apiMajor;
877     plat_.deviceApiMinor = instanceWrapper.apiMinor;
878     if (instanceWrapper.debugUtilsSupported) {
879         debugFunctionUtilities_.debugMessenger = CreateFunctionsVk::CreateDebugMessenger(
880             plat_.instance, DebugMessengerCallback, static_cast<RenderContext*>(&renderContext_));
881     }
882     if (!debugFunctionUtilities_.debugMessenger && instanceWrapper.debugReportSupported) {
883         debugFunctionUtilities_.debugCallback =
884             CreateFunctionsVk::CreateDebugCallback(plat_.instance, DebugReportCallback);
885     }
886 
887     extFunctions_.vkAcquireNextImageKHR =
888         (PFN_vkAcquireNextImageKHR)(void*)vkGetInstanceProcAddr(plat_.instance, "vkAcquireNextImageKHR");
889     if ((plat_.deviceApiMajor >= 1) && (plat_.deviceApiMinor >= 1)) {
890         extFunctions_.vkGetPhysicalDeviceFeatures2 =
891             (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(plat_.instance, "vkGetPhysicalDeviceFeatures2");
892         extFunctions_.vkGetPhysicalDeviceProperties2 =
893             (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(plat_.instance, "vkGetPhysicalDeviceProperties2");
894     }
895 }
896 
CreatePhysicalDevice()897 void DeviceVk::CreatePhysicalDevice()
898 {
899     RENDER_CPU_PERF_SCOPE("CreatePhysicalDevice", "");
900     auto physicalDeviceWrapper = (plat_.physicalDevice == VK_NULL_HANDLE)
901                                      ? CreateFunctionsVk::CreatePhysicalDevice(plat_.instance, DEFAULT_QUEUE)
902                                      : CreateFunctionsVk::GetWrapper(plat_.physicalDevice);
903     const uint32_t physicalDeviceApiMajor =
904         VK_VERSION_MAJOR(physicalDeviceWrapper.physicalDeviceProperties.physicalDeviceProperties.apiVersion);
905     const uint32_t physicalDeviceApiMinor =
906         VK_VERSION_MINOR(physicalDeviceWrapper.physicalDeviceProperties.physicalDeviceProperties.apiVersion);
907     plat_.deviceApiMajor = Math::min(plat_.deviceApiMajor, physicalDeviceApiMajor);
908     plat_.deviceApiMinor = Math::min(plat_.deviceApiMinor, physicalDeviceApiMinor);
909     PLUGIN_LOG_D("device api version %u.%u", plat_.deviceApiMajor, plat_.deviceApiMinor);
910 
911     plat_.physicalDevice = physicalDeviceWrapper.physicalDevice;
912     plat_.physicalDeviceProperties = move(physicalDeviceWrapper.physicalDeviceProperties);
913     plat_.physicalDeviceExtensions = move(physicalDeviceWrapper.physicalDeviceExtensions);
914     const auto& memoryProperties = plat_.physicalDeviceProperties.physicalDeviceMemoryProperties;
915     deviceSharedMemoryPropertyFlags_ =
916         (memoryProperties.memoryTypeCount > 0) ? (MemoryPropertyFlags)memoryProperties.memoryTypes[0].propertyFlags : 0;
917     for (uint32_t idx = 1; idx < memoryProperties.memoryTypeCount; ++idx) {
918         const auto memoryPropertyFlags = (MemoryPropertyFlags)memoryProperties.memoryTypes[idx].propertyFlags;
919         // do not compare lazily allocated or protected memory blocks
920         if ((memoryPropertyFlags & (CORE_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | CORE_MEMORY_PROPERTY_PROTECTED_BIT)) ==
921             0) {
922             deviceSharedMemoryPropertyFlags_ &= memoryPropertyFlags;
923         }
924     }
925 }
926 
CreateDevice(const BackendExtraVk * backendExtra,const vector<LowLevelQueueInfo> & availableQueues)927 void DeviceVk::CreateDevice(const BackendExtraVk* backendExtra, const vector<LowLevelQueueInfo>& availableQueues)
928 {
929     RENDER_CPU_PERF_SCOPE("CreateDevice", "");
930     vector<string_view> preferredExtensions = GetPreferredDeviceExtensions(backendExtra, rcFlags_, plat_);
931     PreparePhysicalDeviceFeaturesForEnabling(backendExtra, plat_);
932 
933     ChainWrapper chainWrapper;
934     ChainObjects chainObjects;
935 
936     VkPhysicalDeviceFeatures2* physicalDeviceFeatures2Ptr = nullptr;
937     VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 {
938         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // sType
939         nullptr,                                      // pNext
940         {},                                           // features
941     };
942     chainWrapper.ppNextFeatures = &physicalDeviceFeatures2.pNext;
943 
944     VkPhysicalDeviceProperties2 physicalDeviceProperties2 {
945         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // sType
946         nullptr,                                        // pNext
947         {},                                             // properties
948     };
949     chainWrapper.ppNextProperties = &physicalDeviceProperties2.pNext;
950 
951     GetPhysicalDeviceYcbcrStructs(chainObjects, chainWrapper);
952 #if (RENDER_VULKAN_RT_ENABLED == 1)
953     if (rcFlags_ & RenderCreateInfo::CreateInfoFlagBits::CREATE_INFO_RAY_TRACING_BIT) {
954         GetPhysicalDeviceRayTracingStructs(chainObjects, chainWrapper);
955     }
956 #endif
957 #if (RENDER_VULKAN_FSR_ENABLED == 1)
958     if (CreateFunctionsVk::HasExtension(plat_.physicalDeviceExtensions, DEVICE_EXTENSION_FRAGMENT_SHADING_RATE)) {
959         GetPhysicalDeviceFragmentShadingRateStructs(chainObjects, chainWrapper);
960     }
961 #endif
962     if (plat_.deviceApiMinor >= 1) { // enable only for 1.1 + for now
963         GetPhysicalDeviceMultiviewFeaturesStructs(chainObjects, chainWrapper);
964     }
965     if (plat_.deviceApiMinor >= 2) { // enable only for 1.2 + for now
966         GetPhysicalDeviceDescriptorIndexingFeaturesStructs(chainObjects, chainWrapper);
967     }
968     if (CreateFunctionsVk::HasExtension(plat_.physicalDeviceExtensions, DEVICE_EXTENSION_MAINTENANCE4)) {
969         GetPhysicalDeviceMaintenance4Structs(chainObjects, chainWrapper);
970     }
971     if ((plat_.deviceApiMajor >= 1) && (plat_.deviceApiMinor >= 1)) {
972         // pipe user extension physical device features
973         if (backendExtra) {
974             if (backendExtra->extensions.physicalDeviceFeaturesToEnable) {
975                 *chainWrapper.ppNextFeatures = backendExtra->extensions.physicalDeviceFeaturesToEnable->pNext;
976             }
977         }
978         if (extFunctions_.vkGetPhysicalDeviceFeatures2) {
979             extFunctions_.vkGetPhysicalDeviceFeatures2(plat_.physicalDevice, &physicalDeviceFeatures2);
980         }
981         if (extFunctions_.vkGetPhysicalDeviceProperties2) {
982             extFunctions_.vkGetPhysicalDeviceProperties2(plat_.physicalDevice, &physicalDeviceProperties2);
983         }
984 
985         // vkGetPhysicalDeviceFeatures has already filled this and PreparePhysicalDeviceFeaturesForEnabling
986         // disabled/ enabled some features.
987         physicalDeviceFeatures2.features = plat_.enabledPhysicalDeviceFeatures;
988         physicalDeviceFeatures2Ptr = &physicalDeviceFeatures2;
989     }
990     const DeviceWrapper deviceWrapper =
991         CreateFunctionsVk::CreateDevice(plat_.instance, plat_.physicalDevice, plat_.physicalDeviceExtensions,
992             plat_.enabledPhysicalDeviceFeatures, physicalDeviceFeatures2Ptr, availableQueues, preferredExtensions);
993     plat_.device = deviceWrapper.device;
994     for (const auto& ref : deviceWrapper.extensions) {
995         extensions_[ref] = 1u;
996     }
997     commonDeviceExtensions_ = GetEnabledCommonDeviceExtensions(extensions_);
998     platformDeviceExtensions_ = GetEnabledPlatformDeviceExtensions(extensions_);
999     commonDeviceProperties_ = GetCommonDevicePropertiesFunc(chainObjects);
1000 }
1001 
CheckExternalConfig(const BackendExtraVk * backendConfiguration)1002 vector<QueueProperties> DeviceVk::CheckExternalConfig(const BackendExtraVk* backendConfiguration)
1003 {
1004     vector<QueueProperties> queueProperties;
1005     queueProperties.push_back(DEFAULT_QUEUE);
1006 
1007     if (!backendConfiguration) {
1008         return queueProperties;
1009     }
1010 
1011     const auto& extra = *backendConfiguration;
1012     if (extra.enableMultiQueue) {
1013         queueProperties.push_back(QueueProperties {
1014             VK_QUEUE_COMPUTE_BIT, // requiredFlags
1015             1,                    // count
1016             1.0f,                 // priority
1017             true,                 // explicitFlags
1018             false,                // canPresent
1019         });
1020         PLUGIN_LOG_I("trying to enable gpu multi-queue, with queue count: %u", (uint32_t)queueProperties.size());
1021     }
1022 
1023     if (extra.instance != VK_NULL_HANDLE) {
1024         PLUGIN_LOG_D("trying to use application given vulkan instance, device, and physical device");
1025         if (!(extra.instance && extra.physicalDevice && extra.device)) {
1026             PLUGIN_LOG_E("Invalid vulkan instance, physical device, and/or device");
1027         }
1028         plat_.instance = extra.instance;
1029         plat_.physicalDevice = extra.physicalDevice;
1030         plat_.device = extra.device;
1031         if (extra.extensions.physicalDeviceFeaturesToEnable) {
1032             plat_.enabledPhysicalDeviceFeatures = extra.extensions.physicalDeviceFeaturesToEnable->features;
1033         }
1034         ownInstanceAndDevice_ = false; // everything given from the application
1035 
1036         const auto myDevice = plat_.physicalDevice;
1037         auto& myProperties = plat_.physicalDeviceProperties;
1038         vkGetPhysicalDeviceProperties(myDevice, &myProperties.physicalDeviceProperties);
1039         vkGetPhysicalDeviceFeatures(myDevice, &myProperties.physicalDeviceFeatures);
1040         vkGetPhysicalDeviceMemoryProperties(myDevice, &myProperties.physicalDeviceMemoryProperties);
1041 
1042         for (const auto& extension : extra.extensions.extensionNames) {
1043             extensions_[extension] = 1u;
1044         }
1045     }
1046     return queueProperties;
1047 }
1048 
SortAvailableQueues(const vector<LowLevelQueueInfo> & availableQueues)1049 void DeviceVk::SortAvailableQueues(const vector<LowLevelQueueInfo>& availableQueues)
1050 {
1051     for (const auto& ref : availableQueues) {
1052         if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_COMPUTE_BIT) {
1053             EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.computeQueues);
1054         } else if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT) {
1055             EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.graphicsQueues);
1056         } else if (ref.queueFlags == VkQueueFlagBits::VK_QUEUE_TRANSFER_BIT) {
1057             EmplaceDeviceQueue(plat_.device, ref, lowLevelGpuQueues_.transferQueues);
1058         }
1059     }
1060 }
1061 
GetBackendType() const1062 DeviceBackendType DeviceVk::GetBackendType() const
1063 {
1064     return DeviceBackendType::VULKAN;
1065 }
1066 
GetPlatformData() const1067 const DevicePlatformData& DeviceVk::GetPlatformData() const
1068 {
1069     return plat_;
1070 }
1071 
GetPlatformDataVk() const1072 const DevicePlatformDataVk& DeviceVk::GetPlatformDataVk() const
1073 {
1074     return plat_;
1075 }
1076 
GetPlatformInternalDataVk() const1077 const DevicePlatformInternalDataVk& DeviceVk::GetPlatformInternalDataVk() const
1078 {
1079     return platInternal_;
1080 }
1081 
GetLowLevelDevice() const1082 ILowLevelDevice& DeviceVk::GetLowLevelDevice() const
1083 {
1084     return *lowLevelDevice_;
1085 }
1086 
GetFormatProperties(const Format format) const1087 FormatProperties DeviceVk::GetFormatProperties(const Format format) const
1088 {
1089     const auto formatSupportSize = static_cast<uint32_t>(formatProperties_.size());
1090     const auto formatIdx = static_cast<uint32_t>(format);
1091     if (formatIdx < formatSupportSize) {
1092         return formatProperties_[formatIdx];
1093     } else if ((formatIdx >= DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER) &&
1094                (formatIdx <= DeviceFormatSupportConstants::ADDITIONAL_FORMAT_END_NUMBER)) {
1095         const uint32_t currIdx = formatIdx - DeviceFormatSupportConstants::ADDITIONAL_FORMAT_START_NUMBER;
1096         PLUGIN_UNUSED(currIdx);
1097         PLUGIN_ASSERT(currIdx < formatSupportSize);
1098         return formatProperties_[currIdx];
1099     }
1100     return {};
1101 }
1102 
GetAccelerationStructureBuildSizes(const AsBuildGeometryInfo & geometry,array_view<const AsGeometryTrianglesInfo> triangles,array_view<const AsGeometryAabbsInfo> aabbs,array_view<const AsGeometryInstancesInfo> instances) const1103 AsBuildSizes DeviceVk::GetAccelerationStructureBuildSizes(const AsBuildGeometryInfo& geometry,
1104     array_view<const AsGeometryTrianglesInfo> triangles, array_view<const AsGeometryAabbsInfo> aabbs,
1105     array_view<const AsGeometryInstancesInfo> instances) const
1106 {
1107 #if (RENDER_VULKAN_RT_ENABLED == 1)
1108     const VkDevice device = plat_.device;
1109 
1110     const size_t arraySize = triangles.size() + aabbs.size() + instances.size();
1111     vector<VkAccelerationStructureGeometryKHR> geometryData(arraySize);
1112     vector<uint32_t> maxPrimitiveCounts(arraySize);
1113     uint32_t arrayIndex = 0;
1114     FillAsBuildGeometryTriangles(geometry, triangles, geometryData, maxPrimitiveCounts, arrayIndex);
1115     FillAsBuildGeometryAabbs(geometry, aabbs, geometryData, maxPrimitiveCounts, arrayIndex);
1116     FillAsBuildGeometryInstances(geometry, instances, geometryData, maxPrimitiveCounts, arrayIndex);
1117 
1118     return GetAsBuildGeometryCombine(device, extFunctions_, geometry, geometryData, maxPrimitiveCounts, arrayIndex);
1119 #else
1120     return AsBuildSizes { 0, 0, 0 };
1121 #endif
1122 }
1123 
CreateDeviceSwapchain(const SwapchainCreateInfo & swapchainCreateInfo)1124 unique_ptr<Swapchain> DeviceVk::CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
1125 {
1126     RENDER_CPU_PERF_SCOPE("CreateDeviceSwapchain", "");
1127     return make_unique<SwapchainVk>(*this, swapchainCreateInfo);
1128 }
1129 
DestroyDeviceSwapchain()1130 void DeviceVk::DestroyDeviceSwapchain() {}
1131 
GetPlatformGpuMemoryAllocator()1132 PlatformGpuMemoryAllocator* DeviceVk::GetPlatformGpuMemoryAllocator()
1133 {
1134     return platformGpuMemoryAllocator_.get();
1135 }
1136 
GetValidGpuQueue(const GpuQueue & gpuQueue) const1137 GpuQueue DeviceVk::GetValidGpuQueue(const GpuQueue& gpuQueue) const
1138 {
1139     const auto getSpecificQueue = [](const uint32_t queueIndex, const GpuQueue::QueueType queueType,
1140                                       const vector<LowLevelGpuQueueVk>& specificQueues, const GpuQueue& defaultQueue) {
1141         const auto queueCount = (uint32_t)specificQueues.size();
1142         if (queueIndex < queueCount) {
1143             return GpuQueue { queueType, queueIndex };
1144         } else if (queueCount > 0) {
1145             return GpuQueue { queueType, 0 };
1146         }
1147         return defaultQueue;
1148     };
1149 
1150     static GpuQueue defaultQueue { GpuQueue::QueueType::GRAPHICS, 0 };
1151     if (gpuQueue.type == GpuQueue::QueueType::COMPUTE) {
1152         return getSpecificQueue(
1153             gpuQueue.index, GpuQueue::QueueType::COMPUTE, lowLevelGpuQueues_.computeQueues, defaultQueue);
1154     } else if (gpuQueue.type == GpuQueue::QueueType::GRAPHICS) {
1155         return getSpecificQueue(
1156             gpuQueue.index, GpuQueue::QueueType::GRAPHICS, lowLevelGpuQueues_.graphicsQueues, defaultQueue);
1157     } else if (gpuQueue.type == GpuQueue::QueueType::TRANSFER) {
1158         return getSpecificQueue(
1159             gpuQueue.index, GpuQueue::QueueType::TRANSFER, lowLevelGpuQueues_.transferQueues, defaultQueue);
1160     } else {
1161         return defaultQueue;
1162     }
1163 }
1164 
GetGpuQueueCount() const1165 uint32_t DeviceVk::GetGpuQueueCount() const
1166 {
1167     return gpuQueueCount_;
1168 }
1169 
InitializePipelineCache(array_view<const uint8_t> initialData)1170 void DeviceVk::InitializePipelineCache(array_view<const uint8_t> initialData)
1171 {
1172     RENDER_CPU_PERF_SCOPE("InitializePipelineCache", "");
1173 
1174     if (plat_.pipelineCache) {
1175         CreateFunctionsVk::DestroyPipelineCache(plat_.device, plat_.pipelineCache);
1176     }
1177     struct CacheHeader {
1178         uint32_t bytes;
1179         uint32_t version;
1180         uint32_t vendorId;
1181         uint32_t deviceId;
1182         uint8_t pipelineCacheUUID[VK_UUID_SIZE];
1183     };
1184     if (initialData.data() && (initialData.size() > sizeof(CacheHeader))) {
1185         CacheHeader header;
1186         CloneData(&header, sizeof(header), initialData.data(), sizeof(header));
1187         const auto& props = plat_.physicalDeviceProperties.physicalDeviceProperties;
1188         if (header.version != VkPipelineCacheHeaderVersion::VK_PIPELINE_CACHE_HEADER_VERSION_ONE ||
1189             header.vendorId != props.vendorID || header.deviceId != props.deviceID ||
1190             memcmp(header.pipelineCacheUUID, props.pipelineCacheUUID, VK_UUID_SIZE) != 0) {
1191             initialData = {};
1192         }
1193     }
1194 
1195     plat_.pipelineCache = CreateFunctionsVk::CreatePipelineCache(plat_.device, initialData);
1196 }
1197 
GetPipelineCache() const1198 vector<uint8_t> DeviceVk::GetPipelineCache() const
1199 {
1200     vector<uint8_t> deviceData;
1201     if (plat_.pipelineCache) {
1202         size_t dataSize = 0u;
1203         if (auto result = vkGetPipelineCacheData(plat_.device, plat_.pipelineCache, &dataSize, nullptr);
1204             result == VK_SUCCESS && dataSize) {
1205             deviceData.resize(dataSize);
1206             dataSize = deviceData.size();
1207             result = vkGetPipelineCacheData(plat_.device, plat_.pipelineCache, &dataSize, deviceData.data());
1208             if (result == VK_SUCCESS) {
1209                 deviceData.resize(dataSize);
1210             } else {
1211                 deviceData.clear();
1212             }
1213         }
1214     }
1215     return deviceData;
1216 }
1217 
GetGpuQueue(const GpuQueue & gpuQueue) const1218 LowLevelGpuQueueVk DeviceVk::GetGpuQueue(const GpuQueue& gpuQueue) const
1219 {
1220     // 1. tries to return the typed queue with given index
1221     // 2. tries to return the typed queue with an index 0
1222     // 3. returns the default queue
1223     const auto getSpecificQueue = [](const uint32_t queueIndex, const vector<LowLevelGpuQueueVk>& specificQueues,
1224                                       const LowLevelGpuQueueVk& defaultQueue) {
1225         const auto queueCount = (uint32_t)specificQueues.size();
1226         if (queueIndex < queueCount) {
1227             return specificQueues[queueIndex];
1228         } else if (queueCount > 0) {
1229             return specificQueues[0];
1230         }
1231         return defaultQueue;
1232     };
1233 
1234     if (gpuQueue.type == GpuQueue::QueueType::COMPUTE) {
1235         return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.computeQueues, lowLevelGpuQueues_.defaultQueue);
1236     } else if (gpuQueue.type == GpuQueue::QueueType::GRAPHICS) {
1237         return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.graphicsQueues, lowLevelGpuQueues_.defaultQueue);
1238     } else if (gpuQueue.type == GpuQueue::QueueType::TRANSFER) {
1239         return getSpecificQueue(gpuQueue.index, lowLevelGpuQueues_.transferQueues, lowLevelGpuQueues_.defaultQueue);
1240     } else {
1241         return lowLevelGpuQueues_.defaultQueue;
1242     }
1243 }
1244 
GetPresentationGpuQueue() const1245 LowLevelGpuQueueVk DeviceVk::GetPresentationGpuQueue() const
1246 {
1247     // NOTE: expected presentation
1248     return GetGpuQueue(GpuQueue { GpuQueue::QueueType::GRAPHICS, 0 });
1249 }
1250 
GetLowLevelGpuQueues() const1251 vector<LowLevelGpuQueueVk> DeviceVk::GetLowLevelGpuQueues() const
1252 {
1253     vector<LowLevelGpuQueueVk> gpuQueues;
1254     gpuQueues.reserve(gpuQueueCount_);
1255     gpuQueues.append(lowLevelGpuQueues_.computeQueues.begin(), lowLevelGpuQueues_.computeQueues.end());
1256     gpuQueues.append(lowLevelGpuQueues_.graphicsQueues.begin(), lowLevelGpuQueues_.graphicsQueues.end());
1257     gpuQueues.append(lowLevelGpuQueues_.transferQueues.begin(), lowLevelGpuQueues_.transferQueues.end());
1258     return gpuQueues;
1259 }
1260 
WaitForIdle()1261 void DeviceVk::WaitForIdle()
1262 {
1263     RENDER_CPU_PERF_SCOPE("WaitForIdle", "");
1264     if (plat_.device) {
1265         if (!isRenderbackendRunning_) {
1266             PLUGIN_LOG_D("Device - WaitForIdle");
1267             vkDeviceWaitIdle(plat_.device); // device
1268         } else {
1269             PLUGIN_LOG_E("Device WaitForIdle can only called when render backend is not running");
1270         }
1271     }
1272 }
1273 
Activate()1274 void DeviceVk::Activate() {}
1275 
Deactivate()1276 void DeviceVk::Deactivate() {}
1277 
AllowThreadedProcessing() const1278 bool DeviceVk::AllowThreadedProcessing() const
1279 {
1280     return true;
1281 }
1282 
GetFeatureConfigurations() const1283 const DeviceVk::FeatureConfigurations& DeviceVk::GetFeatureConfigurations() const
1284 {
1285     return featureConfigurations_;
1286 }
1287 
GetCommonDeviceExtensions() const1288 const DeviceVk::CommonDeviceExtensions& DeviceVk::GetCommonDeviceExtensions() const
1289 {
1290     return commonDeviceExtensions_;
1291 }
1292 
GetPlatformDeviceExtensions() const1293 const PlatformDeviceExtensions& DeviceVk::GetPlatformDeviceExtensions() const
1294 {
1295     return platformDeviceExtensions_;
1296 }
1297 
HasDeviceExtension(const string_view extensionName) const1298 bool DeviceVk::HasDeviceExtension(const string_view extensionName) const
1299 {
1300     return extensions_.contains(extensionName);
1301 }
1302 
CreateDeviceVk(RenderContext & renderContext)1303 unique_ptr<Device> CreateDeviceVk(RenderContext& renderContext)
1304 {
1305     RENDER_CPU_PERF_SCOPE("CreateDeviceVk", "");
1306     return make_unique<DeviceVk>(renderContext);
1307 }
1308 
CreateGpuBuffer(const GpuBufferDesc & desc)1309 unique_ptr<GpuBuffer> DeviceVk::CreateGpuBuffer(const GpuBufferDesc& desc)
1310 {
1311     RENDER_CPU_PERF_SCOPE("CreateGpuBuffer", "");
1312     return make_unique<GpuBufferVk>(*this, desc);
1313 }
1314 
CreateGpuBuffer(const GpuAccelerationStructureDesc & descAccel)1315 unique_ptr<GpuBuffer> DeviceVk::CreateGpuBuffer(const GpuAccelerationStructureDesc& descAccel)
1316 {
1317     RENDER_CPU_PERF_SCOPE("CreateGpuBuffer", "");
1318     return make_unique<GpuBufferVk>(*this, descAccel);
1319 }
1320 
CreateGpuBuffer(const BackendSpecificBufferDesc & desc)1321 unique_ptr<GpuBuffer> DeviceVk::CreateGpuBuffer(const BackendSpecificBufferDesc& desc)
1322 {
1323     return make_unique<GpuBufferVk>(*this, desc);
1324 }
1325 
CreateGpuImage(const GpuImageDesc & desc)1326 unique_ptr<GpuImage> DeviceVk::CreateGpuImage(const GpuImageDesc& desc)
1327 {
1328     RENDER_CPU_PERF_SCOPE("CreateGpuImage", "");
1329     return make_unique<GpuImageVk>(*this, desc);
1330 }
1331 
CreateGpuImageView(const GpuImageDesc & desc,const GpuImagePlatformData & platformData,const uintptr_t hwBuffer)1332 unique_ptr<GpuImage> DeviceVk::CreateGpuImageView(
1333     const GpuImageDesc& desc, const GpuImagePlatformData& platformData, const uintptr_t hwBuffer)
1334 {
1335     RENDER_CPU_PERF_SCOPE("CreateGpuImageView", "");
1336     return make_unique<GpuImageVk>(*this, desc, platformData, hwBuffer);
1337 }
1338 
CreateGpuImageView(const GpuImageDesc & desc,const GpuImagePlatformData & platformData)1339 unique_ptr<GpuImage> DeviceVk::CreateGpuImageView(const GpuImageDesc& desc, const GpuImagePlatformData& platformData)
1340 {
1341     RENDER_CPU_PERF_SCOPE("CreateGpuImageView", "");
1342     return CreateGpuImageView(desc, platformData, 0);
1343 }
1344 
CreateGpuImageViews(const Swapchain & swapchain)1345 vector<unique_ptr<GpuImage>> DeviceVk::CreateGpuImageViews(const Swapchain& swapchain)
1346 {
1347     RENDER_CPU_PERF_SCOPE("CreateGpuImageViews", "");
1348     const GpuImageDesc& desc = swapchain.GetDesc();
1349     const auto& swapchainPlat = static_cast<const SwapchainVk&>(swapchain).GetPlatformData();
1350 
1351     vector<unique_ptr<GpuImage>> gpuImages(swapchainPlat.swapchainImages.images.size());
1352     for (size_t idx = 0; idx < gpuImages.size(); ++idx) {
1353         GpuImagePlatformDataVk gpuImagePlat;
1354         gpuImagePlat.image = swapchainPlat.swapchainImages.images[idx];
1355         gpuImagePlat.imageView = swapchainPlat.swapchainImages.imageViews[idx];
1356         gpuImages[idx] = this->CreateGpuImageView(desc, gpuImagePlat);
1357     }
1358     return gpuImages;
1359 }
1360 
CreateGpuImageView(const GpuImageDesc & desc,const BackendSpecificImageDesc & platformData)1361 unique_ptr<GpuImage> DeviceVk::CreateGpuImageView(
1362     const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData)
1363 {
1364     RENDER_CPU_PERF_SCOPE("CreateGpuImageView", "");
1365     const auto& imageDesc = (const ImageDescVk&)platformData;
1366     GpuImagePlatformDataVk platData;
1367     platData.image = imageDesc.image;
1368     platData.imageView = imageDesc.imageView;
1369     return CreateGpuImageView(desc, platData, imageDesc.platformHwBuffer);
1370 }
1371 
CreateGpuSampler(const GpuSamplerDesc & desc)1372 unique_ptr<GpuSampler> DeviceVk::CreateGpuSampler(const GpuSamplerDesc& desc)
1373 {
1374     RENDER_CPU_PERF_SCOPE("CreateGpuSampler", "");
1375     return make_unique<GpuSamplerVk>(*this, desc);
1376 }
1377 
CreateRenderFrameSync()1378 unique_ptr<RenderFrameSync> DeviceVk::CreateRenderFrameSync()
1379 {
1380     RENDER_CPU_PERF_SCOPE("CreateRenderFrameSync", "");
1381     return make_unique<RenderFrameSyncVk>(*this);
1382 }
1383 
CreateRenderBackend(GpuResourceManager & gpuResourceMgr,CORE_NS::ITaskQueue * const queue)1384 unique_ptr<RenderBackend> DeviceVk::CreateRenderBackend(
1385     GpuResourceManager& gpuResourceMgr, CORE_NS::ITaskQueue* const queue)
1386 {
1387     return make_unique<RenderBackendVk>(*this, gpuResourceMgr, queue);
1388 }
1389 
CreateShaderModule(const ShaderModuleCreateInfo & data)1390 unique_ptr<ShaderModule> DeviceVk::CreateShaderModule(const ShaderModuleCreateInfo& data)
1391 {
1392     RENDER_CPU_PERF_SCOPE("CreateShaderModule", "");
1393     return make_unique<ShaderModuleVk>(*this, data);
1394 }
1395 
CreateComputeShaderModule(const ShaderModuleCreateInfo & data)1396 unique_ptr<ShaderModule> DeviceVk::CreateComputeShaderModule(const ShaderModuleCreateInfo& data)
1397 {
1398     RENDER_CPU_PERF_SCOPE("CreateComputeShaderModule", "");
1399     return make_unique<ShaderModuleVk>(*this, data);
1400 }
1401 
CreateGpuShaderProgram(const GpuShaderProgramCreateData & data)1402 unique_ptr<GpuShaderProgram> DeviceVk::CreateGpuShaderProgram(const GpuShaderProgramCreateData& data)
1403 {
1404     RENDER_CPU_PERF_SCOPE("CreateGpuShaderProgram", "");
1405     return make_unique<GpuShaderProgramVk>(data);
1406 }
1407 
CreateGpuComputeProgram(const GpuComputeProgramCreateData & data)1408 unique_ptr<GpuComputeProgram> DeviceVk::CreateGpuComputeProgram(const GpuComputeProgramCreateData& data)
1409 {
1410     RENDER_CPU_PERF_SCOPE("CreateGpuComputeProgram", "");
1411     return make_unique<GpuComputeProgramVk>(data);
1412 }
1413 
CreateNodeContextDescriptorSetManager()1414 unique_ptr<NodeContextDescriptorSetManager> DeviceVk::CreateNodeContextDescriptorSetManager()
1415 {
1416     return make_unique<NodeContextDescriptorSetManagerVk>(*this);
1417 }
1418 
CreateNodeContextPoolManager(GpuResourceManager & gpuResourceMgr,const GpuQueue & gpuQueue)1419 unique_ptr<NodeContextPoolManager> DeviceVk::CreateNodeContextPoolManager(
1420     GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue)
1421 {
1422     return make_unique<NodeContextPoolManagerVk>(*this, gpuResourceMgr, gpuQueue);
1423 }
1424 
CreateGraphicsPipelineStateObject(const GpuShaderProgram & gpuProgram,const GraphicsState & graphicsState,const PipelineLayout & pipelineLayout,const VertexInputDeclarationView & vertexInputDeclaration,const ShaderSpecializationConstantDataView & specializationConstants,const array_view<const DynamicStateEnum> dynamicStates,const RenderPassDesc & renderPassDesc,const array_view<const RenderPassSubpassDesc> & renderPassSubpassDescs,const uint32_t subpassIndex,const LowLevelRenderPassData * renderPassData,const LowLevelPipelineLayoutData * pipelineLayoutData)1425 unique_ptr<GraphicsPipelineStateObject> DeviceVk::CreateGraphicsPipelineStateObject(const GpuShaderProgram& gpuProgram,
1426     const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
1427     const VertexInputDeclarationView& vertexInputDeclaration,
1428     const ShaderSpecializationConstantDataView& specializationConstants,
1429     const array_view<const DynamicStateEnum> dynamicStates, const RenderPassDesc& renderPassDesc,
1430     const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs, const uint32_t subpassIndex,
1431     const LowLevelRenderPassData* renderPassData, const LowLevelPipelineLayoutData* pipelineLayoutData)
1432 {
1433     RENDER_CPU_PERF_SCOPE("CreateGraphicsPipelineStateObject", "");
1434     PLUGIN_ASSERT(renderPassData);
1435     PLUGIN_ASSERT(pipelineLayoutData);
1436     return make_unique<GraphicsPipelineStateObjectVk>(*this, gpuProgram, graphicsState, pipelineLayout,
1437         vertexInputDeclaration, specializationConstants, dynamicStates, renderPassSubpassDescs, subpassIndex,
1438         *renderPassData, *pipelineLayoutData);
1439 }
1440 
CreateComputePipelineStateObject(const GpuComputeProgram & gpuProgram,const PipelineLayout & pipelineLayout,const ShaderSpecializationConstantDataView & specializationConstants,const LowLevelPipelineLayoutData * pipelineLayoutData)1441 unique_ptr<ComputePipelineStateObject> DeviceVk::CreateComputePipelineStateObject(const GpuComputeProgram& gpuProgram,
1442     const PipelineLayout& pipelineLayout, const ShaderSpecializationConstantDataView& specializationConstants,
1443     const LowLevelPipelineLayoutData* pipelineLayoutData)
1444 {
1445     RENDER_CPU_PERF_SCOPE("CreateComputePipelineStateObject", "");
1446     PLUGIN_ASSERT(pipelineLayoutData);
1447     return make_unique<ComputePipelineStateObjectVk>(
1448         *this, gpuProgram, pipelineLayout, specializationConstants, *pipelineLayoutData);
1449 }
1450 
CreateGpuSemaphore()1451 unique_ptr<GpuSemaphore> DeviceVk::CreateGpuSemaphore()
1452 {
1453     RENDER_CPU_PERF_SCOPE("CreateGpuSemaphore", "");
1454     return make_unique<GpuSemaphoreVk>(*this);
1455 }
1456 
CreateGpuSemaphoreView(const uint64_t handle)1457 unique_ptr<GpuSemaphore> DeviceVk::CreateGpuSemaphoreView(const uint64_t handle)
1458 {
1459     RENDER_CPU_PERF_SCOPE("CreateGpuSemaphoreView", "");
1460     return make_unique<GpuSemaphoreVk>(*this, handle);
1461 }
1462 
GetDebugFunctionUtilities() const1463 const DebugFunctionUtilitiesVk& DeviceVk::GetDebugFunctionUtilities() const
1464 {
1465     return debugFunctionUtilities_;
1466 }
1467 
CreateDebugFunctions()1468 void DeviceVk::CreateDebugFunctions()
1469 {
1470     RENDER_CPU_PERF_SCOPE("CreateDebugFunctions", "");
1471     if (!plat_.device) {
1472         return;
1473     }
1474 
1475 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
1476     debugFunctionUtilities_.vkSetDebugUtilsObjectNameEXT =
1477         (PFN_vkSetDebugUtilsObjectNameEXT)(void*)vkGetDeviceProcAddr(plat_.device, "vkSetDebugUtilsObjectNameEXT");
1478 #endif
1479 #if (RENDER_DEBUG_MARKERS_ENABLED == 1) || (RENDER_DEBUG_COMMAND_MARKERS_ENABLED == 1)
1480     debugFunctionUtilities_.vkCmdBeginDebugUtilsLabelEXT =
1481         (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(plat_.instance, "vkCmdBeginDebugUtilsLabelEXT");
1482     debugFunctionUtilities_.vkCmdEndDebugUtilsLabelEXT =
1483         (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(plat_.instance, "vkCmdEndDebugUtilsLabelEXT");
1484 #endif
1485 }
1486 
GetExtFunctions() const1487 const DeviceVk::ExtFunctions& DeviceVk::GetExtFunctions() const
1488 {
1489     return extFunctions_;
1490 }
1491 
GetPlatformExtFunctions() const1492 const PlatformExtFunctions& DeviceVk::GetPlatformExtFunctions() const
1493 {
1494     return platformExtFunctions_;
1495 }
1496 
GetDefaultVulkanObjects() const1497 const DeviceVk::DefaultVulkanObjects& DeviceVk::GetDefaultVulkanObjects() const
1498 {
1499     return defaultVulkanObjects_;
1500 }
1501 
CreateExtFunctions()1502 void DeviceVk::CreateExtFunctions()
1503 {
1504     RENDER_CPU_PERF_SCOPE("CreateExtFunctions", "");
1505     if (commonDeviceExtensions_.renderPass2) {
1506         extFunctions_.vkCreateRenderPass2KHR =
1507             (PFN_vkCreateRenderPass2KHR)(void*)vkGetInstanceProcAddr(plat_.instance, "vkCreateRenderPass2KHR");
1508         if (!extFunctions_.vkCreateRenderPass2KHR) {
1509             commonDeviceExtensions_.renderPass2 = false;
1510             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateRenderPass2KHR");
1511         }
1512     }
1513     if (commonDeviceExtensions_.getMemoryRequirements2) {
1514         extFunctions_.vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2)vkGetInstanceProcAddr(
1515             plat_.instance, "vkGetImageMemoryRequirements2KHR");
1516         if (!extFunctions_.vkGetImageMemoryRequirements2) {
1517             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetImageMemoryRequirements2");
1518         }
1519     }
1520     if (commonDeviceExtensions_.samplerYcbcrConversion) {
1521         GetYcbcrExtFunctions(plat_.instance, extFunctions_);
1522     }
1523 #if (RENDER_VULKAN_FSR_ENABLED == 1)
1524     if (commonDeviceExtensions_.fragmentShadingRate) {
1525         extFunctions_.vkCmdSetFragmentShadingRateKHR =
1526             (PFN_vkCmdSetFragmentShadingRateKHR)vkGetInstanceProcAddr(plat_.instance, "vkCmdSetFragmentShadingRateKHR");
1527     }
1528 #endif
1529 
1530 #if (RENDER_VULKAN_RT_ENABLED == 1)
1531     if (rcFlags_ & RenderCreateInfo::CreateInfoFlagBits::CREATE_INFO_RAY_TRACING_BIT) {
1532         extFunctions_.vkGetAccelerationStructureBuildSizesKHR =
1533             (PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetInstanceProcAddr(
1534                 plat_.instance, "vkGetAccelerationStructureBuildSizesKHR");
1535         if (!extFunctions_.vkGetAccelerationStructureBuildSizesKHR) {
1536             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetAccelerationStructureBuildSizesKHR");
1537         }
1538         extFunctions_.vkCmdBuildAccelerationStructuresKHR =
1539             (PFN_vkCmdBuildAccelerationStructuresKHR)vkGetInstanceProcAddr(
1540                 plat_.instance, "vkCmdBuildAccelerationStructuresKHR");
1541         if (!extFunctions_.vkCmdBuildAccelerationStructuresKHR) {
1542             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCmdBuildAccelerationStructuresKHR");
1543         }
1544         extFunctions_.vkCreateAccelerationStructureKHR = (PFN_vkCreateAccelerationStructureKHR)vkGetInstanceProcAddr(
1545             plat_.instance, "vkCreateAccelerationStructureKHR");
1546         if (!extFunctions_.vkCreateAccelerationStructureKHR) {
1547             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkCreateAccelerationStructureKHR");
1548         }
1549         extFunctions_.vkDestroyAccelerationStructureKHR = (PFN_vkDestroyAccelerationStructureKHR)vkGetInstanceProcAddr(
1550             plat_.instance, "vkDestroyAccelerationStructureKHR");
1551         if (!extFunctions_.vkDestroyAccelerationStructureKHR) {
1552             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkDestroyAccelerationStructureKHR");
1553         }
1554         extFunctions_.vkGetAccelerationStructureDeviceAddressKHR =
1555             (PFN_vkGetAccelerationStructureDeviceAddressKHR)vkGetInstanceProcAddr(
1556                 plat_.instance, "vkGetAccelerationStructureDeviceAddressKHR");
1557         if (!extFunctions_.vkGetAccelerationStructureDeviceAddressKHR) {
1558             PLUGIN_LOG_E("vkGetInstanceProcAddr failed for vkGetAccelerationStructureDeviceAddressKHR");
1559         }
1560     }
1561 #endif
1562 }
1563 
LowLevelDeviceVk(DeviceVk & deviceVk)1564 LowLevelDeviceVk::LowLevelDeviceVk(DeviceVk& deviceVk)
1565     : deviceVk_(deviceVk), gpuResourceMgr_(static_cast<GpuResourceManager&>(deviceVk_.GetGpuResourceManager()))
1566 {}
1567 
GetBackendType() const1568 DeviceBackendType LowLevelDeviceVk::GetBackendType() const
1569 {
1570     return DeviceBackendType::VULKAN;
1571 }
1572 
GetPlatformDataVk() const1573 const DevicePlatformDataVk& LowLevelDeviceVk::GetPlatformDataVk() const
1574 {
1575     return deviceVk_.GetPlatformDataVk();
1576 }
1577 
GetBuffer(RenderHandle handle) const1578 GpuBufferPlatformDataVk LowLevelDeviceVk::GetBuffer(RenderHandle handle) const
1579 {
1580     if (deviceVk_.GetLockResourceBackendAccess()) {
1581         auto* buffer = gpuResourceMgr_.GetBuffer<GpuBufferVk>(handle);
1582         if (buffer) {
1583             return buffer->GetPlatformData();
1584         }
1585     } else {
1586         PLUGIN_LOG_E("low level device methods can only be used within specific methods");
1587     }
1588     return {};
1589 }
1590 
GetImage(RenderHandle handle) const1591 GpuImagePlatformDataVk LowLevelDeviceVk::GetImage(RenderHandle handle) const
1592 {
1593     if (deviceVk_.GetLockResourceBackendAccess()) {
1594         auto* image = gpuResourceMgr_.GetImage<GpuImageVk>(handle);
1595         if (image) {
1596             return image->GetPlatformData();
1597         }
1598     } else {
1599         PLUGIN_LOG_E("low level device methods can only be used within specific methods");
1600     }
1601     return {};
1602 }
1603 
GetSampler(RenderHandle handle) const1604 GpuSamplerPlatformDataVk LowLevelDeviceVk::GetSampler(RenderHandle handle) const
1605 {
1606     if (deviceVk_.GetLockResourceBackendAccess()) {
1607         auto* sampler = gpuResourceMgr_.GetSampler<GpuSamplerVk>(handle);
1608         if (sampler) {
1609             return sampler->GetPlatformData();
1610         }
1611     } else {
1612         PLUGIN_LOG_E("low level device methods can be only used within specific methods");
1613     }
1614     return {};
1615 }
1616 RENDER_END_NAMESPACE()
1617