|
- unit uvkuDevice;
-
- {$mode objfpc}{$H+}
-
- interface
-
- uses
- Classes, SysUtils,
- Vulkan, uvkuBase, uvkuTypes;
-
- type
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuDescriptorImageInfo = class(TvkuStructure)
- Sampler: VkSampler;
- ImageView: VkImageView;
- ImageLayout: TVkImageLayout;
-
- function GetStructure: TVkDescriptorImageInfo;
- procedure SetStructure(const aData: TVkDescriptorImageInfo);
- end;
- TvkuDescriptorImageInfoList = specialize TvkuObjList<TvkuDescriptorImageInfo>;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuDescriptorBufferInfo = class(TvkuStructure)
- Buffer: VkBuffer;
- Offset: VkDeviceSize;
- Range: VkDeviceSize;
-
- function GetStructure: TVkDescriptorBufferInfo;
- procedure SetStructure(const aData: TVkDescriptorBufferInfo);
- end;
- TvkuDescriptorBufferInfoList = specialize TvkuObjList<TvkuDescriptorBufferInfo>;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuWriteDescriptorSet = class(TvkuStructure)
- private
- fImageInfos: TvkuDescriptorImageInfoList;
- fBufferInfos: TvkuDescriptorBufferInfoList;
- fTexelBufferViews: TVkBufferViewList;
-
- fvkImageInfos: TVkDescriptorImageInfoArr;
- fvkBufferInfos: TVkDescriptorBufferInfoArr;
- public
- DstSet: VkDescriptorSet;
- DstBinding: VkUint32;
- DstArrayElement: VkUint32;
- DescriptorType: TVkDescriptorType;
-
- property ImageInfos: TvkuDescriptorImageInfoList read fImageInfos;
- property BufferInfos: TvkuDescriptorBufferInfoList read fBufferInfos;
-
- function GetStructure: TVkWriteDescriptorSet;
- procedure SetStructure(const aData: TVkWriteDescriptorSet);
-
- procedure AfterConstruction; override;
- procedure BeforeDestruction; override;
- end;
- TvkuWriteDescriptorSetList = specialize TvkuObjList<TvkuWriteDescriptorSet>;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuCopyDescriptorSet = class(TvkuStructure)
- public
- SrcSet: VkDescriptorSet;
- SrcBinding: VkUint32;
- SrcArrayElement: VkUint32;
- DstSet: VkDescriptorSet;
- DstBinding: VkUint32;
- DstArrayElement: VkUint32;
- DescriptorCount: VkUint32;
-
- function GetStructure: TVkCopyDescriptorSet;
- procedure SetStructure(const aData: TVkCopyDescriptorSet);
- end;
- TvkuCopyDescriptorSetList = specialize TvkuObjList<TvkuCopyDescriptorSet>;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuUpdateDescriptorSetHelper = class(TvkuCommandHelper)
- private
- fDeviceCommands: TVkDeviceCommands;
- fWriteDescriptorSets: TvkuWriteDescriptorSetList;
- fCopyDescriptorSets: TvkuCopyDescriptorSetList;
- public
- property WriteDescriptorSets: TvkuWriteDescriptorSetList read fWriteDescriptorSets;
- property CopyDescriptorSets: TvkuCopyDescriptorSetList read fCopyDescriptorSets;
-
- procedure Execute;
-
- constructor Create(const aDeviceCommands: TVkDeviceCommands);
- destructor Destroy; override;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuDevice = class(TvkuAllocHandle)
- private
- fHandle: VkDevice;
- fInstanceCommands: TVkInstanceCommands;
- fDeviceCommands: TVkDeviceCommands;
-
- procedure CreateHandle(
- const aPhyDevice: VkPhysicalDevice;
- const aCreateInfo: PVkDeviceCreateInfo);
- public
- property Handle: VkDevice read fHandle;
- property DeviceCommands: TVkDeviceCommands read fDeviceCommands;
-
- function GetQueue(
- const aQueueFamilyIndex: VkUint32;
- const aQueueIndex: VkUint32): VkQueue;
- function AllocateMemory(
- const aSize: VkUint32;
- const aMemoryTypeIndex: VkUint32;
- aAllocCallbacks: PVkAllocationCallbacks = nil): VkDeviceMemory;
- procedure FreeMemory(
- const aMemory: VkDeviceMemory;
- aAllocCallbacks: PVkAllocationCallbacks = nil);
- procedure WaitIdle;
-
- function UpdateDescriptorSet: TvkuUpdateDescriptorSetHelper;
-
- constructor Create(
- const aPhysicalDevice: VkPhysicalDevice;
- const aCreateInfo: TVkDeviceCreateInfo;
- const aInstanceCommands: TVkInstanceCommands;
- const aAllocCallbacks: PVkAllocationCallbacks = nil);
- constructor Create(
- const aHandle: VkDevice;
- const aOwnsHandle: Boolean;
- const aInstanceCommands: TVkInstanceCommands;
- const aAllocCallbacks: PVkAllocationCallbacks = nil);
- destructor Destroy; override;
- end;
-
- implementation
-
- uses
- uvkuUtils;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuDescriptorImageInfo////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuDescriptorImageInfo.GetStructure: TVkDescriptorImageInfo;
- begin
- FillByte(result, SizeOf(result), 0);
- result.sampler := Sampler;
- result.imageView := ImageView;
- result.imageLayout := ImageLayout;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuDescriptorImageInfo.SetStructure(const aData: TVkDescriptorImageInfo);
- begin
- Sampler := aData.sampler;
- ImageView := aData.imageView;
- ImageLayout := aData.imageLayout;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuDescriptorBufferInfo///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuDescriptorBufferInfo.GetStructure: TVkDescriptorBufferInfo;
- begin
- FillByte(result, SizeOf(result), 0);
- result.buffer := Buffer;
- result.offset := Offset;
- result.range := Range;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuDescriptorBufferInfo.SetStructure(const aData: TVkDescriptorBufferInfo);
- begin
- Buffer := aData.buffer;
- Offset := aData.offset;
- Range := aData.range;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuWriteDescriptorSet/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuWriteDescriptorSet.GetStructure: TVkWriteDescriptorSet;
- var c, i: Integer;
- begin
- c := fImageInfos.Length;
- if (c < fBufferInfos.Length) then
- c := fBufferInfos.Length;
- if (c < fTexelBufferViews.Length) then
- c := fTexelBufferViews.Length;
-
- SetLength(fvkImageInfos, fImageInfos.Length);
- if (fImageInfos.Length <> 0) and (fImageInfos.Length <> c) then
- raise TvkuException.Create('ImageInfos, BufferInfos and TexelBufferViews must be empty or must have the same size!');
- for i := low(fvkImageInfos) to high(fvkImageInfos) do
- fvkImageInfos[i] := fImageInfos[i].GetStructure;
-
- SetLength(fvkBufferInfos, fBufferInfos.Length);
- if (fBufferInfos.Length <> 0) and (fBufferInfos.Length <> c) then
- raise TvkuException.Create('ImageInfos, BufferInfos and TexelBufferViews must be empty or must have the same size!');
- for i := low(fvkBufferInfos) to high(fvkBufferInfos) do
- fvkBufferInfos[i] := fBufferInfos[i].GetStructure;
-
- if (fTexelBufferViews.Length <> 0) and (fTexelBufferViews.Length <> c) then
- raise TvkuException.Create('ImageInfos, BufferInfos and TexelBufferViews must be empty or must have the same size!');
-
- FillByte(result, SizeOf(result), 0);
- result.sType := VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- result.pNext := nil;
- result.dstSet := DstSet;
- result.dstBinding := DstBinding;
- result.dstArrayElement := DstArrayElement;
- result.descriptorCount := c;
- result.descriptorType := DescriptorType;
- result.pImageInfo := @fvkImageInfos[0];
- result.pBufferInfo := @fvkBufferInfos[0];
- result.pTexelBufferView := fTexelBufferViews.PData;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuWriteDescriptorSet.SetStructure(const aData: TVkWriteDescriptorSet);
- var i: Integer;
- begin
- if Assigned(aData.pImageInfo) then begin
- fImageInfos.Length := aData.descriptorCount;
- for i := 0 to fImageInfos.Length-1 do
- fImageInfos[i].SetStructure((aData.pImageInfo + i)^);
- end;
-
- if Assigned(aData.pBufferInfo) then begin
- fBufferInfos.Length := aData.descriptorCount;
- for i := 0 to fBufferInfos.Length-1 do
- fBufferInfos[i].SetStructure((aData.pBufferInfo + i)^);
- end;
-
- fTexelBufferViews.SetData(aData.pTexelBufferView, aData.descriptorCount);
-
- DstSet := aData.dstSet;
- DstBinding := aData.dstBinding;
- DstArrayElement := aData.dstArrayElement;
- DescriptorType := aData.descriptorType;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuWriteDescriptorSet.AfterConstruction;
- begin
- inherited AfterConstruction;
- fImageInfos := TvkuDescriptorImageInfoList.Create;
- fBufferInfos := TvkuDescriptorBufferInfoList.Create;
- fTexelBufferViews := TVkBufferViewList.Create;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuWriteDescriptorSet.BeforeDestruction;
- begin
- FreeAndNil(fImageInfos);
- FreeAndNil(fBufferInfos);
- FreeAndNil(fTexelBufferViews);
- inherited BeforeDestruction;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuCopyDescriptorSet//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuCopyDescriptorSet.GetStructure: TVkCopyDescriptorSet;
- begin
- result.sType := VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
- result.pNext := nil;
- result.srcSet := SrcSet;
- result.srcBinding := SrcBinding;
- result.srcArrayElement := SrcArrayElement;
- result.dstSet := DstSet;
- result.dstBinding := DstBinding;
- result.dstArrayElement := DstArrayElement;
- result.descriptorCount := DescriptorCount;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuCopyDescriptorSet.SetStructure(const aData: TVkCopyDescriptorSet);
- begin
- SrcSet := aData.srcSet;
- SrcBinding := aData.srcBinding;
- SrcArrayElement := aData.srcArrayElement;
- DstSet := aData.dstSet;
- DstBinding := aData.dstBinding;
- DstArrayElement := aData.dstArrayElement;
- DescriptorCount := aData.descriptorCount;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuUpdateDescriptorSetHelper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuUpdateDescriptorSetHelper.Execute;
- var
- i: Integer;
- vkWriteDescriptorSets: array of TVkWriteDescriptorSet;
- vkCopyDescriptorSets: array of TVkCopyDescriptorSet;
- begin
- SetLength(vkWriteDescriptorSets, fWriteDescriptorSets.Length);
- for i := low(vkWriteDescriptorSets) to high(vkWriteDescriptorSets) do
- vkWriteDescriptorSets[i] := fWriteDescriptorSets[i].GetStructure;
-
- SetLength(vkCopyDescriptorSets, fCopyDescriptorSets.Length);
- for i := low(vkCopyDescriptorSets) to high(vkCopyDescriptorSets) do
- vkCopyDescriptorSets[i] := fCopyDescriptorSets[i].GetStructure;
-
- fDeviceCommands.vkUpdateDescriptorSets(
- fDeviceCommands.Device,
- Length(vkWriteDescriptorSets),
- @vkWriteDescriptorSets[0],
- Length(vkCopyDescriptorSets),
- @vkCopyDescriptorSets[0]);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TvkuUpdateDescriptorSetHelper.Create(const aDeviceCommands: TVkDeviceCommands);
- begin
- inherited Create;
- fDeviceCommands := aDeviceCommands;
- fWriteDescriptorSets := TvkuWriteDescriptorSetList.Create;
- fCopyDescriptorSets := TvkuCopyDescriptorSetList.Create;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TvkuUpdateDescriptorSetHelper.Destroy;
- begin
- FreeAndNil(fCopyDescriptorSets);
- FreeAndNil(fWriteDescriptorSets);
- inherited Destroy;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //TvkuDevice/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuDevice.CreateHandle(const aPhyDevice: VkPhysicalDevice; const aCreateInfo: PVkDeviceCreateInfo);
- var err: TVkResult;
- begin
- if not Assigned(fInstanceCommands.vkCreateDevice) then
- raise TvkuInvalidFuncPtrException.Create('vkCreateDevice');
- err := fInstanceCommands.vkCreateDevice(aPhyDevice, aCreateInfo, AllocCallbacks, @fHandle);
- if (err <> VK_SUCCESS) then
- raise TvkuErrorException.Create('unable to create device', err);
- fDeviceCommands := LoadDeviceCommands(fInstanceCommands.Instance, fHandle);
- if not Assigned(fDeviceCommands) then
- raise TvkuException.Create('unable to load device commands');
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuDevice.GetQueue(const aQueueFamilyIndex: VkUint32; const aQueueIndex: VkUint32): VkQueue;
- begin
- if not Assigned(fDeviceCommands.vkGetDeviceQueue) then
- raise TvkuInvalidFuncPtrException.Create('vkGetDeviceQueue');
- fDeviceCommands.vkGetDeviceQueue(fHandle, aQueueFamilyIndex, aQueueIndex, @result);
- if (result = VK_INVALID_HANDLE) then
- raise TvkuException.Create('unable to get device queue');
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuDevice.AllocateMemory(const aSize: VkUint32; const aMemoryTypeIndex: VkUint32;
- aAllocCallbacks: PVkAllocationCallbacks): VkDeviceMemory;
- var
- AllocInfo: TVkMemoryAllocateInfo;
- err: TVkResult;
- begin
- FillByte(AllocInfo, SizeOf(AllocInfo), 0);
- AllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- AllocInfo.pNext := nil;
- AllocInfo.allocationSize := aSize;
- AllocInfo.memoryTypeIndex := aMemoryTypeIndex;
- if not Assigned(aAllocCallbacks) then
- aAllocCallbacks := AllocCallbacks;
- err := fDeviceCommands.vkAllocateMemory(fHandle, @AllocInfo, aAllocCallbacks, @result);
- if (err <> VK_SUCCESS) then
- raise TvkuErrorException.Create('unable to allocate device memory', err);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuDevice.FreeMemory(const aMemory: VkDeviceMemory; aAllocCallbacks: PVkAllocationCallbacks);
- begin
- if not Assigned(aAllocCallbacks) then
- aAllocCallbacks := AllocCallbacks;
- fDeviceCommands.vkFreeMemory(fHandle, aMemory, aAllocCallbacks);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuDevice.WaitIdle;
- var err: TVkResult;
- begin
- err := fDeviceCommands.vkDeviceWaitIdle(fHandle);
- if (err <> VK_SUCCESS) then
- raise TvkuErrorException.Create('unable to wait for device idle', err);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuDevice.UpdateDescriptorSet: TvkuUpdateDescriptorSetHelper;
- begin
- result := TvkuUpdateDescriptorSetHelper.Create(fDeviceCommands);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TvkuDevice.Create(const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo;
- const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks);
- begin
- inherited Create;
- fHandle := nil;
- fInstanceCommands := aInstanceCommands;
- SetAllocCallbacks(aAllocCallbacks);
- CreateHandle(aPhysicalDevice, @aCreateInfo);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- constructor TvkuDevice.Create(const aHandle: VkDevice; const aOwnsHandle: Boolean;
- const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks);
- begin
- inherited Create;
- fHandle := aHandle;
- fInstanceCommands := aInstanceCommands;
- OwnsHandle := aOwnsHandle;
- SetAllocCallbacks(aAllocCallbacks);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- destructor TvkuDevice.Destroy;
- begin
- if OwnsHandle and (fHandle <> VK_INVALID_HANDLE) then
- fDeviceCommands.vkDestroyDevice(fHandle, AllocCallbacks);
- fHandle := VK_INVALID_HANDLE;
- FreeAndNil(fDeviceCommands);
- inherited Destroy;
- end;
-
- end.
|