unit uvkuDeviceFactory; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan, uvkuDevice, uvkuTypes, uvkuFactoryBase, uvkuUtils; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuQueueCreateInfo = class(TvkuStructure) private fQueuePriorities: TVkFloatList; public Flags: VkDeviceQueueCreateFlags; QueueFamilyIndex: VkUint32; property QueuePriorities: TVkFloatList read fQueuePriorities; function GetStructure: TVkDeviceQueueCreateInfo; procedure SetStructure(const aData: TVkDeviceQueueCreateInfo); procedure AfterConstruction; override; procedure BeforeDestruction; override; end; TvkuQueueCreateInfoList = specialize TvkuObjList; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuPhysicalDeviceFeatures = class(TvkuStructure) RobustBufferAccess: VkBool32; FullDrawIndexUint32: VkBool32; ImageCubeArray: VkBool32; IndependentBlend: VkBool32; GeometryShader: VkBool32; TessellationShader: VkBool32; SampleRateShading: VkBool32; DualSrcBlend: VkBool32; LogicOp: VkBool32; MultiDrawIndirect: VkBool32; DrawIndirectFirstInstance: VkBool32; DepthClamp: VkBool32; DepthBiasClamp: VkBool32; FillModeNonSolid: VkBool32; DepthBounds: VkBool32; WideLines: VkBool32; LargePoints: VkBool32; AlphaToOne: VkBool32; MultiViewport: VkBool32; SamplerAnisotropy: VkBool32; TextureCompressionETC2: VkBool32; TextureCompressionASTC_LDR: VkBool32; TextureCompressionBC: VkBool32; OcclusionQueryPrecise: VkBool32; PipelineStatisticsQuery: VkBool32; VertexPipelineStoresAndAtomics: VkBool32; FragmentStoresAndAtomics: VkBool32; ShaderTessellationAndGeometryPointSize: VkBool32; ShaderImageGatherExtended: VkBool32; ShaderStorageImageExtendedFormats: VkBool32; ShaderStorageImageMultisample: VkBool32; ShaderStorageImageReadWithoutFormat: VkBool32; ShaderStorageImageWriteWithoutFormat: VkBool32; ShaderUniformBufferArrayDynamicIndexing: VkBool32; ShaderSampledImageArrayDynamicIndexing: VkBool32; ShaderStorageBufferArrayDynamicIndexing: VkBool32; ShaderStorageImageArrayDynamicIndexing: VkBool32; ShaderClipDistance: VkBool32; ShaderCullDistance: VkBool32; ShaderFloat64: VkBool32; ShaderInt64: VkBool32; ShaderInt16: VkBool32; ShaderResourceResidency: VkBool32; ShaderResourceMinLod: VkBool32; SparseBinding: VkBool32; SparseResidencyBuffer: VkBool32; SparseResidencyImage2D: VkBool32; SparseResidencyImage3D: VkBool32; SparseResidency2Samples: VkBool32; SparseResidency4Samples: VkBool32; SparseResidency8Samples: VkBool32; SparseResidency16Samples: VkBool32; SparseResidencyAliased: VkBool32; VariableMultisampleRate: VkBool32; InheritedQueries: VkBool32; function GetStructure: TVkPhysicalDeviceFeatures; procedure SetStructure(const aData: TVkPhysicalDeviceFeatures); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuDeviceFactory = class(TvkuInstanceObjFactory) private fEnabledFeatures: TvkuPhysicalDeviceFeatures; fFlags: VkDeviceCreateFlags; fEnabledLayerNames: TStringList; fEnabledExtensionNames: TStringList; fQueueCreateInfos: TvkuQueueCreateInfoList; fvkEnabledFeatures: TVkPhysicalDeviceFeatures; fvkEnabledLayerNames: array of PVkChar; fvkEnabledExtensionNames: array of PVkChar; fvkQueueCreateInfos: array of TVkDeviceQueueCreateInfo; function GetEnabledLayerNames: TStrings; function GetEnabledExtensionNames: TStrings; public property Flags: VkDeviceCreateFlags read fFlags write fFlags; property EnabledLayerNames: TStrings read GetEnabledLayerNames; property EnabledExtensionNames: TStrings read GetEnabledExtensionNames; property EnabledFeatures: TvkuPhysicalDeviceFeatures read fEnabledFeatures; property QueueCreateInfos: TvkuQueueCreateInfoList read fQueueCreateInfos; function GetStructure: TVkDeviceCreateInfo; procedure SetStructure(const aData: TVkDeviceCreateInfo); function CreateDevice(const aPhysicalDevice: VkPhysicalDevice): TvkuDevice; procedure AfterConstruction; override; procedure BeforeDestruction; override; end; implementation ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuQueueCreateInfo//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuQueueCreateInfo.GetStructure: TVkDeviceQueueCreateInfo; begin FillByte(result, SizeOf(result), 0); result.sType := VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; result.pNext := nil; result.flags := Flags; result.queueFamilyIndex := QueueFamilyIndex; result.queueCount := fQueuePriorities.Length; result.pQueuePriorities := fQueuePriorities.PData; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuQueueCreateInfo.SetStructure(const aData: TVkDeviceQueueCreateInfo); var i: Integer; begin Flags := aData.flags; QueueFamilyIndex := aData.queueFamilyIndex; fQueuePriorities.Length := aData.queueCount; for i := 0 to fQueuePriorities.Length-1 do fQueuePriorities[i] := (aData.pQueuePriorities + i)^; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuQueueCreateInfo.AfterConstruction; begin inherited AfterConstruction; fQueuePriorities := TVkFloatList.Create; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuQueueCreateInfo.BeforeDestruction; begin FreeAndNil(fQueuePriorities); inherited BeforeDestruction; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuPhysicalDeviceFeatures///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuPhysicalDeviceFeatures.GetStructure: TVkPhysicalDeviceFeatures; begin FillByte(result, SizeOf(result), 0); result.robustBufferAccess := RobustBufferAccess; result.fullDrawIndexUint32 := FullDrawIndexUint32; result.imageCubeArray := ImageCubeArray; result.independentBlend := IndependentBlend; result.geometryShader := GeometryShader; result.tessellationShader := TessellationShader; result.sampleRateShading := SampleRateShading; result.dualSrcBlend := DualSrcBlend; result.logicOp := LogicOp; result.multiDrawIndirect := MultiDrawIndirect; result.drawIndirectFirstInstance := DrawIndirectFirstInstance; result.depthClamp := DepthClamp; result.depthBiasClamp := DepthBiasClamp; result.fillModeNonSolid := FillModeNonSolid; result.depthBounds := DepthBounds; result.wideLines := WideLines; result.largePoints := LargePoints; result.alphaToOne := AlphaToOne; result.multiViewport := MultiViewport; result.samplerAnisotropy := SamplerAnisotropy; result.textureCompressionETC2 := TextureCompressionETC2; result.textureCompressionASTC_LDR := TextureCompressionASTC_LDR; result.textureCompressionBC := TextureCompressionBC; result.occlusionQueryPrecise := OcclusionQueryPrecise; result.pipelineStatisticsQuery := PipelineStatisticsQuery; result.vertexPipelineStoresAndAtomics := VertexPipelineStoresAndAtomics; result.fragmentStoresAndAtomics := FragmentStoresAndAtomics; result.shaderTessellationAndGeometryPointSize := ShaderTessellationAndGeometryPointSize; result.shaderImageGatherExtended := ShaderImageGatherExtended; result.shaderStorageImageExtendedFormats := ShaderStorageImageExtendedFormats; result.shaderStorageImageMultisample := ShaderStorageImageMultisample; result.shaderStorageImageReadWithoutFormat := ShaderStorageImageReadWithoutFormat; result.shaderStorageImageWriteWithoutFormat := ShaderStorageImageWriteWithoutFormat; result.shaderUniformBufferArrayDynamicIndexing := ShaderUniformBufferArrayDynamicIndexing; result.shaderSampledImageArrayDynamicIndexing := ShaderSampledImageArrayDynamicIndexing; result.shaderStorageBufferArrayDynamicIndexing := ShaderStorageBufferArrayDynamicIndexing; result.shaderStorageImageArrayDynamicIndexing := ShaderStorageImageArrayDynamicIndexing; result.shaderClipDistance := ShaderClipDistance; result.shaderCullDistance := ShaderCullDistance; result.shaderFloat64 := ShaderFloat64; result.shaderInt64 := ShaderInt64; result.shaderInt16 := ShaderInt16; result.shaderResourceResidency := ShaderResourceResidency; result.shaderResourceMinLod := ShaderResourceMinLod; result.sparseBinding := SparseBinding; result.sparseResidencyBuffer := SparseResidencyBuffer; result.sparseResidencyImage2D := SparseResidencyImage2D; result.sparseResidencyImage3D := SparseResidencyImage3D; result.sparseResidency2Samples := SparseResidency2Samples; result.sparseResidency4Samples := SparseResidency4Samples; result.sparseResidency8Samples := SparseResidency8Samples; result.sparseResidency16Samples := SparseResidency16Samples; result.sparseResidencyAliased := SparseResidencyAliased; result.variableMultisampleRate := VariableMultisampleRate; result.inheritedQueries := InheritedQueries; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuPhysicalDeviceFeatures.SetStructure(const aData: TVkPhysicalDeviceFeatures); begin RobustBufferAccess := aData.robustBufferAccess; FullDrawIndexUint32 := aData.fullDrawIndexUint32; ImageCubeArray := aData.imageCubeArray; IndependentBlend := aData.independentBlend; GeometryShader := aData.geometryShader; TessellationShader := aData.tessellationShader; SampleRateShading := aData.sampleRateShading; DualSrcBlend := aData.dualSrcBlend; LogicOp := aData.logicOp; MultiDrawIndirect := aData.multiDrawIndirect; DrawIndirectFirstInstance := aData.drawIndirectFirstInstance; DepthClamp := aData.depthClamp; DepthBiasClamp := aData.depthBiasClamp; FillModeNonSolid := aData.fillModeNonSolid; DepthBounds := aData.depthBounds; WideLines := aData.wideLines; LargePoints := aData.largePoints; AlphaToOne := aData.alphaToOne; MultiViewport := aData.multiViewport; SamplerAnisotropy := aData.samplerAnisotropy; TextureCompressionETC2 := aData.textureCompressionETC2; TextureCompressionASTC_LDR := aData.textureCompressionASTC_LDR; TextureCompressionBC := aData.textureCompressionBC; OcclusionQueryPrecise := aData.occlusionQueryPrecise; PipelineStatisticsQuery := aData.pipelineStatisticsQuery; VertexPipelineStoresAndAtomics := aData.vertexPipelineStoresAndAtomics; FragmentStoresAndAtomics := aData.fragmentStoresAndAtomics; ShaderTessellationAndGeometryPointSize := aData.shaderTessellationAndGeometryPointSize; ShaderImageGatherExtended := aData.shaderImageGatherExtended; ShaderStorageImageExtendedFormats := aData.shaderStorageImageExtendedFormats; ShaderStorageImageMultisample := aData.shaderStorageImageMultisample; ShaderStorageImageReadWithoutFormat := aData.shaderStorageImageReadWithoutFormat; ShaderStorageImageWriteWithoutFormat := aData.shaderStorageImageWriteWithoutFormat; ShaderUniformBufferArrayDynamicIndexing := aData.shaderUniformBufferArrayDynamicIndexing; ShaderSampledImageArrayDynamicIndexing := aData.shaderSampledImageArrayDynamicIndexing; ShaderStorageBufferArrayDynamicIndexing := aData.shaderStorageBufferArrayDynamicIndexing; ShaderStorageImageArrayDynamicIndexing := aData.shaderStorageImageArrayDynamicIndexing; ShaderClipDistance := aData.shaderClipDistance; ShaderCullDistance := aData.shaderCullDistance; ShaderFloat64 := aData.shaderFloat64; ShaderInt64 := aData.shaderInt64; ShaderInt16 := aData.shaderInt16; ShaderResourceResidency := aData.shaderResourceResidency; ShaderResourceMinLod := aData.shaderResourceMinLod; SparseBinding := aData.sparseBinding; SparseResidencyBuffer := aData.sparseResidencyBuffer; SparseResidencyImage2D := aData.sparseResidencyImage2D; SparseResidencyImage3D := aData.sparseResidencyImage3D; SparseResidency2Samples := aData.sparseResidency2Samples; SparseResidency4Samples := aData.sparseResidency4Samples; SparseResidency8Samples := aData.sparseResidency8Samples; SparseResidency16Samples := aData.sparseResidency16Samples; SparseResidencyAliased := aData.sparseResidencyAliased; VariableMultisampleRate := aData.variableMultisampleRate; InheritedQueries := aData.inheritedQueries; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuDeviceFactory////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDeviceFactory.GetEnabledLayerNames: TStrings; begin result := fEnabledLayerNames; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDeviceFactory.GetEnabledExtensionNames: TStrings; begin result := fEnabledExtensionNames; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDeviceFactory.GetStructure: TVkDeviceCreateInfo; var i: Integer; begin if (fQueueCreateInfos.Length <= 0) then raise TvkuException.Create('no queue create infos assigned'); fvkEnabledFeatures := fEnabledFeatures.GetStructure; SetLength(fvkEnabledLayerNames, fEnabledLayerNames.Count); for i := 0 to fEnabledLayerNames.Count-1 do fvkEnabledLayerNames[i] := PVkChar(fEnabledLayerNames[i]); SetLength(fvkEnabledExtensionNames, fEnabledExtensionNames.Count); for i := 0 to fEnabledExtensionNames.Count-1 do fvkEnabledExtensionNames[i] := PVkChar(fEnabledExtensionNames[i]); SetLength(fvkQueueCreateInfos, fQueueCreateInfos.Length); for i := low(fvkQueueCreateInfos) to high(fvkQueueCreateInfos) do fvkQueueCreateInfos[i] := fQueueCreateInfos[i].GetStructure; FillByte(result, SizeOf(result), 0); result.sType := VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; result.pNext := nil; result.flags := fFlags; result.queueCreateInfoCount := Length(fvkQueueCreateInfos); result.pQueueCreateInfos := @fvkQueueCreateInfos[0]; result.enabledLayerCount := Length(fvkEnabledLayerNames); result.ppEnabledLayerNames := @fvkEnabledLayerNames[0]; result.enabledExtensionCount := Length(fvkEnabledExtensionNames); result.ppEnabledExtensionNames := @fvkEnabledExtensionNames[0]; result.pEnabledFeatures := @fvkEnabledFeatures; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuDeviceFactory.SetStructure(const aData: TVkDeviceCreateInfo); var i: Integer; begin if Assigned(aData.pEnabledFeatures) then fEnabledFeatures.SetStructure(aData.pEnabledFeatures^); fEnabledLayerNames.Clear; for i := 0 to aData.enabledLayerCount-1 do fEnabledLayerNames.Add(aData.ppEnabledLayerNames[i]); fEnabledExtensionNames.Clear; for i := 0 to aData.enabledExtensionCount-1 do fEnabledExtensionNames.Add(aData.ppEnabledExtensionNames[i]); fQueueCreateInfos.Length := aData.queueCreateInfoCount; for i := 0 to fQueueCreateInfos.Length-1 do fQueueCreateInfos[i].SetStructure((aData.pQueueCreateInfos + i)^); fFlags := aData.flags; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDeviceFactory.CreateDevice(const aPhysicalDevice: VkPhysicalDevice): TvkuDevice; begin result := TvkuDevice.Create(aPhysicalDevice, GetStructure, InstanceCommands, AllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuDeviceFactory.AfterConstruction; begin inherited AfterConstruction; fEnabledFeatures := TvkuPhysicalDeviceFeatures.Create; fEnabledLayerNames := TStringList.Create; fEnabledExtensionNames := TStringList.Create; fQueueCreateInfos := TvkuQueueCreateInfoList.Create; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuDeviceFactory.BeforeDestruction; begin FreeAndNil(fQueueCreateInfos); FreeAndNil(fEnabledLayerNames); FreeAndNil(fEnabledExtensionNames); FreeAndNil(fEnabledFeatures); inherited BeforeDestruction; end; end.