unit uvkuUtils; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuException = class(Exception); TvkuErrorException = class(TvkuException) private fError: TVkResult; public property Error: TVkResult read fError; constructor Create(const msg: string; const aError: TVkResult); end; TvkuInvalidFuncPtrException = class(TvkuException) private fExtensionName: String; fFunctionName: String; fExtentionName: String; public property FunctionName: String read fFunctionName; property ExtensionName: String read fExtensionName; constructor Create(const aFunctionName: String; const aExtensionName: String = ''); end; function vkuMakeString(const aFeatures: TVkPhysicalDeviceFeatures; const aSeperator: String = sLineBreak): String; function vkuMakeString(const aProperties: TVkPhysicalDeviceProperties; const aPrintLimits, aPrintSparseProps: Boolean): String; function vkuMakeString(const aMemoryProperties: TVkPhysicalDeviceMemoryProperties): String; function vkuGetMemoryTypeIndex( const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; aMemoryTypeBits: VkUint32; const aProperty: TVkMemoryPropertyFlagBit): VkUint32; implementation ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuErrorException////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuErrorException.Create(const msg: string; const aError: TVkResult); begin inherited Create(msg); fError := aError; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuInvalidFuncPtrException//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuInvalidFuncPtrException.Create(const aFunctionName: String; const aExtensionName: String); var s: String; begin fFunctionName := aFunctionName; fExtensionName := aExtensionName; s := 'did you load the vulkan core commands?'; if (aExtensionName <> '') then s := 'did you enabled/load the ' + fExtensionName + ' extension?'; inherited Create('invalid function pointer: ' + fFunctionName + '; ' + s); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function vkuMakeString(const aFeatures: TVkPhysicalDeviceFeatures; const aSeperator: String): String; procedure AddToResult(const b: VkBool32; const aName: String); begin if (b = 0) then exit; if (result <> '') then result := result + aSeperator; result := result + aName; end; begin result := ''; AddToResult(aFeatures.robustBufferAccess, 'RobustBufferAccess'); AddToResult(aFeatures.fullDrawIndexUint32, 'FullDrawIndexUint32'); AddToResult(aFeatures.imageCubeArray, 'ImageCubeArray'); AddToResult(aFeatures.independentBlend, 'IndependentBlend'); AddToResult(aFeatures.geometryShader, 'GeometryShader'); AddToResult(aFeatures.tessellationShader, 'TessellationShader'); AddToResult(aFeatures.sampleRateShading, 'SampleRateShading'); AddToResult(aFeatures.dualSrcBlend, 'DualSrcBlend'); AddToResult(aFeatures.logicOp, 'LogicOp'); AddToResult(aFeatures.multiDrawIndirect, 'MultiDrawIndirect'); AddToResult(aFeatures.drawIndirectFirstInstance, 'DrawIndirectFirstInstance'); AddToResult(aFeatures.depthClamp, 'DepthClamp'); AddToResult(aFeatures.depthBiasClamp, 'DepthBiasClamp'); AddToResult(aFeatures.fillModeNonSolid, 'FillModeNonSolid'); AddToResult(aFeatures.depthBounds, 'DepthBounds'); AddToResult(aFeatures.wideLines, 'WideLines'); AddToResult(aFeatures.largePoints, 'LargePoints'); AddToResult(aFeatures.alphaToOne, 'AlphaToOne'); AddToResult(aFeatures.multiViewport, 'MultiViewport'); AddToResult(aFeatures.samplerAnisotropy, 'SamplerAnisotropy'); AddToResult(aFeatures.textureCompressionETC2, 'TextureCompressionETC2'); AddToResult(aFeatures.textureCompressionASTC_LDR, 'TextureCompressionASTC_LDR'); AddToResult(aFeatures.textureCompressionBC, 'TextureCompressionBC'); AddToResult(aFeatures.occlusionQueryPrecise, 'OcclusionQueryPrecise'); AddToResult(aFeatures.pipelineStatisticsQuery, 'PipelineStatisticsQuery'); AddToResult(aFeatures.vertexPipelineStoresAndAtomics, 'VertexPipelineStoresAndAtomics'); AddToResult(aFeatures.fragmentStoresAndAtomics, 'FragmentStoresAndAtomics'); AddToResult(aFeatures.shaderTessellationAndGeometryPointSize, 'ShaderTessellationAndGeometryPointSize'); AddToResult(aFeatures.shaderImageGatherExtended, 'ShaderImageGatherExtended'); AddToResult(aFeatures.shaderStorageImageExtendedFormats, 'ShaderStorageImageExtendedFormats'); AddToResult(aFeatures.shaderStorageImageMultisample, 'ShaderStorageImageMultisample'); AddToResult(aFeatures.shaderStorageImageReadWithoutFormat, 'ShaderStorageImageReadWithoutFormat'); AddToResult(aFeatures.shaderStorageImageWriteWithoutFormat, 'ShaderStorageImageWriteWithoutFormat'); AddToResult(aFeatures.shaderUniformBufferArrayDynamicIndexing, 'ShaderUniformBufferArrayDynamicIndexing'); AddToResult(aFeatures.shaderSampledImageArrayDynamicIndexing, 'ShaderSampledImageArrayDynamicIndexing'); AddToResult(aFeatures.shaderStorageBufferArrayDynamicIndexing, 'ShaderStorageBufferArrayDynamicIndexing'); AddToResult(aFeatures.shaderStorageImageArrayDynamicIndexing, 'ShaderStorageImageArrayDynamicIndexing'); AddToResult(aFeatures.shaderClipDistance, 'ShaderClipDistance'); AddToResult(aFeatures.shaderCullDistance, 'ShaderCullDistance'); AddToResult(aFeatures.shaderFloat64, 'ShaderFloat64'); AddToResult(aFeatures.shaderInt64, 'ShaderInt64'); AddToResult(aFeatures.shaderInt16, 'ShaderInt16'); AddToResult(aFeatures.shaderResourceResidency, 'ShaderResourceResidency'); AddToResult(aFeatures.shaderResourceMinLod, 'ShaderResourceMinLod'); AddToResult(aFeatures.sparseBinding, 'SparseBinding'); AddToResult(aFeatures.sparseResidencyBuffer, 'SparseResidencyBuffer'); AddToResult(aFeatures.sparseResidencyImage2D, 'SparseResidencyImage2D'); AddToResult(aFeatures.sparseResidencyImage3D, 'SparseResidencyImage3D'); AddToResult(aFeatures.sparseResidency2Samples, 'SparseResidency2Samples'); AddToResult(aFeatures.sparseResidency4Samples, 'SparseResidency4Samples'); AddToResult(aFeatures.sparseResidency8Samples, 'SparseResidency8Samples'); AddToResult(aFeatures.sparseResidency16Samples, 'SparseResidency16Samples'); AddToResult(aFeatures.sparseResidencyAliased, 'SparseResidencyAliased'); AddToResult(aFeatures.variableMultisampleRate, 'VariableMultisampleRate'); AddToResult(aFeatures.inheritedQueries, 'InheritedQueries'); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function vkuMakeString(const aProperties: TVkPhysicalDeviceProperties; const aPrintLimits, aPrintSparseProps: Boolean): String; function UUIDtoStr: String; var i: Integer; begin result := ''; for i := low(aProperties.pipelineCacheUUID) to High(aProperties.pipelineCacheUUID) do begin if (result <> '') then result := result + ':'; result := result + IntToHex(aProperties.pipelineCacheUUID[i], 2); end; end; function toString(const i: Int64): String; begin result := IntToStr(i); end; function toString(const e: Extended): String; begin result := Format('%.3f', [e]); end; function toString(const arr: array of VkUint32): String; var i: Integer; begin result := ''; for i := low(arr) to high(arr) do begin if (i <> low(arr)) then result := result + '; '; result := result + toString(arr[i]); end; end; function toString(const arr: array of VkFloat): String; var i: Integer; begin result := ''; for i := low(arr) to high(arr) do begin if (i <> low(arr)) then result := result + '; '; result := result + toString(arr[i]); end; end; function toString(const aType: TVkPhysicalDeviceType): String; begin case aType of VK_PHYSICAL_DEVICE_TYPE_OTHER: result := 'Other'; VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: result := 'IntegratedGPU'; VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: result := 'DiscreteGPU'; VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: result := 'VirtualGPU'; VK_PHYSICAL_DEVICE_TYPE_CPU: result := 'CPU'; else result := 'Unknown'; end; end; function toString(const aChar: PVkChar): String; begin result := String(aChar); end; begin result := Format( 'ApiVersion: %x (v%d.%d.%d)' + sLineBreak + 'DriverVersion: %s' + sLineBreak + 'VendorID: %s' + sLineBreak + 'DeviceID: %s' + sLineBreak + 'DeviceType: %s' + sLineBreak + 'deviceName: %s' + sLineBreak + 'PipelineCacheUUID: %s' + sLineBreak ,[ aProperties.apiVersion, vkGetVersionMajor(aProperties.apiVersion), vkGetVersionMinor(aProperties.apiVersion), vkgetVersionPatch(aProperties.apiVersion), toString(aProperties.driverVersion), toString(aProperties.vendorID), toString(aProperties.deviceID), toString(aProperties.deviceType), toString(@aProperties.deviceName[0]), UUIDtoStr ]); if aPrintLimits then begin result := result + Format( 'Limits:' + sLineBreak + ' MaxImageDimension1D: %s' + sLineBreak + ' MaxImageDimension2D: %s' + sLineBreak + ' MaxImageDimension3D: %s' + sLineBreak + ' MaxImageDimensionCube: %s' + sLineBreak + ' MaxImageArrayLayers: %s' + sLineBreak + ' MaxTexelBufferElements: %s' + sLineBreak + ' MaxUniformBufferRange: %s' + sLineBreak + ' MaxStorageBufferRange: %s' + sLineBreak + ' MaxPushConstantsSize: %s' + sLineBreak + ' MaxMemoryAllocationCount: %s' + sLineBreak + ' MaxSamplerAllocationCount: %s' + sLineBreak + ' BufferImageGranularity: %s' + sLineBreak + ' SparseAddressSpaceSize: %s' + sLineBreak + ' MaxBoundDescriptorSets: %s' + sLineBreak + ' MaxPerStageDescriptorSamplers: %s' + sLineBreak + ' MaxPerStageDescriptorUniformBuffers: %s' + sLineBreak + ' MaxPerStageDescriptorStorageBuffers: %s' + sLineBreak + ' MaxPerStageDescriptorSampledImages: %s' + sLineBreak + ' MaxPerStageDescriptorStorageImages: %s' + sLineBreak + ' MaxPerStageDescriptorInputAttachments: %s' + sLineBreak + ' MaxPerStageResources: %s' + sLineBreak + ' MaxDescriptorSetSamplers: %s' + sLineBreak + ' MaxDescriptorSetUniformBuffers: %s' + sLineBreak + ' MaxDescriptorSetUniformBuffersDynamic: %s' + sLineBreak + ' MaxDescriptorSetStorageBuffers: %s' + sLineBreak + ' MaxDescriptorSetStorageBuffersDynamic: %s' + sLineBreak + ' MaxDescriptorSetSampledImages: %s' + sLineBreak + ' MaxDescriptorSetStorageImages: %s' + sLineBreak + ' MaxDescriptorSetInputAttachments: %s' + sLineBreak + ' MaxVertexInputAttributes: %s' + sLineBreak + ' MaxVertexInputBindings: %s' + sLineBreak + ' MaxVertexInputAttributeOffset: %s' + sLineBreak + ' MaxVertexInputBindingStride: %s' + sLineBreak + ' MaxVertexOutputComponents: %s' + sLineBreak + ' MaxTessellationGenerationLevel: %s' + sLineBreak + ' MaxTessellationPatchSize: %s' + sLineBreak + ' MaxTessellationControlPerVertexInputComponents: %s' + sLineBreak + ' MaxTessellationControlPerVertexOutputComponents: %s' + sLineBreak + ' MaxTessellationControlPerPatchOutputComponents: %s' + sLineBreak + ' MaxTessellationControlTotalOutputComponents: %s' + sLineBreak + ' MaxTessellationEvaluationInputComponents: %s' + sLineBreak + ' MaxTessellationEvaluationOutputComponents: %s' + sLineBreak + ' MaxGeometryShaderInvocations: %s' + sLineBreak + ' MaxGeometryInputComponents: %s' + sLineBreak + ' MaxGeometryOutputComponents: %s' + sLineBreak + ' MaxGeometryOutputVertices: %s' + sLineBreak + ' MaxGeometryTotalOutputComponents: %s' + sLineBreak + ' MaxFragmentInputComponents: %s' + sLineBreak + ' MaxFragmentOutputAttachments: %s' + sLineBreak + ' MaxFragmentDualSrcAttachments: %s' + sLineBreak + ' MaxFragmentCombinedOutputResources: %s' + sLineBreak + ' MaxComputeSharedMemorySize: %s' + sLineBreak + ' MaxComputeWorkGroupCount: %s' + sLineBreak + ' MaxComputeWorkGroupInvocations: %s' + sLineBreak + ' MaxComputeWorkGroupSize: %s' + sLineBreak + ' SubPixelPrecisionBits: %s' + sLineBreak + ' SubTexelPrecisionBits: %s' + sLineBreak + ' MipmapPrecisionBits: %s' + sLineBreak + ' MaxDrawIndexedIndexValue: %s' + sLineBreak + ' MaxDrawIndirectCount: %s' + sLineBreak + ' MaxSamplerLodBias: %s' + sLineBreak + ' MaxSamplerAnisotropy: %s' + sLineBreak + ' MaxViewports: %s' + sLineBreak + ' MaxViewportDimensions: %s' + sLineBreak + ' ViewportBoundsRange: %s' + sLineBreak + ' ViewportSubPixelBits: %s' + sLineBreak + ' MinMemoryMapAlignment: %s' + sLineBreak + ' MinTexelBufferOffsetAlignment: %s' + sLineBreak + ' MinUniformBufferOffsetAlignment: %s' + sLineBreak + ' MinStorageBufferOffsetAlignment: %s' + sLineBreak + ' MinTexelOffset: %s' + sLineBreak + ' MaxTexelOffset: %s' + sLineBreak + ' MinTexelGatherOffset: %s' + sLineBreak + ' MaxTexelGatherOffset: %s' + sLineBreak + ' MinInterpolationOffset: %s' + sLineBreak + ' MaxInterpolationOffset: %s' + sLineBreak + ' SubPixelInterpolationOffsetBits: %s' + sLineBreak + ' MaxFramebufferWidth: %s' + sLineBreak + ' MaxFramebufferHeight: %s' + sLineBreak + ' MaxFramebufferLayers: %s' + sLineBreak + ' FramebufferColorSampleCounts: %s' + sLineBreak + ' FramebufferDepthSampleCounts: %s' + sLineBreak + ' FramebufferStencilSampleCounts: %s' + sLineBreak + ' FramebufferNoAttachmentsSampleCounts: %s' + sLineBreak + ' MaxColorAttachments: %s' + sLineBreak + ' SampledImageColorSampleCounts: %s' + sLineBreak + ' SampledImageIntegerSampleCounts: %s' + sLineBreak + ' SampledImageDepthSampleCounts: %s' + sLineBreak + ' SampledImageStencilSampleCounts: %s' + sLineBreak + ' StorageImageSampleCounts: %s' + sLineBreak + ' MaxSampleMaskWords: %s' + sLineBreak + ' TimestampComputeAndGraphics: %s' + sLineBreak + ' TimestampPeriod: %s' + sLineBreak + ' MaxClipDistances: %s' + sLineBreak + ' MaxCullDistances: %s' + sLineBreak + ' MaxCombinedClipAndCullDistances: %s' + sLineBreak + ' DiscreteQueuePriorities: %s' + sLineBreak + ' PointSizeRange: %s' + sLineBreak + ' LineWidthRange: %s' + sLineBreak + ' PointSizeGranularity: %s' + sLineBreak + ' LineWidthGranularity: %s' + sLineBreak + ' StrictLines: %s' + sLineBreak + ' StandardSampleLocations: %s' + sLineBreak + ' OptimalBufferCopyOffsetAlignment: %s' + sLineBreak + ' OptimalBufferCopyRowPitchAlignment: %s' + sLineBreak + ' NonCoherentAtomSize: %s' + sLineBreak ,[ toString(aProperties.limits.maxImageDimension1D), toString(aProperties.limits.maxImageDimension2D), toString(aProperties.limits.maxImageDimension3D), toString(aProperties.limits.maxImageDimensionCube), toString(aProperties.limits.maxImageArrayLayers), toString(aProperties.limits.maxTexelBufferElements), toString(aProperties.limits.maxUniformBufferRange), toString(aProperties.limits.maxStorageBufferRange), toString(aProperties.limits.maxPushConstantsSize), toString(aProperties.limits.maxMemoryAllocationCount), toString(aProperties.limits.maxSamplerAllocationCount), toString(aProperties.limits.bufferImageGranularity), toString(aProperties.limits.sparseAddressSpaceSize), toString(aProperties.limits.maxBoundDescriptorSets), toString(aProperties.limits.maxPerStageDescriptorSamplers), toString(aProperties.limits.maxPerStageDescriptorUniformBuffers), toString(aProperties.limits.maxPerStageDescriptorStorageBuffers), toString(aProperties.limits.maxPerStageDescriptorSampledImages), toString(aProperties.limits.maxPerStageDescriptorStorageImages), toString(aProperties.limits.maxPerStageDescriptorInputAttachments), toString(aProperties.limits.maxPerStageResources), toString(aProperties.limits.maxDescriptorSetSamplers), toString(aProperties.limits.maxDescriptorSetUniformBuffers), toString(aProperties.limits.maxDescriptorSetUniformBuffersDynamic), toString(aProperties.limits.maxDescriptorSetStorageBuffers), toString(aProperties.limits.maxDescriptorSetStorageBuffersDynamic), toString(aProperties.limits.maxDescriptorSetSampledImages), toString(aProperties.limits.maxDescriptorSetStorageImages), toString(aProperties.limits.maxDescriptorSetInputAttachments), toString(aProperties.limits.maxVertexInputAttributes), toString(aProperties.limits.maxVertexInputBindings), toString(aProperties.limits.maxVertexInputAttributeOffset), toString(aProperties.limits.maxVertexInputBindingStride), toString(aProperties.limits.maxVertexOutputComponents), toString(aProperties.limits.maxTessellationGenerationLevel), toString(aProperties.limits.maxTessellationPatchSize), toString(aProperties.limits.maxTessellationControlPerVertexInputComponents), toString(aProperties.limits.maxTessellationControlPerVertexOutputComponents), toString(aProperties.limits.maxTessellationControlPerPatchOutputComponents), toString(aProperties.limits.maxTessellationControlTotalOutputComponents), toString(aProperties.limits.maxTessellationEvaluationInputComponents), toString(aProperties.limits.maxTessellationEvaluationOutputComponents), toString(aProperties.limits.maxGeometryShaderInvocations), toString(aProperties.limits.maxGeometryInputComponents), toString(aProperties.limits.maxGeometryOutputComponents), toString(aProperties.limits.maxGeometryOutputVertices), toString(aProperties.limits.maxGeometryTotalOutputComponents), toString(aProperties.limits.maxFragmentInputComponents), toString(aProperties.limits.maxFragmentOutputAttachments), toString(aProperties.limits.maxFragmentDualSrcAttachments), toString(aProperties.limits.maxFragmentCombinedOutputResources), toString(aProperties.limits.maxComputeSharedMemorySize), toString(aProperties.limits.maxComputeWorkGroupCount), toString(aProperties.limits.maxComputeWorkGroupInvocations), toString(aProperties.limits.maxComputeWorkGroupSize), toString(aProperties.limits.subPixelPrecisionBits), toString(aProperties.limits.subTexelPrecisionBits), toString(aProperties.limits.mipmapPrecisionBits), toString(aProperties.limits.maxDrawIndexedIndexValue), toString(aProperties.limits.maxDrawIndirectCount), toString(aProperties.limits.maxSamplerLodBias), toString(aProperties.limits.maxSamplerAnisotropy), toString(aProperties.limits.maxViewports), toString(aProperties.limits.maxViewportDimensions), toString(aProperties.limits.viewportBoundsRange), toString(aProperties.limits.viewportSubPixelBits), toString(aProperties.limits.minMemoryMapAlignment), toString(aProperties.limits.minTexelBufferOffsetAlignment), toString(aProperties.limits.minUniformBufferOffsetAlignment), toString(aProperties.limits.minStorageBufferOffsetAlignment), toString(aProperties.limits.minTexelOffset), toString(aProperties.limits.maxTexelOffset), toString(aProperties.limits.minTexelGatherOffset), toString(aProperties.limits.maxTexelGatherOffset), toString(aProperties.limits.minInterpolationOffset), toString(aProperties.limits.maxInterpolationOffset), toString(aProperties.limits.subPixelInterpolationOffsetBits), toString(aProperties.limits.maxFramebufferWidth), toString(aProperties.limits.maxFramebufferHeight), toString(aProperties.limits.maxFramebufferLayers), toString(PVkUint32(@aProperties.limits.framebufferColorSampleCounts)^), toString(PVkUint32(@aProperties.limits.framebufferDepthSampleCounts)^), toString(PVkUint32(@aProperties.limits.framebufferStencilSampleCounts)^), toString(PVkUint32(@aProperties.limits.framebufferNoAttachmentsSampleCounts)^), toString(aProperties.limits.maxColorAttachments), toString(PVkUint32(@aProperties.limits.sampledImageColorSampleCounts)^), toString(PVkUint32(@aProperties.limits.sampledImageIntegerSampleCounts)^), toString(PVkUint32(@aProperties.limits.sampledImageDepthSampleCounts)^), toString(PVkUint32(@aProperties.limits.sampledImageStencilSampleCounts)^), toString(PVkUint32(@aProperties.limits.storageImageSampleCounts)^), toString(aProperties.limits.maxSampleMaskWords), toString(aProperties.limits.timestampComputeAndGraphics), toString(aProperties.limits.timestampPeriod), toString(aProperties.limits.maxClipDistances), toString(aProperties.limits.maxCullDistances), toString(aProperties.limits.maxCombinedClipAndCullDistances), toString(aProperties.limits.discreteQueuePriorities), toString(aProperties.limits.pointSizeRange), toString(aProperties.limits.lineWidthRange), toString(aProperties.limits.pointSizeGranularity), toString(aProperties.limits.lineWidthGranularity), toString(aProperties.limits.strictLines), toString(aProperties.limits.standardSampleLocations), toString(aProperties.limits.optimalBufferCopyOffsetAlignment), toString(aProperties.limits.optimalBufferCopyRowPitchAlignment), toString(aProperties.limits.nonCoherentAtomSize) ]); end; if aPrintSparseProps then begin result := result + Format( 'SparseProperties:' + sLineBreak + ' ResidencyStandard2DBlockShape: %s' + sLineBreak + ' ResidencyStandard2DMultisampleBlockShape: %s' + sLineBreak + ' ResidencyStandard3DBlockShape: %s' + sLineBreak + ' ResidencyAlignedMipSize: %s' + sLineBreak + ' ResidencyNonResidentStrict: %s' + sLineBreak, [ toString(aProperties.sparseProperties.residencyStandard2DBlockShape), toString(aProperties.sparseProperties.residencyStandard2DMultisampleBlockShape), toString(aProperties.sparseProperties.residencyStandard3DBlockShape), toString(aProperties.sparseProperties.residencyAlignedMipSize), toString(aProperties.sparseProperties.residencyNonResidentStrict) ]); end; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function vkuMakeString(const aMemoryProperties: TVkPhysicalDeviceMemoryProperties): String; var i: Integer; begin result := 'Types:' + sLineBreak; for i := 0 to aMemoryProperties.memoryTypeCount-1 do begin result := result + Format( ' Type %d:' + sLineBreak + ' PropertyFlags: 0x%.16X' + sLineBreak + ' HeapIndex: %d (0x%2:.16X)' + sLineBreak, [i, PVkUint32(@aMemoryProperties.memoryTypes[i].propertyFlags)^, aMemoryProperties.memoryTypes[i].heapIndex]); end; result := result + 'Heaps:' + sLineBreak; for i := 0 to aMemoryProperties.memoryHeapCount-1 do begin result := result + Format( ' Heap %d:' + sLineBreak + ' Size: %d (0x%1:.16X)' + sLineBreak + ' Flags: 0x%.16X' + sLineBreak, [i, aMemoryProperties.memoryHeaps[i].size, PVkUint32(@aMemoryProperties.memoryHeaps[i].flags)^]); end; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function vkuGetMemoryTypeIndex( const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; aMemoryTypeBits: VkUint32; const aProperty: TVkMemoryPropertyFlagBit): VkUint32; var i: Integer; begin result := 0; for i := 0 to VK_MAX_MEMORY_TYPES-1 do begin if ((aMemoryTypeBits and 1) = 1) and (aProperty in aMemoryProperties.memoryTypes[i].propertyFlags) then begin result := i; break; end; aMemoryTypeBits := aMemoryTypeBits shr 1; end; end; end.