unit vImage; {$mode objfpc}{$H+} interface uses SysUtils, Vulkan, vDevice, vPipeline, vMemory, vDependence; const VK_FORMAT_R10G11B11_UFLOAT_FAKE32=TVkFormat(ord(VK_FORMAT_B10G11R11_UFLOAT_PACK32)+1000000000); type PvImageBarrier=^TvImageBarrier; TvImageBarrier=object type t_push_cb=function():TVkCommandBuffer of object; var //image:TVkImage; //range:TVkImageSubresourceRange; // AccessMask:TVkAccessFlags; ImgLayout :TVkImageLayout; StageMask :TVkPipelineStageFlags; Procedure Init({_image:TVkImage;_sub:TVkImageSubresourceRange}); function Push(cmd:TVkCommandBuffer; cb:t_push_cb; image:TVkImage; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags):Boolean; end; TvSwapChainImage=class FHandle:TVkImage; FView :TVkImage; Barrier:TvImageBarrier; procedure PushBarrier(cmd:TVkCommandBuffer; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags); end; TvSwapChain=class FSurface:TvSurface; FSize :TVkExtent2D; FHandle :TVkSwapchainKHR; FImages :array of TvSwapChainImage; Constructor Create(Surface:TvSurface;mode:Integer;imageUsage:TVkImageUsageFlags); Destructor Destroy; override; end; TvImageView=class(TvRefsObject) FHandle:TVkImageView; FName :RawByteString; procedure SetObjectName(const name:RawByteString); Destructor Destroy; override; end; TvCustomImage=class(TvRefsObject) FHandle:TVkImage; FFormat:TVkFormat; //real used format FBind :TvPointer; FSize :TVkDeviceSize; FName :RawByteString; function is_invalid:Boolean; procedure FreeHandle; virtual; Destructor Destroy; override; function GetImageInfo:TVkImageCreateInfo; virtual; abstract; function GetRequirements:TVkMemoryRequirements; function GetDedicatedAllocation:Boolean; function Compile(ext:Pointer):Boolean; virtual; function BindMem(P:TvPointer):TVkResult; procedure UnBindMem(do_free:Boolean); function Hold(Sender:TObject):Boolean; override; function Drop(Sender:TObject):Boolean; override; function OnReleaseMem(Sender:TObject):Boolean; virtual; procedure SetObjectName(const name:RawByteString); end; const //usage image TM_READ =1; TM_WRITE =2; TM_CLEAR =4; //Render target is cleared TM_MIXED =8; //Mixed image usage TM_INVAL=16; //invalid buffer/image type t_image_usage=(iu_attachment,iu_depthstenc,iu_sampled,iu_storage,iu_transfer,iu_buffer,iu_htile,iu_cmask,iu_degamma); s_image_usage=set of t_image_usage; type TvExtent3D=packed record width :Word; //(0..16383) height:Word; //(0..16383) depth :Word; //(0..8192) end; TvDstSel=bitpacked record x,y,z,w:0..15; //(0..6) end; TvImageMemoryKey=packed object start:QWORD; __end:QWORD; end; TvTiling=bitpacked record idx:0..31; //0..31 (5) alt:0..1; //1 end; TvImageKeyParams=bitpacked object itype :0..3; //2 TVkImageType 0..2 pow2pad :0..1; //1 invalid :0..1; //1 reserved :0..15; //4 tiling :TvTiling; samples :Byte; //TVkSampleCountFlagBits 1..4 (3) mipLevels :Byte; //(0..15) (4) width :Word; //(0..16383) height :Word; //(0..16383) depth :Word; //(0..8192) arrayLayers:Word; //(0..16383) pitch :Word; //(0..16383) pad_width :Word; pad_height :Word; function layerCount:Word; end; PvImageKey=^TvImageKey; TvImageKey=packed object Addr :Pointer; Addr2 :Pointer; cformat:TVkFormat; params :TvImageKeyParams; end; PvImageViewKey=^TvImageViewKey; TvImageViewKey=bitpacked object cformat :TVkFormat; vtype :0..127; //TVkImageViewType 0..6 invalid :0..1; fusage :Byte; dstSel :TvDstSel; //word base_level:Byte; //first mip level (0..15) last_level:Byte; //last mip level (0..15) base_array:Word; //first array index (0..16383) last_array:Word; //texture height (0..16383) minLod :TVkFloat; function arrayLayers:Word; function baseArrayLayer:Word; function layerCount:Word; end; TvImage=class(TvCustomImage) FExtent:TVkExtent3D; FUsage :TVkFlags; Fflags :TVkImageCreateFlags; Barrier:TvImageBarrier; Constructor Create(format:TVkFormat;extent:TVkExtent3D;usage:TVkFlags;flags:TVkImageCreateFlags;ext:Pointer=nil); function GetImageInfo:TVkImageCreateInfo; override; function GetViewInfo:TVkImageViewCreateInfo; virtual; abstract; function NewView:TvImageView; function NewViewF(Format:TVkFormat):TvImageView; procedure PushBarrier(cmd:TVkCommandBuffer; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags); end; TvHostImage1D=class(TvImage) function GetImageInfo:TVkImageCreateInfo; override; end; TvHostImage2D=class(TvImage) function GetImageInfo:TVkImageCreateInfo; override; end; TvDeviceImage1D=class(TvImage) function GetViewInfo:TVkImageViewCreateInfo; override; function GetImageInfo:TVkImageCreateInfo; override; end; TvDeviceImage2D=class(TvImage) function GetViewInfo:TVkImageViewCreateInfo; override; function GetImageInfo:TVkImageCreateInfo; override; end; TvFramebufferAttachmentShort=packed record cformat :TVkFormat; width :Word; height :Word; layerCount:Word; end; AvFramebufferAttach=array[0..8] of TVkFramebufferAttachmentImageInfo; AvFramebufferAShort=array[0..8] of TvFramebufferAttachmentShort; AvFramebufferImages=array[0..8] of TvImageView; AvImageViews =array[0..8] of TVkImageView; TvFramebuffer=class(TvRefsObject) FHandle:TVkFramebuffer; function IsImageless:Boolean; virtual; Destructor Destroy; override; end; PvFramebufferImagelessKey=^TvFramebufferImagelessKey; TvFramebufferImagelessKey=packed object FRenderPass :TvRenderPass; FWidth :Word; FHeight :Word; FLayers :Word; FImagesCount:Word; FImages :AvFramebufferAShort; Procedure SetRenderPass(r:TvRenderPass); Procedure SetSize(Size:TVkExtent2D); Procedure AddImageAt(Key:TvImageKey); Procedure Export(var F:AvFramebufferAttach); end; TvFramebufferImageless=class(TvFramebuffer) Key:TvFramebufferImagelessKey; function IsImageless:Boolean; override; function Compile:Boolean; end; PvFramebufferBindedKey=^TvFramebufferBindedKey; TvFramebufferBindedKey=packed object FRenderPass :TvRenderPass; FWidth :Word; FHeight :Word; FLayers :Word; FImagesCount:Word; FImages :AvFramebufferImages; Procedure SetRenderPass(r:TvRenderPass); Procedure SetSize(Size:TVkExtent2D); Procedure AddImageView(v:TvImageView); end; TvFramebufferBinded=class(TvFramebuffer) Key:TvFramebufferBindedKey; FAcquire:bitpacked array[0..8] of Boolean; function Compile:Boolean; Procedure AcquireImageViews; Procedure ReleaseImageViews; Destructor Destroy; override; end; Function GetAspectMaskByFormat(cformat:TVkFormat):DWORD; Function GetDepthStencilInitLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout; Function GetDepthStencilSendLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout; Function GetDepthStencilAccessAttachMask(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkAccessFlags; function GetColorSendLayout(IMAGE_USAGE:Byte):TVkImageLayout; Function GetColorAccessAttachMask(IMAGE_USAGE:Byte):TVkAccessFlags; Function getFormatSize(cformat:TVkFormat):Byte; //in bytes function IsTexelFormat(cformat:TVkFormat):Boolean; function IsDepthOrStencilFormat(cformat:TVkFormat):Boolean; Function IsDepthAndStencil (cformat:TVkFormat):Boolean; function GetDepthOnlyFormat (cformat:TVkFormat):TVkFormat; function GetStencilOnlyFormat (cformat:TVkFormat):TVkFormat; function GetDepthOnly (const key:TvImageKey):TvImageKey; function GetStencilOnly(const key:TvImageKey):TvImageKey; function vkGetFormatSupport(format:TVkFormat;tiling:TVkImageTiling;usage:TVkImageUsageFlags):Boolean; function vkFixFormatSupport(format:TVkFormat;tiling:TVkImageTiling;usage:TVkImageUsageFlags):TVkFormat; function GET_FORMATS_LEN(buf:PVkFormat):Byte; function GET_VK_IMAGE_MUTABLE(cformat:TVkFormat):PVkFormat; function GET_VK_FORMAT_STORAGE(cformat:TVkFormat):TVkFormat; function GET_VK_IMAGE_USAGE_DEFAULT (cformat:TVkFormat):TVkFlags; function GET_VK_IMAGE_USAGE_ATTACHMENT(cformat:TVkFormat):TVkFlags; function GET_VK_IMAGE_CREATE_DEFAULT (cformat:TVkFormat):TVkFlags; Function GetNormalizedParams(const key:TvImageKey):TvImageKeyParams; Function CompareNormalized(const a,b:TvImageKey):Integer; Function GetVkFormatStr(cformat:TVkFormat):RawByteString; implementation uses subr_backtrace; function TvImageKeyParams.layerCount:Word; begin if (TVkImageType(itype)=VK_IMAGE_TYPE_3D) then begin Result:=1; //3D texture array does not exist? end else begin Result:=arrayLayers; end; end; // function TvImageViewKey.arrayLayers:Word; begin Result:=last_array-base_array+1; end; function TvImageViewKey.baseArrayLayer:Word; begin case TVkImageViewType(vtype) of VK_IMAGE_VIEW_TYPE_3D: begin Result:=0; //3D texture array does not exist? end; VK_IMAGE_VIEW_TYPE_CUBE, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: begin if (arrayLayers mod 6)<>0 then begin //broken CUBE? Result:=0; end else begin Result:=base_array; end; end; else begin Result:=base_array; end; end; end; function TvImageViewKey.layerCount:Word; begin case TVkImageViewType(vtype) of VK_IMAGE_VIEW_TYPE_3D: begin Result:=1; //3D texture array does not exist? end; VK_IMAGE_VIEW_TYPE_CUBE, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: begin Result:=((arrayLayers+5) div 6)*6; //align up end; else begin Result:=arrayLayers; end; end; end; Function getFormatSize(cformat:TVkFormat):Byte; //in bytes begin Result:=0; Case cformat of VK_FORMAT_UNDEFINED :Result:=0; //pixel size VK_FORMAT_R8_UNORM , VK_FORMAT_R8_SNORM , VK_FORMAT_R8_USCALED , VK_FORMAT_R8_SSCALED , VK_FORMAT_R8_UINT , VK_FORMAT_R8_SINT , VK_FORMAT_R8_SRGB :Result:=1; VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT , VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT , VK_FORMAT_R4G4B4A4_UNORM_PACK16 , VK_FORMAT_B4G4R4A4_UNORM_PACK16 , VK_FORMAT_R5G6B5_UNORM_PACK16 , VK_FORMAT_B5G6R5_UNORM_PACK16 , VK_FORMAT_A1R5G5B5_UNORM_PACK16 , VK_FORMAT_R5G5B5A1_UNORM_PACK16 , VK_FORMAT_R8G8_UNORM , VK_FORMAT_R8G8_SNORM , VK_FORMAT_R8G8_USCALED , VK_FORMAT_R8G8_SSCALED , VK_FORMAT_R8G8_UINT , VK_FORMAT_R8G8_SINT , VK_FORMAT_R8G8_SRGB , VK_FORMAT_R16_UNORM , VK_FORMAT_R16_SNORM , VK_FORMAT_R16_USCALED , VK_FORMAT_R16_SSCALED , VK_FORMAT_R16_UINT , VK_FORMAT_R16_SINT , VK_FORMAT_R16_SFLOAT :Result:=2; VK_FORMAT_R8G8B8A8_UNORM , VK_FORMAT_R8G8B8A8_SNORM , VK_FORMAT_R8G8B8A8_USCALED , VK_FORMAT_R8G8B8A8_SSCALED , VK_FORMAT_R8G8B8A8_UINT , VK_FORMAT_R8G8B8A8_SINT , VK_FORMAT_R8G8B8A8_SRGB , VK_FORMAT_B8G8R8A8_UNORM , VK_FORMAT_B8G8R8A8_SNORM , VK_FORMAT_B8G8R8A8_USCALED , VK_FORMAT_B8G8R8A8_SSCALED , VK_FORMAT_B8G8R8A8_UINT , VK_FORMAT_B8G8R8A8_SINT , VK_FORMAT_B8G8R8A8_SRGB , VK_FORMAT_A8B8G8R8_UNORM_PACK32 , VK_FORMAT_A8B8G8R8_SNORM_PACK32 , VK_FORMAT_A8B8G8R8_USCALED_PACK32 , VK_FORMAT_A8B8G8R8_SSCALED_PACK32 , VK_FORMAT_A8B8G8R8_UINT_PACK32 , VK_FORMAT_A8B8G8R8_SINT_PACK32 , VK_FORMAT_A8B8G8R8_SRGB_PACK32 , VK_FORMAT_A2R10G10B10_UNORM_PACK32 , VK_FORMAT_A2R10G10B10_SNORM_PACK32 , VK_FORMAT_A2R10G10B10_USCALED_PACK32, VK_FORMAT_A2R10G10B10_SSCALED_PACK32, VK_FORMAT_A2R10G10B10_UINT_PACK32 , VK_FORMAT_A2R10G10B10_SINT_PACK32 , VK_FORMAT_A2B10G10R10_UNORM_PACK32 , VK_FORMAT_A2B10G10R10_SNORM_PACK32 , VK_FORMAT_A2B10G10R10_USCALED_PACK32, VK_FORMAT_A2B10G10R10_SSCALED_PACK32, VK_FORMAT_A2B10G10R10_UINT_PACK32 , VK_FORMAT_A2B10G10R10_SINT_PACK32 , VK_FORMAT_R16G16_UNORM , VK_FORMAT_R16G16_SNORM , VK_FORMAT_R16G16_USCALED , VK_FORMAT_R16G16_SSCALED , VK_FORMAT_R16G16_UINT , VK_FORMAT_R16G16_SINT , VK_FORMAT_R16G16_SFLOAT , VK_FORMAT_R32_UINT , VK_FORMAT_R32_SINT , VK_FORMAT_R32_SFLOAT , VK_FORMAT_B10G11R11_UFLOAT_PACK32 , VK_FORMAT_R10G11B11_UFLOAT_FAKE32 , VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 :Result:=4; VK_FORMAT_R16G16B16A16_UNORM , VK_FORMAT_R16G16B16A16_SNORM , VK_FORMAT_R16G16B16A16_USCALED , VK_FORMAT_R16G16B16A16_SSCALED , VK_FORMAT_R16G16B16A16_UINT , VK_FORMAT_R16G16B16A16_SINT , VK_FORMAT_R16G16B16A16_SFLOAT , VK_FORMAT_R32G32_UINT , VK_FORMAT_R32G32_SINT , VK_FORMAT_R32G32_SFLOAT :Result:=8; VK_FORMAT_R32G32B32_UINT , VK_FORMAT_R32G32B32_SINT , VK_FORMAT_R32G32B32_SFLOAT :Result:=12; VK_FORMAT_R32G32B32A32_UINT , VK_FORMAT_R32G32B32A32_SINT , VK_FORMAT_R32G32B32A32_SFLOAT :Result:=16; //stencil VK_FORMAT_S8_UINT :Result:=1; //depth VK_FORMAT_D16_UNORM :Result:=2; VK_FORMAT_X8_D24_UNORM_PACK32 :Result:=4; VK_FORMAT_D32_SFLOAT :Result:=4; //depth stencil VK_FORMAT_D16_UNORM_S8_UINT :Result:=3; VK_FORMAT_D24_UNORM_S8_UINT :Result:=4; VK_FORMAT_D32_SFLOAT_S8_UINT :Result:=5; //texel size VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK.. VK_FORMAT_BC4_SNORM_BLOCK :Result:=8; VK_FORMAT_BC2_UNORM_BLOCK.. VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC5_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK :Result:=16; else Assert(false,'getFormatSize:TODO:'+IntToStr(ord(cformat))); end; end; function IsTexelFormat(cformat:TVkFormat):Boolean; begin Case cformat of VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK: Result:=True; else Result:=False; end; end; function IsDepthOrStencilFormat(cformat:TVkFormat):Boolean; begin Case cformat of //stencil VK_FORMAT_S8_UINT, //depth VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT, //depth stencil VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT: Result:=True; else Result:=False; end; end; Function IsDepthAndStencil(cformat:TVkFormat):Boolean; begin Case cformat of VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT: Result:=True; else Result:=False; end; end; function GetDepthOnlyFormat(cformat:TVkFormat):TVkFormat; begin Case cformat of //depth VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT: Result:=cformat; //depth stencil VK_FORMAT_D16_UNORM_S8_UINT :Result:=VK_FORMAT_D16_UNORM; VK_FORMAT_D24_UNORM_S8_UINT :Result:=VK_FORMAT_X8_D24_UNORM_PACK32; VK_FORMAT_D32_SFLOAT_S8_UINT:Result:=VK_FORMAT_D32_SFLOAT; else Result:=VK_FORMAT_UNDEFINED; end; end; function GetStencilOnlyFormat(cformat:TVkFormat):TVkFormat; begin Case cformat of //stencil VK_FORMAT_S8_UINT, //depth stencil VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT: Result:=VK_FORMAT_S8_UINT; else Result:=VK_FORMAT_UNDEFINED; end; end; // function GetDepthOnly(const key:TvImageKey):TvImageKey; begin Result.Addr :=key.Addr; Result.Addr2 :=nil; Result.cformat:=GetDepthOnlyFormat(key.cformat); Result.params :=key.params; end; function GetStencilOnly(const key:TvImageKey):TvImageKey; begin Result.Addr :=key.Addr2; Result.Addr2 :=nil; Result.cformat:=GetStencilOnlyFormat(key.cformat); Result.params :=key.params; end; // function TvFramebuffer.IsImageless:Boolean; begin Result:=False; end; Destructor TvFramebuffer.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then begin vkDestroyFramebuffer(Device.FHandle,FHandle,nil); end; inherited; end; // Procedure TvFramebufferBindedKey.SetRenderPass(r:TvRenderPass); begin FRenderPass:=r; end; Procedure TvFramebufferBindedKey.SetSize(Size:TVkExtent2D); begin FWidth :=Size.width; FHeight:=Size.height; FLayers:=1; end; Procedure TvFramebufferBindedKey.AddImageView(v:TvImageView); begin Assert(v<>nil,'AddImageView'); if (FImagesCount>=Length(AvFramebufferImages)) then Exit; FImages[FImagesCount]:=v; Inc(FImagesCount); end; /// const MUTABLE_8:array[0..7] of TVkFormat=( VK_FORMAT_R8_UNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_R8_USCALED, VK_FORMAT_R8_SSCALED, VK_FORMAT_R8_UINT, VK_FORMAT_R8_SINT, VK_FORMAT_R8_SRGB, VK_FORMAT_UNDEFINED ); MUTABLE_16:array[0..18] of TVkFormat=( //VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, //VK1.3 //VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, //VK1.3 VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_USCALED, VK_FORMAT_R8G8_SSCALED, VK_FORMAT_R8G8_UINT, VK_FORMAT_R8G8_SINT, VK_FORMAT_R8G8_SRGB, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_SNORM, VK_FORMAT_R16_USCALED, VK_FORMAT_R16_SSCALED, VK_FORMAT_R16_UINT, VK_FORMAT_R16_SINT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_UNDEFINED ); MUTABLE_8888:array[0..44] of TVkFormat=( VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_USCALED, VK_FORMAT_R8G8B8A8_SSCALED, VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_SINT, VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SNORM, VK_FORMAT_B8G8R8A8_USCALED, VK_FORMAT_B8G8R8A8_SSCALED, VK_FORMAT_B8G8R8A8_UINT, VK_FORMAT_B8G8R8A8_SINT, VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_FORMAT_A8B8G8R8_SNORM_PACK32, VK_FORMAT_A8B8G8R8_USCALED_PACK32, VK_FORMAT_A8B8G8R8_SSCALED_PACK32, VK_FORMAT_A8B8G8R8_UINT_PACK32, VK_FORMAT_A8B8G8R8_SINT_PACK32, VK_FORMAT_A8B8G8R8_SRGB_PACK32, VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_FORMAT_A2R10G10B10_SNORM_PACK32, VK_FORMAT_A2R10G10B10_USCALED_PACK32, VK_FORMAT_A2R10G10B10_SSCALED_PACK32, VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_SINT_PACK32, VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2B10G10R10_SNORM_PACK32, VK_FORMAT_A2B10G10R10_USCALED_PACK32, VK_FORMAT_A2B10G10R10_SSCALED_PACK32, VK_FORMAT_A2B10G10R10_UINT_PACK32, VK_FORMAT_A2B10G10R10_SINT_PACK32, VK_FORMAT_R16G16_UNORM, VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_USCALED, VK_FORMAT_R16G16_SSCALED, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R32_UINT, VK_FORMAT_R32_SINT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_UNDEFINED ); MUTABLE_5999:array[0..1] of TVkFormat=( VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_FORMAT_UNDEFINED ); MUTABLE_3232:array[0..10] of TVkFormat=( VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_USCALED, VK_FORMAT_R16G16B16A16_SSCALED, VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_UNDEFINED ); MUTABLE_323232:array[0..3] of TVkFormat=( VK_FORMAT_R32G32B32_UINT, VK_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SFLOAT, VK_FORMAT_UNDEFINED ); MUTABLE_32323232:array[0..3] of TVkFormat=( VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_UNDEFINED ); MUTABLE_D16_UNORM:array[0..1] of TVkFormat=( VK_FORMAT_D16_UNORM, VK_FORMAT_UNDEFINED ); MUTABLE_X8_D24_UNORM:array[0..1] of TVkFormat=( VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_UNDEFINED ); MUTABLE_D32_SFLOAT:array[0..1] of TVkFormat=( VK_FORMAT_D32_SFLOAT, VK_FORMAT_UNDEFINED ); MUTABLE_S8_UINT:array[0..1] of TVkFormat=( VK_FORMAT_S8_UINT, VK_FORMAT_UNDEFINED ); MUTABLE_D16_UNORM_S8_UINT:array[0..1] of TVkFormat=( VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_UNDEFINED ); MUTABLE_D24_UNORM_S8_UINT:array[0..1] of TVkFormat=( VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_UNDEFINED ); MUTABLE_D32_SFLOAT_S8_UINT:array[0..1] of TVkFormat=( VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_UNDEFINED ); MUTABLE_BC1_RGB:array[0..2] of TVkFormat=( VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_BC1_RGB_SRGB_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC1_RGBA:array[0..2] of TVkFormat=( VK_FORMAT_BC1_RGBA_UNORM_BLOCK, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC2:array[0..2] of TVkFormat=( VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC2_SRGB_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC3:array[0..2] of TVkFormat=( VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC4:array[0..2] of TVkFormat=( VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC4_SNORM_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC5:array[0..2] of TVkFormat=( VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC5_SNORM_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC6:array[0..2] of TVkFormat=( VK_FORMAT_BC6H_UFLOAT_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_UNDEFINED ); MUTABLE_BC7:array[0..2] of TVkFormat=( VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_BC7_SRGB_BLOCK, VK_FORMAT_UNDEFINED ); function GET_FORMATS_LEN(buf:PVkFormat):Byte; begin Result:=0; if (buf=nil) then Exit; while (buf[0]<>VK_FORMAT_UNDEFINED) do begin Inc(Result); Inc(buf); end; end; function GET_VK_IMAGE_MUTABLE(cformat:TVkFormat):PVkFormat; begin Result:=nil; case cformat of VK_FORMAT_R8_UNORM :Result:=@MUTABLE_8; VK_FORMAT_R8_SNORM :Result:=@MUTABLE_8; VK_FORMAT_R8_USCALED:Result:=@MUTABLE_8; VK_FORMAT_R8_SSCALED:Result:=@MUTABLE_8; VK_FORMAT_R8_UINT :Result:=@MUTABLE_8; VK_FORMAT_R8_SINT :Result:=@MUTABLE_8; VK_FORMAT_R8_SRGB :Result:=@MUTABLE_8; VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT:Result:=@MUTABLE_16; VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:Result:=@MUTABLE_16; VK_FORMAT_R4G4B4A4_UNORM_PACK16 :Result:=@MUTABLE_16; VK_FORMAT_B4G4R4A4_UNORM_PACK16 :Result:=@MUTABLE_16; VK_FORMAT_R5G6B5_UNORM_PACK16 :Result:=@MUTABLE_16; VK_FORMAT_B5G6R5_UNORM_PACK16 :Result:=@MUTABLE_16; VK_FORMAT_R8G8_UNORM :Result:=@MUTABLE_16; VK_FORMAT_R8G8_SNORM :Result:=@MUTABLE_16; VK_FORMAT_R8G8_USCALED :Result:=@MUTABLE_16; VK_FORMAT_R8G8_SSCALED :Result:=@MUTABLE_16; VK_FORMAT_R8G8_UINT :Result:=@MUTABLE_16; VK_FORMAT_R8G8_SINT :Result:=@MUTABLE_16; VK_FORMAT_R8G8_SRGB :Result:=@MUTABLE_16; VK_FORMAT_R16_UNORM :Result:=@MUTABLE_16; VK_FORMAT_R16_SNORM :Result:=@MUTABLE_16; VK_FORMAT_R16_USCALED :Result:=@MUTABLE_16; VK_FORMAT_R16_SSCALED :Result:=@MUTABLE_16; VK_FORMAT_R16_UINT :Result:=@MUTABLE_16; VK_FORMAT_R16_SINT :Result:=@MUTABLE_16; VK_FORMAT_R16_SFLOAT :Result:=@MUTABLE_16; VK_FORMAT_R8G8B8A8_UNORM :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_SNORM :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_USCALED :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_SSCALED :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_UINT :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_SINT :Result:=@MUTABLE_8888; VK_FORMAT_R8G8B8A8_SRGB :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_UNORM :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_SNORM :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_USCALED :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_SSCALED :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_UINT :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_SINT :Result:=@MUTABLE_8888; VK_FORMAT_B8G8R8A8_SRGB :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_UNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_SNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_USCALED_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_SSCALED_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_UINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_SINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A8B8G8R8_SRGB_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_UNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_SNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_USCALED_PACK32:Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_SSCALED_PACK32:Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_UINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2R10G10B10_SINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_UNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_SNORM_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_USCALED_PACK32:Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_SSCALED_PACK32:Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_UINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_A2B10G10R10_SINT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_UNORM :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_SNORM :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_USCALED :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_SSCALED :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_UINT :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_SINT :Result:=@MUTABLE_8888; VK_FORMAT_R16G16_SFLOAT :Result:=@MUTABLE_8888; VK_FORMAT_R32_UINT :Result:=@MUTABLE_8888; VK_FORMAT_R32_SINT :Result:=@MUTABLE_8888; VK_FORMAT_R32_SFLOAT :Result:=@MUTABLE_8888; VK_FORMAT_B10G11R11_UFLOAT_PACK32 :Result:=@MUTABLE_8888; VK_FORMAT_R10G11B11_UFLOAT_FAKE32 :Result:=@MUTABLE_8888; VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 :Result:=@MUTABLE_5999; VK_FORMAT_R16G16B16A16_UNORM :Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_SNORM :Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_USCALED:Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_SSCALED:Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_UINT :Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_SINT :Result:=@MUTABLE_3232; VK_FORMAT_R16G16B16A16_SFLOAT :Result:=@MUTABLE_3232; VK_FORMAT_R32G32_UINT :Result:=@MUTABLE_3232; VK_FORMAT_R32G32_SINT :Result:=@MUTABLE_3232; VK_FORMAT_R32G32_SFLOAT :Result:=@MUTABLE_3232; VK_FORMAT_R32G32B32_UINT :Result:=@MUTABLE_323232; VK_FORMAT_R32G32B32_SINT :Result:=@MUTABLE_323232; VK_FORMAT_R32G32B32_SFLOAT :Result:=@MUTABLE_323232; VK_FORMAT_R32G32B32A32_UINT :Result:=@MUTABLE_32323232; VK_FORMAT_R32G32B32A32_SINT :Result:=@MUTABLE_32323232; VK_FORMAT_R32G32B32A32_SFLOAT :Result:=@MUTABLE_32323232; VK_FORMAT_D16_UNORM:Result:=@MUTABLE_D16_UNORM; VK_FORMAT_X8_D24_UNORM_PACK32:Result:=@MUTABLE_X8_D24_UNORM; VK_FORMAT_D32_SFLOAT:Result:=@MUTABLE_D32_SFLOAT; VK_FORMAT_S8_UINT:Result:=@MUTABLE_S8_UINT; VK_FORMAT_D16_UNORM_S8_UINT:Result:=@MUTABLE_D16_UNORM_S8_UINT; VK_FORMAT_D24_UNORM_S8_UINT:Result:=@MUTABLE_D24_UNORM_S8_UINT; VK_FORMAT_D32_SFLOAT_S8_UINT:Result:=@MUTABLE_D32_SFLOAT_S8_UINT; VK_FORMAT_BC1_RGB_UNORM_BLOCK:Result:=@MUTABLE_BC1_RGB; VK_FORMAT_BC1_RGB_SRGB_BLOCK :Result:=@MUTABLE_BC1_RGB; VK_FORMAT_BC1_RGBA_UNORM_BLOCK:Result:=@MUTABLE_BC1_RGBA; VK_FORMAT_BC1_RGBA_SRGB_BLOCK :Result:=@MUTABLE_BC1_RGBA; VK_FORMAT_BC2_UNORM_BLOCK:Result:=@MUTABLE_BC2; VK_FORMAT_BC2_SRGB_BLOCK :Result:=@MUTABLE_BC2; VK_FORMAT_BC3_UNORM_BLOCK:Result:=@MUTABLE_BC3; VK_FORMAT_BC3_SRGB_BLOCK :Result:=@MUTABLE_BC3; VK_FORMAT_BC4_UNORM_BLOCK:Result:=@MUTABLE_BC4; VK_FORMAT_BC4_SNORM_BLOCK:Result:=@MUTABLE_BC4; VK_FORMAT_BC5_UNORM_BLOCK:Result:=@MUTABLE_BC5; VK_FORMAT_BC5_SNORM_BLOCK:Result:=@MUTABLE_BC5; VK_FORMAT_BC6H_UFLOAT_BLOCK:Result:=@MUTABLE_BC6; VK_FORMAT_BC6H_SFLOAT_BLOCK:Result:=@MUTABLE_BC6; VK_FORMAT_BC7_UNORM_BLOCK:Result:=@MUTABLE_BC7; VK_FORMAT_BC7_SRGB_BLOCK :Result:=@MUTABLE_BC7; else; end; end; function GET_VK_FORMAT_STORAGE(cformat:TVkFormat):TVkFormat; begin Result:=cformat; case cformat of VK_FORMAT_R8_SNORM, VK_FORMAT_R8_USCALED, VK_FORMAT_R8_SSCALED, VK_FORMAT_R8_SINT:Result:=VK_FORMAT_R8_UINT; VK_FORMAT_R8_SRGB:Result:=VK_FORMAT_R8_UNORM; VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_R8G8_SNORM, VK_FORMAT_R8G8_USCALED, VK_FORMAT_R8G8_SSCALED, VK_FORMAT_R8G8_SINT:Result:=VK_FORMAT_R8G8_UINT; VK_FORMAT_R8G8_SRGB:Result:=VK_FORMAT_R8G8_UNORM; VK_FORMAT_R16_SNORM, VK_FORMAT_R16_USCALED, VK_FORMAT_R16_SSCALED, VK_FORMAT_R16_SINT, VK_FORMAT_R16_SFLOAT:Result:=VK_FORMAT_R16_UINT; VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_USCALED, VK_FORMAT_R8G8B8A8_SSCALED, VK_FORMAT_R8G8B8A8_SINT:Result:=VK_FORMAT_R8G8B8A8_UINT; VK_FORMAT_R8G8B8A8_SRGB:Result:=VK_FORMAT_R8G8B8A8_UNORM; VK_FORMAT_B8G8R8A8_SNORM, VK_FORMAT_B8G8R8A8_USCALED, VK_FORMAT_B8G8R8A8_SSCALED, VK_FORMAT_B8G8R8A8_UINT, VK_FORMAT_B8G8R8A8_SINT:Result:=VK_FORMAT_R8G8B8A8_UINT; VK_FORMAT_B8G8R8A8_SRGB:Result:=VK_FORMAT_B8G8R8A8_UNORM; VK_FORMAT_A8B8G8R8_SNORM_PACK32, VK_FORMAT_A8B8G8R8_USCALED_PACK32, VK_FORMAT_A8B8G8R8_SSCALED_PACK32, VK_FORMAT_A8B8G8R8_SINT_PACK32:Result:=VK_FORMAT_A8B8G8R8_UINT_PACK32; VK_FORMAT_A8B8G8R8_SRGB_PACK32:Result:=VK_FORMAT_A8B8G8R8_UNORM_PACK32; VK_FORMAT_A2R10G10B10_SNORM_PACK32, VK_FORMAT_A2R10G10B10_USCALED_PACK32, VK_FORMAT_A2R10G10B10_SSCALED_PACK32, VK_FORMAT_A2R10G10B10_UINT_PACK32, VK_FORMAT_A2R10G10B10_SINT_PACK32:Result:=VK_FORMAT_A2R10G10B10_UNORM_PACK32; VK_FORMAT_A2B10G10R10_SNORM_PACK32, VK_FORMAT_A2B10G10R10_USCALED_PACK32, VK_FORMAT_A2B10G10R10_SSCALED_PACK32, VK_FORMAT_A2B10G10R10_UINT_PACK32, VK_FORMAT_A2B10G10R10_SINT_PACK32:Result:=VK_FORMAT_A2B10G10R10_UNORM_PACK32; VK_FORMAT_R16G16_SNORM, VK_FORMAT_R16G16_USCALED, VK_FORMAT_R16G16_SSCALED, VK_FORMAT_R16G16_UINT, VK_FORMAT_R16G16_SINT, VK_FORMAT_R16G16_SFLOAT:Result:=VK_FORMAT_R16G16_UNORM; VK_FORMAT_R32_SINT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_B10G11R11_UFLOAT_PACK32:Result:=VK_FORMAT_R32_UINT; VK_FORMAT_R10G11B11_UFLOAT_FAKE32:Result:=VK_FORMAT_R32_UINT; VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:Result:=VK_FORMAT_R32_UINT; VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_USCALED, VK_FORMAT_R16G16B16A16_SSCALED, VK_FORMAT_R16G16B16A16_SINT, VK_FORMAT_R16G16B16A16_SFLOAT:Result:=VK_FORMAT_R16G16B16A16_UINT; VK_FORMAT_R32G32_SINT, VK_FORMAT_R32G32_SFLOAT:Result:=VK_FORMAT_R32G32_UINT; VK_FORMAT_R32G32B32_SINT, VK_FORMAT_R32G32B32_SFLOAT:Result:=VK_FORMAT_R32G32B32_UINT; VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SFLOAT:Result:=VK_FORMAT_R32G32B32A32_UINT; VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK.. VK_FORMAT_BC4_SNORM_BLOCK:Result:=VK_FORMAT_R32G32_UINT; VK_FORMAT_BC2_UNORM_BLOCK.. VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC5_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK:Result:=VK_FORMAT_R32G32B32A32_UINT; else; end; end; const VK_IMAGE_USAGE_= ord(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) or ord(VK_IMAGE_USAGE_TRANSFER_DST_BIT) or ord(VK_IMAGE_USAGE_SAMPLED_BIT); VK_IMAGE_USAGE_DEFAULT= VK_IMAGE_USAGE_ or ord(VK_IMAGE_USAGE_STORAGE_BIT); VK_IMAGE_USAGE_DEFAULT_COLOR= VK_IMAGE_USAGE_ or ord(VK_IMAGE_USAGE_STORAGE_BIT) or ord(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); VK_IMAGE_USAGE_DEFAULT_DEPTH= VK_IMAGE_USAGE_ or ord(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); function GET_VK_IMAGE_USAGE_DEFAULT(cformat:TVkFormat):TVkFlags; begin Case cformat of VK_FORMAT_R4G4_UNORM_PACK8.. VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A8B8G8R8_UNORM_PACK32.. VK_FORMAT_A2B10G10R10_SINT_PACK32, VK_FORMAT_R10G11B11_UFLOAT_FAKE32, //VK_FORMAT_B10G11R11_UFLOAT_PACK32.. VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: Result:=VK_IMAGE_USAGE_DEFAULT; VK_FORMAT_D16_UNORM.. VK_FORMAT_D32_SFLOAT_S8_UINT: Result:=VK_IMAGE_USAGE_DEFAULT_DEPTH; VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK: Result:=VK_IMAGE_USAGE_DEFAULT; else Result:=VK_IMAGE_USAGE_DEFAULT_COLOR; end; end; function GET_VK_IMAGE_USAGE_ATTACHMENT(cformat:TVkFormat):TVkFlags; begin Case cformat of VK_FORMAT_R4G4_UNORM_PACK8.. VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A8B8G8R8_UNORM_PACK32.. VK_FORMAT_A2B10G10R10_SINT_PACK32, VK_FORMAT_R10G11B11_UFLOAT_FAKE32, VK_FORMAT_B10G11R11_UFLOAT_PACK32.. VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: Result:=ord(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); VK_FORMAT_D16_UNORM.. VK_FORMAT_D32_SFLOAT_S8_UINT: Result:=ord(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK: Result:=0; //prohibited else Result:=ord(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); end; end; function GET_VK_IMAGE_CREATE_DEFAULT(cformat:TVkFormat):TVkFlags; begin Case cformat of VK_FORMAT_BC1_RGB_UNORM_BLOCK.. VK_FORMAT_BC7_SRGB_BLOCK: Result:=ord(VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) or ord(VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) or ord(VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT); else Result:=ord(VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) or ord(VK_IMAGE_CREATE_EXTENDED_USAGE_BIT); end; end; procedure FixToNormalizedTiling(var tiling:TvTiling); inline; begin case tiling.idx of 9,13,27:tiling.idx:=5; 14,28:tiling.idx:=10; 16,29:tiling.idx:=11; 17,30:tiling.idx:=12; else; end; end; Function GetNormalizedParams(const key:TvImageKey):TvImageKeyParams; begin Result:=key.params; if IsTexelFormat(key.cformat) then begin Result.width :=(Result.width +3) shr 2; Result.height:=(Result.height+3) shr 2; end; FixToNormalizedTiling(Result.tiling); Result.pitch :=0; Result.pad_width :=0; Result.pad_height:=0; end; Function CompareNormalized(const a,b:TvImageKey):Integer; begin //1 Addr Result:=Integer(a.Addr>b.Addr)-Integer(a.Addr0) then Exit; //1 Stencil Result:=Integer(a.Addr2>b.Addr2)-Integer(a.Addr20) then Exit; //2 cformat Result:=getFormatSize(a.cformat)-getFormatSize(b.cformat); if (Result<>0) then Exit; //3 params Result:=CompareByte(GetNormalizedParams(a),GetNormalizedParams(b),SizeOf(TvImageKeyParams)); end; Function GetVkFormatStr(cformat:TVkFormat):RawByteString; begin case cformat of VK_FORMAT_R10G11B11_UFLOAT_FAKE32:Result:='R10G11B11_UFLOAT_FAKE32'; {$I VK_FORMAT_STR.inc} else Result:='0x'+HexStr(ord(cformat),8); end; end; // Procedure TvFramebufferImagelessKey.SetRenderPass(r:TvRenderPass); begin FRenderPass:=r; end; Procedure TvFramebufferImagelessKey.SetSize(Size:TVkExtent2D); begin FWidth :=Size.width; FHeight:=Size.height; FLayers:=1; end; Procedure TvFramebufferImagelessKey.AddImageAt(Key:TvImageKey); begin if (FImagesCount>=Length(FImages)) then Exit; if (Key.params.width>FWidth) then begin FWidth:=Key.params.width; end; if (Key.params.height>FHeight) then begin FHeight:=Key.params.height; end; if (Key.params.layerCount>FLayers) then begin FLayers:=Key.params.layerCount; end; with FImages[FImagesCount] do begin cformat :=Key.cformat; width :=Key.params.width; height :=Key.params.height; layerCount:=key.params.layerCount; end; Inc(FImagesCount); end; Procedure TvFramebufferImagelessKey.Export(var F:AvFramebufferAttach); var cformat:TVkFormat; MUTABLE:PVkFormat; i:Word; begin if (FImagesCount<>0) then For i:=0 to FImagesCount-1 do begin cformat:=FImages[i].cformat; MUTABLE:=GET_VK_IMAGE_MUTABLE(cformat); with F[i] do begin sType :=VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO; pNext :=nil; flags :=GET_VK_IMAGE_CREATE_DEFAULT (cformat); usage :=GET_VK_IMAGE_USAGE_ATTACHMENT(cformat); width :=FImages[i].width; height :=FImages[i].height; layerCount :=FImages[i].layerCount; viewFormatCount:=GET_FORMATS_LEN(MUTABLE); pViewFormats :=MUTABLE; end; end; end; /// function TvFramebufferImageless.IsImageless:Boolean; begin Result:=True; end; function TvFramebufferImageless.Compile:Boolean; var r:TVkResult; info:TVkFramebufferCreateInfo; imgs:TVkFramebufferAttachmentsCreateInfo; fatt:AvFramebufferAttach; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) then Exit(True); if (Key.FRenderPass=nil) then Exit; if (Key.FRenderPass.FHandle=VK_NULL_HANDLE) then Exit; if (Key.FImagesCount=0) then Exit; if (Key.FWidth=0) or (Key.FHeight=0) then Exit; info:=Default(TVkFramebufferCreateInfo); info.sType :=VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; info.renderPass :=Key.FRenderPass.FHandle; info.attachmentCount:=Key.FImagesCount; info.width :=Key.FWidth; info.height :=Key.FHeight; info.layers :=Key.FLayers; info.flags :=ord(VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT); info.pAttachments :=nil; Key.Export(fatt); imgs:=Default(TVkFramebufferAttachmentsCreateInfo); imgs.sType:=VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO; imgs.attachmentImageInfoCount:=Key.FImagesCount; imgs.pAttachmentImageInfos :=@fatt; info.pNext:=@imgs; r:=vkCreateFramebuffer(Device.FHandle,@info,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateFramebuffer'); end; Result:=(r=VK_SUCCESS); end; /// Procedure TvFramebufferBinded.AcquireImageViews; var i:Word; begin if (Key.FImagesCount<>0) then For i:=0 to Key.FImagesCount-1 do if (Key.FImages[i]<>nil) then if (not FAcquire[i]) then begin Key.FImages[i].Acquire(Self); FAcquire[i]:=True; end; end; Procedure TvFramebufferBinded.ReleaseImageViews; var i:Word; begin if (Key.FImagesCount<>0) then For i:=0 to Key.FImagesCount-1 do if (Key.FImages[i]<>nil) then if (FAcquire[i]) then begin Key.FImages[i].Release(Self); FAcquire[i]:=False; end; end; function TvFramebufferBinded.Compile:Boolean; var i:TVkUInt32; r:TVkResult; info:TVkFramebufferCreateInfo; FImageViews:AvImageViews; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) then Exit(True); if (Key.FRenderPass=nil) then Exit; if (Key.FRenderPass.FHandle=VK_NULL_HANDLE) then Exit; if (Key.FImagesCount=0) then Exit; if (Key.FWidth=0) or (Key.FHeight=0) then Exit; AcquireImageViews; info:=Default(TVkFramebufferCreateInfo); info.sType :=VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; info.renderPass :=Key.FRenderPass.FHandle; info.attachmentCount:=Key.FImagesCount; info.width :=Key.FWidth; info.height :=Key.FHeight; info.layers :=Key.FLayers; For i:=0 to Key.FImagesCount-1 do begin if (Key.FImages[i]<>nil) then begin FImageViews[i]:=Key.FImages[i].FHandle; end; end; info.pAttachments:=@FImageViews; r:=vkCreateFramebuffer(Device.FHandle,@info,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateFramebuffer'); end; Result:=(r=VK_SUCCESS); end; Destructor TvFramebufferBinded.Destroy; begin ReleaseImageViews; inherited; end; Constructor TvSwapChain.Create(Surface:TvSurface;mode:Integer;imageUsage:TVkImageUsageFlags); var queueFamilyIndices:array[0..1] of TVkUInt32; cinfo:TVkSwapchainCreateInfoKHR; r:TVkResult; i,count:TVkUInt32; cimg:TVkImageViewCreateInfo; FImage:array of TVkImage; FView:TVkImageView; begin FSurface:=Surface; Case mode of 1,2,3:; else mode:=1; end; FSize:=Surface.GetSize; if (FSize.width=0) or (FSize.height=0) then Exit; cinfo:=Default(TVkSwapchainCreateInfoKHR); cinfo.sType :=VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; cinfo.surface :=FSurface.FHandle; cinfo.minImageCount :=2; cinfo.imageFormat :=FSurface.Fformat.format; cinfo.imageColorSpace :=FSurface.Fformat.colorSpace; cinfo.imageExtent :=FSize; cinfo.imageArrayLayers:=1; cinfo.imageUsage :=imageUsage or ord(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); if (VulkanApp.FGFamily<>Surface.FPFamily) then begin queueFamilyIndices[0]:=VulkanApp.FGFamily; queueFamilyIndices[1]:=Surface.FPFamily; cinfo.imageSharingMode :=VK_SHARING_MODE_CONCURRENT; cinfo.queueFamilyIndexCount :=2; cinfo.pQueueFamilyIndices :=@queueFamilyIndices; end else begin cinfo.imageSharingMode :=VK_SHARING_MODE_EXCLUSIVE; cinfo.queueFamilyIndexCount :=0; cinfo.pQueueFamilyIndices :=nil; end; cinfo.preTransform :=VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; cinfo.compositeAlpha:=VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; cinfo.presentMode :=Surface.FModes[mode-1]; cinfo.clipped :=VK_TRUE; cinfo.oldSwapchain :=VK_NULL_HANDLE; r:=vkCreateSwapchainKHR(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateSwapchainKHR:',r); Exit; end; count:=1; Case mode of 1,2:count:=2; 3:count:=3; end; SetLength(FImage,count); SetLength(FImages,count); r:=vkGetSwapchainImagesKHR(Device.FHandle,FHandle,@count,@FImage[0]); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkGetSwapchainImagesKHR:',r); Exit; end; cimg:=Default(TVkImageViewCreateInfo); cimg.sType :=VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; cimg.viewType :=VK_IMAGE_VIEW_TYPE_2D; cimg.format :=Surface.Fformat.format; cimg.components.r:=VK_COMPONENT_SWIZZLE_IDENTITY; cimg.components.g:=VK_COMPONENT_SWIZZLE_IDENTITY; cimg.components.b:=VK_COMPONENT_SWIZZLE_IDENTITY; cimg.components.a:=VK_COMPONENT_SWIZZLE_IDENTITY; cimg.subresourceRange.aspectMask :=TVkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT); cimg.subresourceRange.baseMipLevel :=0; cimg.subresourceRange.levelCount :=1; cimg.subresourceRange.baseArrayLayer:=0; cimg.subresourceRange.layerCount :=1; For i:=0 to count-1 do begin cimg.image:=FImage[i]; FView:=VK_NULL_HANDLE; r:=vkCreateImageView(Device.FHandle,@cimg,nil,@FView); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateImageView:',r); Exit; end; FImages[i]:=TvSwapChainImage.Create; FImages[i].FHandle:=FImage[i]; FImages[i].FView :=FView; FImages[i].Barrier.Init; end; end; Destructor TvSwapChain.Destroy; var i:Integer; begin For i:=0 to High(FImages) do begin if (FImages[i].FView<>VK_NULL_HANDLE) then begin vkDestroyImageView(Device.FHandle,FImages[i].FView,nil); end; FImages[i].Free; end; if (FHandle<>VK_NULL_HANDLE) then begin vkDestroySwapchainKHR(Device.FHandle,FHandle,nil); end; end; function TvCustomImage.is_invalid:Boolean; begin Result:=(FHandle=VK_NULL_HANDLE); end; procedure TvCustomImage.FreeHandle; var F:TVkImage; begin F:=System.InterlockedExchange64(FHandle,VK_NULL_HANDLE); if (F<>VK_NULL_HANDLE) then begin vkDestroyImage(Device.FHandle,F,nil); end; end; Destructor TvCustomImage.Destroy; begin FreeHandle; // UnBindMem(True); // inherited; end; function TvCustomImage.GetRequirements:TVkMemoryRequirements; begin Result:=Default(TVkMemoryRequirements); vkGetImageMemoryRequirements(Device.FHandle,FHandle,@Result); end; function TvCustomImage.GetDedicatedAllocation:Boolean; var info:TVkImageMemoryRequirementsInfo2; rmem:TVkMemoryRequirements2; rded:TVkMemoryDedicatedRequirements; begin Result:=false; if Pointer(vkGetImageMemoryRequirements2)=nil then Exit; info:=Default(TVkImageMemoryRequirementsInfo2); info.sType:=VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; info.image:=FHandle; rmem:=Default(TVkMemoryRequirements2); rmem.sType:=VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; rded:=Default(TVkMemoryDedicatedRequirements); rded.sType:=VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; rmem.pNext:=@rded; vkGetImageMemoryRequirements2(Device.FHandle,@info,@rmem); Result:=(rded.requiresDedicatedAllocation<>VK_FALSE) or (rded.prefersDedicatedAllocation <>VK_FALSE); end; function TvCustomImage.Compile(ext:Pointer):Boolean; var cinfo:TVkImageCreateInfo; clist:TVkImageFormatListCreateInfo; MUTABLE:PVkFormat; r:TVkResult; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) then Exit(True); cinfo:=GetImageInfo; cinfo.format:=vkFixFormatSupport(cinfo.format,cinfo.tiling,cinfo.usage); //save real format FFormat:=cinfo.format; cinfo.pNext:=@clist; MUTABLE:=GET_VK_IMAGE_MUTABLE(cinfo.format); clist:=Default(TVkImageFormatListCreateInfo); clist.sType:=VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO; clist.viewFormatCount:=GET_FORMATS_LEN(MUTABLE); clist.pViewFormats :=MUTABLE; clist.pNext:=ext; r:=vkCreateImage(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateImage:',r); Exit; end; FSize:=GetRequirements.size; Result:=True; end; function TvCustomImage.BindMem(P:TvPointer):TVkResult; var B:TvPointer; begin B:=P.Acquire; if (B.FMemory<>nil) then //try Acquire begin // Result:=vkBindImageMemory(Device.FHandle,FHandle,B.FMemory.FHandle,B.FOffset); // if (Result=VK_SUCCESS) then begin B.FMemory.AddDependence(@Self.OnReleaseMem); FBind:=B; end; // B.Release; //release Acquire end else begin Result:=VK_ERROR_UNKNOWN; end; if (Result<>VK_SUCCESS) then begin Writeln(stderr,'Error BindMem:',Result,' To:0x',HexStr(FHandle,16)); vMemory.MemManager._print_devs; vMemory.MemManager._print_host; end; end; procedure TvCustomImage.UnBindMem(do_free:Boolean); var B:TvPointer; H:Integer; begin B.FMemory:=TvDeviceMemory(System.InterlockedExchange(Pointer(FBind.FMemory),nil)); B.FOffset:=FBind.FOffset; H:=System.InterlockedExchangeAdd(FHold,0); if (B.FMemory<>nil) then begin if do_free then begin B.FMemory.DelDependence(@Self.OnReleaseMem); while (H<>0) do begin B.Drop; Dec(H); end; MemManager.FreeMemory(B); end; end; end; function TvCustomImage.Hold(Sender:TObject):Boolean; begin Result:=FBind.Hold; if Result then begin Result:=inherited; if not Result then begin FBind.Drop; end; end; end; function TvCustomImage.Drop(Sender:TObject):Boolean; begin Result:=FBind.Drop; if Result then begin Result:=inherited; end; end; function TvCustomImage.OnReleaseMem(Sender:TObject):Boolean; begin FreeHandle; // UnBindMem(False); // Result:=True; end; procedure TvCustomImage.SetObjectName(const name:RawByteString); begin FName:=name; DebugReport.SetObjectName(VK_OBJECT_TYPE_IMAGE,FHandle,PChar(name)); end; /// procedure _test_and_set_to(var new:TVkFlags; test:TVkFlags; val_test:TVkImageUsageFlagBits; val_sets:TVkFormatFeatureFlagBits); begin if ((test and ord(val_test))<>0) then begin new:=new or ord(val_sets); end; end; function vkGetFormatSupport(format:TVkFormat;tiling:TVkImageTiling;usage:TVkImageUsageFlags):Boolean; var prop:TVkFormatProperties; test:TVkFormatFeatureFlags; begin Result:=False; prop:=Default(TVkFormatProperties); vkGetPhysicalDeviceFormatProperties( VulkanApp.FPhysicalDevice, format, @prop); test:=0; _test_and_set_to(test,usage,VK_IMAGE_USAGE_TRANSFER_SRC_BIT ,VK_FORMAT_FEATURE_TRANSFER_SRC_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_TRANSFER_DST_BIT ,VK_FORMAT_FEATURE_TRANSFER_DST_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_SAMPLED_BIT ,VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_STORAGE_BIT ,VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ,VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ,VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); _test_and_set_to(test,usage,VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT ,VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT); Case tiling of VK_IMAGE_TILING_OPTIMAL: begin Result:=(prop.optimalTilingFeatures and test)=test; end; VK_IMAGE_TILING_LINEAR: begin Result:=(prop.linearTilingFeatures and test)=test; end; else; end; end; //D16_UNORM_S8_UINT -> D24_UNORM_S8_UINT -> D32_SFLOAT_S8_UINT //D16_UNORM -> X8_D24_UNORM_PACK32 -> D32_SFLOAT function vkFixFormatSupport(format:TVkFormat;tiling:TVkImageTiling;usage:TVkImageUsageFlags):TVkFormat; begin Result:=format; repeat Case Result of VK_FORMAT_D16_UNORM_S8_UINT: begin if vkGetFormatSupport(Result,tiling,usage) then Break; Result:=VK_FORMAT_D24_UNORM_S8_UINT; end; VK_FORMAT_D24_UNORM_S8_UINT: begin if vkGetFormatSupport(Result,tiling,usage) then Break; Result:=VK_FORMAT_D32_SFLOAT_S8_UINT; end; VK_FORMAT_D16_UNORM: begin if vkGetFormatSupport(Result,tiling,usage) then Break; Result:=VK_FORMAT_X8_D24_UNORM_PACK32; end; VK_FORMAT_X8_D24_UNORM_PACK32: begin if vkGetFormatSupport(Result,tiling,usage) then Break; Result:=VK_FORMAT_D32_SFLOAT; end; else Break; end; until false; end; Constructor TvImage.Create(format:TVkFormat;extent:TVkExtent3D;usage:TVkFlags;flags:TVkImageCreateFlags;ext:Pointer=nil); begin FFormat:=format; FExtent:=extent; FUsage:=usage; Fflags:=flags; Barrier.Init; Compile(ext); end; function TvImage.GetImageInfo:TVkImageCreateInfo; begin Result:=Default(TVkImageCreateInfo); Result.format:=FFormat; Result.extent:=FExtent; Result.usage :=FUsage; Result.flags :=Fflags; end; function TvImage.NewView:TvImageView; begin Result:=NewViewF(FFormat); end; function TvImage.NewViewF(Format:TVkFormat):TvImageView; var cinfo:TVkImageViewCreateInfo; FImg:TVkImageView; r:TVkResult; begin Result:=nil; cinfo:=GetViewInfo; cinfo.image :=FHandle; cinfo.format:=Format; FImg:=VK_NULL_HANDLE; r:=vkCreateImageView(Device.FHandle,@cinfo,nil,@FImg); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateImageView:',r); Exit; end; Result:=TvImageView.Create; Result.FHandle:=FImg; end; procedure TvSwapChainImage.PushBarrier(cmd:TVkCommandBuffer; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags); begin if (cmd=VK_NULL_HANDLE) then Exit; Barrier.Push(cmd, nil, FHandle, range, dstAccessMask, newImageLayout, dstStageMask); end; procedure TvImage.PushBarrier(cmd:TVkCommandBuffer; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags); begin if (cmd=VK_NULL_HANDLE) then Exit; Barrier.Push(cmd, nil, FHandle, range, dstAccessMask, newImageLayout, dstStageMask); end; procedure TvImageView.SetObjectName(const name:RawByteString); begin FName:=name; DebugReport.SetObjectName(VK_OBJECT_TYPE_IMAGE_VIEW,FHandle,PChar(name)); end; Destructor TvImageView.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then begin vkDestroyImageView(Device.FHandle,FHandle,nil); end; end; function TvHostImage1D.GetImageInfo:TVkImageCreateInfo; begin Result:=inherited; Result.sType :=VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; Result.imageType :=VK_IMAGE_TYPE_1D; Result.arrayLayers :=1; Result.mipLevels :=1; Result.initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED; Result.samples :=VK_SAMPLE_COUNT_1_BIT; Result.tiling :=VK_IMAGE_TILING_LINEAR; end; function TvHostImage2D.GetImageInfo:TVkImageCreateInfo; begin Result:=inherited; Result.sType :=VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; Result.imageType :=VK_IMAGE_TYPE_2D; Result.arrayLayers :=1; Result.mipLevels :=1; Result.initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED; Result.samples :=VK_SAMPLE_COUNT_1_BIT; Result.tiling :=VK_IMAGE_TILING_LINEAR; end; // function TvDeviceImage1D.GetImageInfo:TVkImageCreateInfo; begin Result:=inherited; Result.sType :=VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; Result.imageType :=VK_IMAGE_TYPE_1D; Result.arrayLayers :=1; Result.mipLevels :=1; Result.initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED; Result.samples :=VK_SAMPLE_COUNT_1_BIT; Result.tiling :=VK_IMAGE_TILING_OPTIMAL; end; function TvDeviceImage1D.GetViewInfo:TVkImageViewCreateInfo; begin Result:=Default(TVkImageViewCreateInfo); Result.sType :=VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; Result.viewType :=VK_IMAGE_VIEW_TYPE_1D; Result.format :=FFormat; Result.components.r:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.g:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.b:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.a:=VK_COMPONENT_SWIZZLE_IDENTITY; Case FFormat of VK_FORMAT_S8_UINT: Result.subresourceRange.aspectMask :=ord(VK_IMAGE_ASPECT_STENCIL_BIT); VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT: Result.subresourceRange.aspectMask :=ord(VK_IMAGE_ASPECT_DEPTH_BIT); VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT: Result.subresourceRange.aspectMask :=ord(VK_IMAGE_ASPECT_DEPTH_BIT) or ord(VK_IMAGE_ASPECT_STENCIL_BIT); else Result.subresourceRange.aspectMask :=ord(VK_IMAGE_ASPECT_COLOR_BIT); end; Result.subresourceRange.baseMipLevel :=0; Result.subresourceRange.levelCount :=1; Result.subresourceRange.baseArrayLayer:=0; Result.subresourceRange.layerCount :=1; end; // function TvDeviceImage2D.GetImageInfo:TVkImageCreateInfo; begin Result:=inherited; Result.sType :=VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; Result.imageType :=VK_IMAGE_TYPE_2D; Result.arrayLayers :=1; Result.mipLevels :=1; Result.initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED; Result.samples :=VK_SAMPLE_COUNT_1_BIT; Result.tiling :=VK_IMAGE_TILING_OPTIMAL; end; function TvDeviceImage2D.GetViewInfo:TVkImageViewCreateInfo; begin Result:=Default(TVkImageViewCreateInfo); Result.sType :=VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; Result.viewType :=VK_IMAGE_VIEW_TYPE_2D; Result.format :=FFormat; Result.components.r:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.g:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.b:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.components.a:=VK_COMPONENT_SWIZZLE_IDENTITY; Result.subresourceRange.aspectMask :=GetAspectMaskByFormat(FFormat); Result.subresourceRange.baseMipLevel :=0; Result.subresourceRange.levelCount :=1; Result.subresourceRange.baseArrayLayer:=0; Result.subresourceRange.layerCount :=1; end; Function GetAspectMaskByFormat(cformat:TVkFormat):DWORD; begin Case cformat of VK_FORMAT_S8_UINT: Result :=ord(VK_IMAGE_ASPECT_STENCIL_BIT); VK_FORMAT_D16_UNORM, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT: Result :=ord(VK_IMAGE_ASPECT_DEPTH_BIT); VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT: Result :=ord(VK_IMAGE_ASPECT_DEPTH_BIT) or ord(VK_IMAGE_ASPECT_STENCIL_BIT); else Result :=ord(VK_IMAGE_ASPECT_COLOR_BIT); end; end; { WW VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL RR VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL RW VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL WR VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL W_ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL R_ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL _W VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL _R VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL } Function GetDepthStencilInitLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout; var IMAGE_USAGE:Byte; begin IMAGE_USAGE:=(DEPTH_USAGE or STENCIL_USAGE); // if ((IMAGE_USAGE and TM_READ)=0) then begin Result:=VK_IMAGE_LAYOUT_UNDEFINED; end else if ((IMAGE_USAGE and (TM_WRITE or TM_CLEAR))<>0) then begin Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; end else begin Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; end; end; Function GetDepthStencilSendLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout; var IMAGE_USAGE:Byte; begin IMAGE_USAGE:=(DEPTH_USAGE or STENCIL_USAGE); // if ((IMAGE_USAGE and (TM_WRITE or TM_CLEAR))<>0) then begin Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; end else begin Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; end; end; Function GetDepthStencilAccessAttachMask(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkAccessFlags; var IMAGE_USAGE:Byte; begin IMAGE_USAGE:=(DEPTH_USAGE or STENCIL_USAGE); // Result:=(ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) *ord((IMAGE_USAGE and TM_READ )<>0) ) or (ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)*ord((IMAGE_USAGE and (TM_WRITE or TM_CLEAR))<>0) ); end; function GetColorSendLayout(IMAGE_USAGE:Byte):TVkImageLayout; begin if ((IMAGE_USAGE and TM_MIXED)<>0) then begin Result:=VK_IMAGE_LAYOUT_GENERAL; end else begin Result:=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; end; end; Function GetColorAccessAttachMask(IMAGE_USAGE:Byte):TVkAccessFlags; begin Result:=(ord(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) *ord((IMAGE_USAGE and TM_READ )<>0) ) or (ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)*ord((IMAGE_USAGE and (TM_WRITE or TM_CLEAR))<>0) ); end; Procedure TvImageBarrier.Init({_image:TVkImage;_sub:TVkImageSubresourceRange}); begin //image :=_image; //range :=_sub; AccessMask:=ord(VK_ACCESS_NONE_KHR); ImgLayout :=VK_IMAGE_LAYOUT_UNDEFINED; StageMask :=ord(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); end; function IsRead(dstAccessMask:TVkAccessFlags):Boolean; inline; begin Result:=dstAccessMask and ( ord(VK_ACCESS_INDIRECT_COMMAND_READ_BIT) or ord(VK_ACCESS_INDEX_READ_BIT) or ord(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) or ord(VK_ACCESS_UNIFORM_READ_BIT) or ord(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) or ord(VK_ACCESS_SHADER_READ_BIT) or ord(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) or ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) or ord(VK_ACCESS_TRANSFER_READ_BIT) or ord(VK_ACCESS_HOST_READ_BIT) or ord(VK_ACCESS_MEMORY_READ_BIT) )<>0; end; function IsWrite(dstAccessMask:TVkAccessFlags):Boolean; inline; begin Result:=dstAccessMask and ( ord(VK_ACCESS_SHADER_WRITE_BIT) or ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) or ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) or ord(VK_ACCESS_TRANSFER_WRITE_BIT) or ord(VK_ACCESS_HOST_WRITE_BIT) or ord(VK_ACCESS_MEMORY_WRITE_BIT) )<>0; end; const ALL_GRAPHICS_STAGE:TVkPipelineStageFlags=( ord(VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT) or ord(VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT) or ord(VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT) or ord(VK_PIPELINE_STAGE_VERTEX_INPUT_BIT) or ord(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT) or ord(VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT) or ord(VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT) or ord(VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT) or ord(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) or ord(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) or ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) or ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) or ord(VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT) or ord(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT) or ord(VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) or ord(VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT) ); function ChangeStage(curr,next:TVkPipelineStageFlags):Boolean; begin if ((curr and ord(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT))<>0) then begin curr:=(curr and (not ord(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT))) or ALL_GRAPHICS_STAGE; end; if ((next and ord(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT))<>0) then begin next:=(next and (not ord(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT))) or ALL_GRAPHICS_STAGE; end; Result:=((curr and next)<>next); end; procedure _test_and_set_to(var str :RawByteString; test :TVkAccessFlags; bit_test:TVkAccessFlagBits; bit_str :RawByteString); begin if ((test and ord(bit_test))<>0) then begin if (str='') then begin str:=bit_str; end else begin str:=str + '|' + bit_str; end; end; end; function GetAccessMaskStr(AccessMask:TVkAccessFlags):RawByteString; begin if (AccessMask=0) then Exit('NONE'); Result:=''; _test_and_set_to(Result,AccessMask,VK_ACCESS_INDIRECT_COMMAND_READ_BIT ,'ICR'); _test_and_set_to(Result,AccessMask,VK_ACCESS_INDEX_READ_BIT ,'IR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT ,'VAR'); _test_and_set_to(Result,AccessMask,VK_ACCESS_UNIFORM_READ_BIT ,'UR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_INPUT_ATTACHMENT_READ_BIT ,'IAR'); _test_and_set_to(Result,AccessMask,VK_ACCESS_SHADER_READ_BIT ,'SR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_SHADER_WRITE_BIT ,'SW' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_COLOR_ATTACHMENT_READ_BIT ,'CAR'); _test_and_set_to(Result,AccessMask,VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ,'CAW'); _test_and_set_to(Result,AccessMask,VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT ,'DAR'); _test_and_set_to(Result,AccessMask,VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,'DAW'); _test_and_set_to(Result,AccessMask,VK_ACCESS_TRANSFER_READ_BIT ,'TR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_TRANSFER_WRITE_BIT ,'TW' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_HOST_READ_BIT ,'HR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_HOST_WRITE_BIT ,'HW' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_MEMORY_READ_BIT ,'MR' ); _test_and_set_to(Result,AccessMask,VK_ACCESS_MEMORY_WRITE_BIT ,'MW' ); end; function TvImageBarrier.Push(cmd:TVkCommandBuffer; cb:t_push_cb; image:TVkImage; range:TVkImageSubresourceRange; dstAccessMask:TVkAccessFlags; newImageLayout:TVkImageLayout; dstStageMask:TVkPipelineStageFlags):Boolean; var info:TVkImageMemoryBarrier; begin Result:=False; //Writeln('Push:0x',HexStr(image,16),' ',HexStr(dstAccessMask,8),' ',(newImageLayout),' ',HexStr(dstStageMask,8)); //RAW //WAR //WAW if (AccessMask<>dstAccessMask ) or (ImgLayout <>newImageLayout) or (ImgLayout =VK_IMAGE_LAYOUT_GENERAL) or (newImageLayout=VK_IMAGE_LAYOUT_GENERAL) or ChangeStage(StageMask,dstStageMask) or (IsRead (AccessMask) and IsWrite(dstAccessMask)) or (IsWrite(AccessMask) and IsRead (dstAccessMask)) or (IsWrite(AccessMask) and IsWrite(dstAccessMask)) then begin Result:=True; if (cb<>nil) then begin cmd:=cb(); end; if (cmd=0) then Exit; if (image=VK_NULL_HANDLE) then begin print_backtrace(StdErr,Get_pc_addr,get_frame,0); end; Writeln('Barrier:'#13#10, ' image =0x',HexStr(image,16),#13#10, ' srcAccessMask=',GetAccessMaskStr(AccessMask),#13#10, ' dstAccessMask=',GetAccessMaskStr(dstAccessMask),#13#10, ' oldLayout =' ,ImgLayout,#13#10, ' newLayout =' ,newImageLayout ); info:=Default(TVkImageMemoryBarrier); info.sType :=VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; info.srcAccessMask :=AccessMask; info.dstAccessMask :=dstAccessMask; info.oldLayout :=ImgLayout; info.newLayout :=newImageLayout; info.image :=image; info.subresourceRange:=range; vkCmdPipelineBarrier(cmd, StageMask, dstStageMask, ord(VK_DEPENDENCY_BY_REGION_BIT), 0, nil, 0, nil, 1, @info); AccessMask:=dstAccessMask; ImgLayout :=newImageLayout; StageMask :=dstStageMask; end; end; end.