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