mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-23 14:29:53 +00:00
795 lines
21 KiB
ObjectPascal
795 lines
21 KiB
ObjectPascal
unit vImage;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
vulkan,
|
|
vDevice,
|
|
vPipeline,
|
|
vMemory;
|
|
|
|
type
|
|
PvImageBarrier=^TvImageBarrier;
|
|
TvImageBarrier=object
|
|
//image:TVkImage;
|
|
//range:TVkImageSubresourceRange;
|
|
//
|
|
AccessMask:TVkAccessFlags;
|
|
ImgLayout:TVkImageLayout;
|
|
StageMask:TVkPipelineStageFlags;
|
|
Procedure Init({_image:TVkImage;_sub:TVkImageSubresourceRange});
|
|
function Push(cmd:TVkCommandBuffer;
|
|
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
|
|
FHandle:TVkImageView;
|
|
FRefs:ptruint;
|
|
Procedure Acquire;
|
|
Procedure Release;
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
TvCustomImage=class
|
|
FHandle:TVkImage;
|
|
Destructor Destroy; override;
|
|
function GetImageInfo:TVkImageCreateInfo; virtual; abstract;
|
|
function GetRequirements:TVkMemoryRequirements;
|
|
function GetDedicatedAllocation:Boolean;
|
|
function BindMem(P:TvPointer):TVkResult;
|
|
function Compile(ext:Pointer):Boolean;
|
|
end;
|
|
|
|
const
|
|
//useage image
|
|
TM_READ =1;
|
|
TM_WRITE=2;
|
|
TM_CLEAR=4;
|
|
|
|
type
|
|
TvExtent3D=packed record
|
|
width:Word; //(0..16383)
|
|
height:Word; //(0..16383)
|
|
depth:Word; //(0..8192)
|
|
end;
|
|
|
|
TvDstSel=bitpacked record
|
|
r,g,b,a:0..15; //(0..6)
|
|
end;
|
|
|
|
PvImageKey=^TvImageKey;
|
|
TvImageKey=packed object
|
|
Addr:Pointer;
|
|
cformat:TVkFormat;
|
|
params:packed record
|
|
itype:Byte; //TVkImageType 0..2
|
|
tiling_idx:Byte; //0..31
|
|
extend:TvExtent3D;
|
|
samples:Byte; //TVkSampleCountFlagBits 1..4
|
|
mipLevels:Byte; //(0..15)
|
|
arrayLayers:Word; //(0..16383)
|
|
end;
|
|
end;
|
|
|
|
PvImageViewKey=^TvImageViewKey;
|
|
TvImageViewKey=packed record
|
|
cformat:TVkFormat;
|
|
vtype:Word; //TVkImageViewType 0..6
|
|
dstSel:TvDstSel;
|
|
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)
|
|
end;
|
|
|
|
TvImage=class(TvCustomImage)
|
|
FFormat:TVkFormat;
|
|
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;
|
|
|
|
AvFramebufferImages=array[0..8] of TvImageView;
|
|
AvImageViews=array[0..8] of TVkImageView;
|
|
|
|
TvFramebuffer=class
|
|
FHandle:TVkFramebuffer;
|
|
FEdit,FCompile:ptruint;
|
|
FRenderPass:TvRenderPass;
|
|
FSize:TVkExtent2D;
|
|
FImages:AvFramebufferImages;
|
|
FImagesCount:ptruint;
|
|
Procedure SetRenderPass(r:TvRenderPass);
|
|
Procedure SetSize(Size:TVkExtent2D);
|
|
Procedure AddImageView(v:TvImageView);
|
|
Procedure FreeImageViews;
|
|
function IsEdit:Boolean;
|
|
function Compile:Boolean;
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
Function GetAspectMaskByFormat(cformat:TVkFormat):DWORD;
|
|
|
|
Function getFormatSize(cformat:TVkFormat):Byte; //in bytes
|
|
function IsTexelFormat(cformat:TVkFormat):Boolean;
|
|
|
|
implementation
|
|
|
|
Function getFormatSize(cformat:TVkFormat):Byte; //in bytes
|
|
begin
|
|
Result:=0;
|
|
Case cformat of
|
|
//pixel size
|
|
VK_FORMAT_R8G8B8A8_SRGB :Result:=4;
|
|
VK_FORMAT_R8G8B8A8_UNORM :Result:=4;
|
|
VK_FORMAT_R8G8_UNORM :Result:=2;
|
|
VK_FORMAT_R8_UNORM :Result:=1;
|
|
VK_FORMAT_R8_UINT :Result:=1;
|
|
VK_FORMAT_R8_SRGB :Result:=1;
|
|
VK_FORMAT_R5G6B5_UNORM_PACK16 :Result:=2;
|
|
VK_FORMAT_R4G4B4A4_UNORM_PACK16:Result:=2;
|
|
VK_FORMAT_R32_SFLOAT :Result:=4;
|
|
|
|
//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,'TODO');
|
|
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;
|
|
|
|
Procedure TvFramebuffer.SetRenderPass(r:TvRenderPass);
|
|
begin
|
|
if (r=FRenderPass) then Exit;
|
|
FRenderPass:=r;
|
|
Inc(FEdit);
|
|
end;
|
|
|
|
Procedure TvFramebuffer.SetSize(Size:TVkExtent2D);
|
|
begin
|
|
if CompareByte(Size,FSize,SizeOf(TVkExtent2D))=0 then Exit;
|
|
FSize:=Size;
|
|
Inc(FEdit);
|
|
end;
|
|
|
|
Procedure TvFramebuffer.AddImageView(v:TvImageView);
|
|
begin
|
|
if (v=nil) then Exit;
|
|
if (FImagesCount>=Length(AvFramebufferImages)) then Exit;
|
|
FImages[FImagesCount]:=v;
|
|
Inc(FImagesCount);
|
|
v.Acquire;
|
|
Inc(FEdit);
|
|
end;
|
|
|
|
Procedure TvFramebuffer.FreeImageViews;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if (FImagesCount<>0) then
|
|
For i:=0 to FImagesCount-1 do
|
|
if (FImages[i]<>nil) then
|
|
begin
|
|
FImages[i].Release;
|
|
FImages[i]:=nil;
|
|
end;
|
|
FImagesCount:=0;
|
|
|
|
//It:=FImages.cbegin;
|
|
//if (It.Item<>nil) then
|
|
//repeat
|
|
// TvImageView(It.Item^).Release;
|
|
//until not It.Next;
|
|
//FImages.Free;
|
|
Inc(FEdit);
|
|
end;
|
|
|
|
function TvFramebuffer.IsEdit:Boolean;
|
|
begin
|
|
Result:=(FEdit<>FCompile);
|
|
end;
|
|
|
|
function TvFramebuffer.Compile:Boolean;
|
|
var
|
|
i:TVkUInt32;
|
|
r:TVkResult;
|
|
info:TVkFramebufferCreateInfo;
|
|
FImageViews:AvImageViews;
|
|
begin
|
|
Result:=False;
|
|
if (not IsEdit) then Exit(true);
|
|
if (FRenderPass=nil) then Exit;
|
|
if (FRenderPass.FHandle=VK_NULL_HANDLE) then Exit;
|
|
if (FSize.width=0) or (FSize.height=0) then Exit;
|
|
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyFramebuffer(Device.FHandle,FHandle,nil);
|
|
FHandle:=VK_NULL_HANDLE;
|
|
end;
|
|
|
|
info:=Default(TVkFramebufferCreateInfo);
|
|
info.sType :=VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
info.renderPass :=FRenderPass.FHandle;
|
|
info.attachmentCount:=FImagesCount;
|
|
info.width :=FSize.width;
|
|
info.height:=FSize.height;
|
|
info.layers:=1;
|
|
|
|
if (info.attachmentCount<>0) then
|
|
begin
|
|
FImageViews:=Default(AvImageViews);
|
|
|
|
For i:=0 to FImagesCount-1 do
|
|
if (FImages[i]<>nil) then
|
|
begin
|
|
FImageViews[i]:=FImages[i].FHandle;
|
|
end;
|
|
|
|
info.pAttachments:=@FImageViews;
|
|
end;
|
|
|
|
if (info.attachmentCount=0) then
|
|
begin
|
|
if (info.pAttachments<>nil) then
|
|
FreeMem(info.pAttachments);
|
|
info.flags:=ord(VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT);
|
|
info.pAttachments:=nil;
|
|
end;
|
|
|
|
r:=vkCreateFramebuffer(Device.FHandle,@info,nil,@FHandle);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkCreateFramebuffer');
|
|
end;
|
|
|
|
Result:=(r=VK_SUCCESS);
|
|
end;
|
|
|
|
Destructor TvFramebuffer.Destroy;
|
|
begin
|
|
FreeImageViews;
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
vkDestroyFramebuffer(Device.FHandle,FHandle,nil);
|
|
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
|
|
vkDestroyImageView(Device.FHandle,FImages[i].FView,nil);
|
|
FImages[i].Free;
|
|
end;
|
|
vkDestroySwapchainKHR(Device.FHandle,FHandle,nil);
|
|
end;
|
|
|
|
Destructor TvCustomImage.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
vkDestroyImage(Device.FHandle,FHandle,nil);
|
|
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.BindMem(P:TvPointer):TVkResult;
|
|
begin
|
|
Result:=vkBindImageMemory(Device.FHandle,FHandle,P.FHandle,P.FOffset);
|
|
end;
|
|
|
|
function TvCustomImage.Compile(ext:Pointer):Boolean;
|
|
var
|
|
cinfo:TVkImageCreateInfo;
|
|
r:TVkResult;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyImage(Device.FHandle,FHandle,nil);
|
|
FHandle:=VK_NULL_HANDLE;
|
|
end;
|
|
|
|
cinfo:=GetImageInfo;
|
|
cinfo.pNext:=ext;
|
|
r:=vkCreateImage(Device.FHandle,@cinfo,nil,@FHandle);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkCreateImage:',r);
|
|
Exit;
|
|
end;
|
|
Result:=True;
|
|
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,
|
|
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,
|
|
FHandle,
|
|
range,
|
|
dstAccessMask,
|
|
newImageLayout,
|
|
dstStageMask);
|
|
end;
|
|
|
|
Procedure TvImageView.Acquire;
|
|
begin
|
|
System.InterlockedIncrement(Pointer(FRefs));
|
|
end;
|
|
|
|
Procedure TvImageView.Release;
|
|
begin
|
|
if System.InterlockedDecrement(Pointer(FRefs))=nil then
|
|
begin
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
Destructor TvImageView.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
vkDestroyImageView(Device.FHandle,FHandle,nil);
|
|
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;
|
|
|
|
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 TvImageBarrier.Push(cmd:TVkCommandBuffer;
|
|
image:TVkImage;
|
|
range:TVkImageSubresourceRange;
|
|
dstAccessMask:TVkAccessFlags;
|
|
newImageLayout:TVkImageLayout;
|
|
dstStageMask:TVkPipelineStageFlags):Boolean;
|
|
var
|
|
info:TVkImageMemoryBarrier;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (AccessMask<>dstAccessMask) or
|
|
(ImgLayout <>newImageLayout) or
|
|
(StageMask <>dstStageMask) then
|
|
begin
|
|
Result:=True;
|
|
|
|
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,
|
|
0,
|
|
0, nil,
|
|
0, nil,
|
|
1, @info);
|
|
|
|
AccessMask:=dstAccessMask;
|
|
ImgLayout :=newImageLayout;
|
|
StageMask :=dstStageMask;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|