diff --git a/projects/triangle/triangle.lpr b/projects/triangle/triangle.lpr index 9d6beeb..32c0b5a 100644 --- a/projects/triangle/triangle.lpr +++ b/projects/triangle/triangle.lpr @@ -1,12 +1,13 @@ program triangle; {$mode objfpc}{$H+} +{$APPTYPE CONSOLE} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} - Interfaces, Dialogs, Forms, uMainForm, Vulkan, uvkuInstance, uvkuUtils, uvkuInstanceEx, uvkuPhysicalDevice; + Interfaces, Dialogs, Forms, uMainForm, Vulkan; {$R *.res} diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps index 1ef1b0e..0cf8ed8 100644 --- a/projects/triangle/triangle.lps +++ b/projects/triangle/triangle.lps @@ -4,13 +4,14 @@ - + - - - + + + + @@ -18,208 +19,216 @@ - - - + + - - - - + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + - - + + - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - + diff --git a/projects/triangle/uMainForm.pas b/projects/triangle/uMainForm.pas index 5fcb45c..7fc4eae 100644 --- a/projects/triangle/uMainForm.pas +++ b/projects/triangle/uMainForm.pas @@ -6,15 +6,18 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - Vulkan, uvkuInstanceEx; + Vulkan, uvkuInstanceEx, uvkuPhysicalDevice, uvkuUtils; type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TCustomAllocHandler = class(TvkuAllocationHandler) protected - procedure InternalAllocationNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); - procedure InternalFreeNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); + function AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override; + function ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override; + procedure FreeMemory(const aMemory: PVkVoid); override; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TMainForm = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); @@ -31,18 +34,40 @@ implementation {$R *.lfm} -procedure TCustomAllocHandler.InternalAllocationNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TCustomAllocHandler//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TCustomAllocHandler.AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; begin - inherited InternalAllocationNotification(aSize, aType, aScope); + result := inherited AllocateMemory(aSize, aAlignment, aScope); + WriteLn(Format('%d bytes of memory allocated at %p', [ aSize, result ])); end; -procedure TCustomAllocHandler.InternalFreeNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TCustomAllocHandler.ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; +var p: PVkVoid; begin - inherited InternalFreeNotification(aSize, aType, aScope); + p := aOriginal; + result := inherited ReallocateMemory(aOriginal, aSize, aAlignment, aScope); + WriteLn(Format('%d bytes of memory (from %p) reallocated at %p', [ aSize, p, result ])); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TCustomAllocHandler.FreeMemory(const aMemory: PVkVoid); +begin + WriteLn(Format('free memory at %p', [ aMemory ])); + inherited FreeMemory(aMemory); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TMainForm////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TMainForm.FormCreate(Sender: TObject); +var + i: Integer; + d: TvkuPhysicalDevice; begin + WriteLn('create vulkan instance'); fIntance := TvkuInstanceEx.Create( 0, [], @@ -50,8 +75,17 @@ begin TvkuInstanceEx.DefaultApplicationInfo, TvkuAllocationHandler.Create, true); + + WriteLn('read vulkan devices:'); + for i := 0 to fIntance.PhysicalDeviceCount-1 do begin + d := fIntance.PhysicalDevices[i]; + WriteLn(vkuMakeString(d.GetFeatures, ', ')); + WriteLn(vkuMakeString(d.GetProperties, true, true)); + WriteLn(vkuMakeString(d.GetMemoryProperties)); + end; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TMainForm.FormDestroy(Sender: TObject); begin FreeAndNil(fIntance); diff --git a/projects/utils/uvkuInstance.pas b/projects/utils/uvkuInstance.pas index 1ef5e06..630770f 100644 --- a/projects/utils/uvkuInstance.pas +++ b/projects/utils/uvkuInstance.pas @@ -5,7 +5,8 @@ unit uvkuInstance; interface uses - Classes, SysUtils, Vulkan; + Classes, SysUtils, + Vulkan, uvkuPhysicalDevice; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -13,17 +14,19 @@ type private fHandle: VkInstance; fAllocCallbacks: PVkAllocationCallbacks; - fPhysicalDevices: array of VkPhysicalDevice; + fPhysicalDevices: array of TvkuPhysicalDevice; function GetPhysicalDeviceCount: Integer; - function GetPhysicalDevices(const aIndex: Integer): VkPhysicalDevice; + function GetPhysicalDevices(const aIndex: Integer): TvkuPhysicalDevice; procedure UpdatePhysicalDevices; + procedure ClearPhysicalDevices; protected procedure CreateHandle(aCreateInfo: PVkInstanceCreateInfo; aAllocCallbacks: PVkAllocationCallbacks); constructor Create; public - property PhysicalDeviceCount: Integer read GetPhysicalDeviceCount; - property PhysicalDevices[const aIndex: Integer]: VkPhysicalDevice read GetPhysicalDevices; + property Handle: VkInstance read fHandle; + property PhysicalDeviceCount: Integer read GetPhysicalDeviceCount; + property PhysicalDevices[const aIndex: Integer]: TvkuPhysicalDevice read GetPhysicalDevices; constructor Create(const aCreateInfo: TVkInstanceCreateInfo); constructor Create(const aCreateInfo: TVkInstanceCreateInfo; const aAllocCallbacks: TVkAllocationCallbacks); @@ -45,18 +48,20 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuInstance.GetPhysicalDevices(const aIndex: Integer): VkPhysicalDevice; +function TvkuInstance.GetPhysicalDevices(const aIndex: Integer): TvkuPhysicalDevice; begin UpdatePhysicalDevices; if (aIndex < Low(fPhysicalDevices)) or (aIndex > High(fPhysicalDevices)) then - raise TvkuException.CreateFmt('index (%d) out of range (%d-%d)', [aIndex, Low(fPhysicalDevices), High(fPhysicalDevices)]); + raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fPhysicalDevices), High(fPhysicalDevices)]); result := fPhysicalDevices[aIndex]; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuInstance.UpdatePhysicalDevices; var + i: Integer; c: VkUint32; + arr: array of VkPhysicalDevice; err: TVkResult; begin if (Length(fPhysicalDevices) > 0) then @@ -65,11 +70,24 @@ begin err := vkEnumeratePhysicalDevices(fHandle, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device number', err); - SetLength(fPhysicalDevices, c); + SetLength(arr, c); - err := vkEnumeratePhysicalDevices(fHandle, @c, @fPhysicalDevices[0]); + err := vkEnumeratePhysicalDevices(fHandle, @c, @arr[0]); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical devices', err); + + SetLength(fPhysicalDevices, c); + for i := 0 to c-1 do + fPhysicalDevices[i] := TvkuPhysicalDevice.Create(arr[i]); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuInstance.ClearPhysicalDevices; +var i: Integer; +begin + for i := low(fPhysicalDevices) to high(fPhysicalDevices) do + FreeAndNil(fPhysicalDevices[i]); + SetLength(fPhysicalDevices, 0); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -110,6 +128,7 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuInstance.Destroy; begin + ClearPhysicalDevices; if Assigned(fHandle) then begin vkDestroyInstance(fHandle, fAllocCallbacks); fHandle := nil; diff --git a/projects/utils/uvkuPhysicalDevice.pas b/projects/utils/uvkuPhysicalDevice.pas index f2333e3..cf86195 100644 --- a/projects/utils/uvkuPhysicalDevice.pas +++ b/projects/utils/uvkuPhysicalDevice.pas @@ -10,54 +10,41 @@ uses type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TVkQueueFamilyPropertiesArr = array of TVkQueueFamilyProperties; TVkSparseImageFormatPropertiesArr = array of TVkSparseImageFormatProperties; TvkuPhysicalDevice = class(TObject) - private type - TPropertyFlag = ( - pfFeatures, - pfProperties, - pfMemoryProperties - ); - TPropertyFlags = set of TPropertyFlag; private fHandle: VkPhysicalDevice; - fCached: TPropertyFlags; - - fFeatures: TVkPhysicalDeviceFeatures; - fProperties: TVkPhysicalDeviceProperties; - fMemoryProperties: TVkPhysicalDeviceMemoryProperties; - fFormatProperties: array[TVkFormat] of PVkFormatProperties; - + function GetQueueFamilyProperties(const aIndex: Integer): TVkQueueFamilyProperties; + function GetQueueFamilyPropertyCount: Integer; + public function GetFeatures: TVkPhysicalDeviceFeatures; function GetProperties: TVkPhysicalDeviceProperties; function GetMemoryProperties: TVkPhysicalDeviceMemoryProperties; - function GetQueueFamilyPropertyCount: Integer; - function GetQueueFamilyProperties(const aIndex: Integer): TVkQueueFamilyProperties; + function GetQueueFamilyProperties: TVkQueueFamilyPropertiesArr; function GetFormatProperties(const aFormat: TVkFormat): TVkFormatProperties; - public - property Handle: VkPhysicalDevice read fHandle; - property Features: TVkPhysicalDeviceFeatures read GetFeatures; - property Properties: TVkPhysicalDeviceProperties read GetProperties; - property MemoryProperties: TVkPhysicalDeviceMemoryProperties read GetMemoryProperties; - - property QueueFamilyPropertyCount: Integer read GetQueueFamilyPropertyCount; - property QueueFamilyProperties[const aIndex: Integer]: TVkQueueFamilyProperties read GetQueueFamilyProperties; - - property FormatProperties[const aFormat: TVkFormat]: TVkFormatProperties read GetFormatProperties; - function GetImageFormatProperties( const aFormat: TVkFormat; const aImageType: TVkImageType; const aTiling: TVkImageTiling; const aUsage: VkImageUsageFlags; const aFlags: VkImageCreateFlags): TVkImageFormatProperties; - function GetSparseImageFormatProperties( const aFormat: TVkFormat; const aImageType: TVkImageType; const aSamples: TVkSampleCountFlagBits; const aUsage: VkImageUsageFlags; const aTiling: TVkImageTiling): TVkSparseImageFormatPropertiesArr; + public + property Handle: VkPhysicalDevice read fHandle; + property Features: TVkPhysicalDeviceFeatures read GetFeatures; + property Properties: TVkPhysicalDeviceProperties read GetProperties; + property MemoryProperties: TVkPhysicalDeviceMemoryProperties read GetMemoryProperties; + + property QueueFamilyPropertyCount: Integer read GetQueueFamilyPropertyCount; + property QueueFamilyProperties[const aIndex: Integer]: TVkQueueFamilyProperties read GetQueueFamilyProperties; + + property FormatProperties[const aFormat: TVkFormat]: TVkFormatProperties read GetFormatProperties; constructor Create(const aHandle: VkPhysicalDevice); end; @@ -70,65 +57,72 @@ uses ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuPhysicalDevice///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDevice.GetFeatures: TVkPhysicalDeviceFeatures; +function TvkuPhysicalDevice.GetQueueFamilyProperties(const aIndex: Integer): TVkQueueFamilyProperties; +var arr: TVkQueueFamilyPropertiesArr; begin - if not (pfFeatures in fCached) then begin - vkGetPhysicalDeviceFeatures(fHandle, @fFeatures); - Include(fCached, pfFeatures); - end; - result := fFeatures; + arr := GetQueueFamilyProperties(); + if (aIndex < Low(arr)) or (aIndex > High(arr)) then + raise TvkuException.CreateFmt('index (%) out of range (%d : %d)', [aIndex, Low(arr), High(arr)]); + result := arr[aIndex]; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDevice.GetProperties: TVkPhysicalDeviceProperties; +function TvkuPhysicalDevice.GetQueueFamilyPropertyCount: Integer; begin - if not (pfProperties in fCached) then begin - vkGetPhysicalDeviceProperties(fHandle, @fProperties); - Include(fCached, pfProperties); - end; - result := fProperties; + result := Length(GetQueueFamilyProperties); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDevice.GetMemoryProperties: TVkPhysicalDeviceMemoryProperties; +function TvkuPhysicalDevice.GetFeatures: TVkPhysicalDeviceFeatures; begin - if not (pfMemoryProperties in fCached) then begin - vkGetPhysicalDeviceMemoryProperties(fHandle, @fMemoryProperties); - Include(fCached, pfMemoryProperties); - end; - result := fMemoryProperties; + vkGetPhysicalDeviceFeatures(fHandle, @result); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDevice.GetQueueFamilyPropertyCount: Integer; +function TvkuPhysicalDevice.GetProperties: TVkPhysicalDeviceProperties; begin - + vkGetPhysicalDeviceProperties(fHandle, @result); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDevice.GetQueueFamilyProperties(const aIndex: Integer): TVkQueueFamilyProperties; +function TvkuPhysicalDevice.GetMemoryProperties: TVkPhysicalDeviceMemoryProperties; begin + vkGetPhysicalDeviceMemoryProperties(fHandle, @result); +end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuPhysicalDevice.GetQueueFamilyProperties: TVkQueueFamilyPropertiesArr; +var c: VkUint32; +begin + vkGetPhysicalDeviceQueueFamilyProperties(fHandle, @c, nil); + SetLength(result, c); + vkGetPhysicalDeviceQueueFamilyProperties(fHandle, @c, @result[0]); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuPhysicalDevice.GetFormatProperties(const aFormat: TVkFormat): TVkFormatProperties; begin - + vkGetPhysicalDeviceFormatProperties(fHandle, aFormat, @result); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuPhysicalDevice.GetImageFormatProperties(const aFormat: TVkFormat; const aImageType: TVkImageType; const aTiling: TVkImageTiling; const aUsage: VkImageUsageFlags; const aFlags: VkImageCreateFlags): TVkImageFormatProperties; +var err: TVkResult; begin - + err := vkGetPhysicalDeviceImageFormatProperties(fHandle, aFormat, aImageType, aTiling, aUsage, aFlags, @result); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to get physical device image format properties', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuPhysicalDevice.GetSparseImageFormatProperties(const aFormat: TVkFormat; const aImageType: TVkImageType; const aSamples: TVkSampleCountFlagBits; const aUsage: VkImageUsageFlags; const aTiling: TVkImageTiling): TVkSparseImageFormatPropertiesArr; +var c: VkUint32; begin - + vkGetPhysicalDeviceSparseImageFormatProperties(fHandle, aFormat, aImageType, aSamples, aUsage, aTiling, @c, nil); + SetLength(result, c); + vkGetPhysicalDeviceSparseImageFormatProperties(fHandle, aFormat, aImageType, aSamples, aUsage, aTiling, @c, @result[0]); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/projects/utils/uvkuUtils.pas b/projects/utils/uvkuUtils.pas index 38d1c55..259a888 100644 --- a/projects/utils/uvkuUtils.pas +++ b/projects/utils/uvkuUtils.pas @@ -19,6 +19,10 @@ type constructor Create(const msg: string; const aError: TVkResult); 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; + implementation ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -30,5 +34,420 @@ begin fError := aError; 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(aProperties.limits.framebufferColorSampleCounts), + toString(aProperties.limits.framebufferDepthSampleCounts), + toString(aProperties.limits.framebufferStencilSampleCounts), + toString(aProperties.limits.framebufferNoAttachmentsSampleCounts), + toString(aProperties.limits.maxColorAttachments), + toString(aProperties.limits.sampledImageColorSampleCounts), + toString(aProperties.limits.sampledImageIntegerSampleCounts), + toString(aProperties.limits.sampledImageDepthSampleCounts), + toString(aProperties.limits.sampledImageStencilSampleCounts), + toString(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, 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, aMemoryProperties.memoryHeaps[i].flags]); + end; +end; + + end.