fpPS4/vulkan/vImageTiling.pas
red-prig fb40aa7070 +
2022-06-26 23:50:32 +03:00

426 lines
12 KiB
ObjectPascal

unit vImageTiling;
{$mode objfpc}{$H+}
interface
uses
SysUtils,
RWLock,
g23tree,
ps4_tiling,
Vulkan,
vDevice,
vMemory,
vBuffer,
vImage,
vHostBufferManager,
vCmdBuffer;
Procedure LoadFromBuffer(cmd:TvCustomCmdBuffer;image:TObject); //TvImage2
implementation
uses
vImageManager;
Function getFormatSize(cformat:TVkFormat):Byte;
begin
Result:=0;
Case cformat of
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:=4;
VK_FORMAT_R5G6B5_UNORM_PACK16:Result:=2;
else
Assert(false,'TODO');
end;
end;
{
Procedure _Load_Linear(cmd:TvCustomCmdBuffer;image:TvImage2);
var
buf:TvHostBuffer;
BufferImageCopy:TVkBufferImageCopy;
size:Ptruint;
begin
size:=image.key.params.extend.width*
image.key.params.extend.height*
image.key.params.extend.depth*
getFormatSize(image.key.cformat);
image.PushBarrier(cmd,
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
buf:=FetchHostBuffer(cmd,
image.key.Addr,
size,
ord(VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
vkBufferMemoryBarrier(cmd.cmdbuf,
buf.FHandle,
ord(VK_ACCESS_SHADER_WRITE_BIT),
ord(VK_ACCESS_MEMORY_READ_BIT),
buf.Foffset,size,
ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)
);
BufferImageCopy:=Default(TVkBufferImageCopy);
BufferImageCopy.bufferOffset:=buf.Foffset;
BufferImageCopy.bufferRowLength:=0;
BufferImageCopy.bufferImageHeight:=0;
BufferImageCopy.imageSubresource:=image.GetSubresLayer;
BufferImageCopy.imageExtent.Create(image.key.params.extend.width,
image.key.params.extend.height,
image.key.params.extend.depth);
Case image.key.cformat of
VK_FORMAT_D16_UNORM_S8_UINT,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT_S8_UINT:
BufferImageCopy.imageSubresource.aspectMask:=ord(VK_IMAGE_ASPECT_DEPTH_BIT);
else;
end;
//image.data_usage:=image.data_usage and (not TM_READ);
vkCmdCopyBufferToImage(cmd.cmdbuf,
buf.FHandle,
image.FHandle,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
@BufferImageCopy);
end;
}
Procedure _Load_Linear(cmd:TvCustomCmdBuffer;image:TvImage2);
var
buf:TvHostImage2;
ImageCopy:TVkImageCopy;
begin
buf:=image.FetchHostImage(cmd,ord(VK_IMAGE_USAGE_TRANSFER_SRC_BIT) or
ord(VK_IMAGE_USAGE_TRANSFER_DST_BIT));
Assert(buf<>nil,'FetchHostImage');
image.PushBarrier(cmd,
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
buf.PushBarrier(cmd,
ord(VK_ACCESS_TRANSFER_READ_BIT),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
ImageCopy:=Default(TVkImageCopy);
ImageCopy.srcSubresource:=image.GetSubresLayer;
ImageCopy.dstSubresource:=image.GetSubresLayer;
ImageCopy.extent.Create(image.key.params.extend.width,
image.key.params.extend.height,
image.key.params.extend.depth);
Case image.key.cformat of
VK_FORMAT_D16_UNORM_S8_UINT,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT_S8_UINT:
begin
ImageCopy.srcSubresource.aspectMask:=ord(VK_IMAGE_ASPECT_DEPTH_BIT);
ImageCopy.dstSubresource.aspectMask:=ord(VK_IMAGE_ASPECT_DEPTH_BIT);
end
else;
end;
vkCmdCopyImage(cmd.cmdbuf,
buf.FHandle,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image.FHandle,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,@ImageCopy);
end;
type
TvTempBuffer=class(TvBuffer)
Fhost:TvPointer;
procedure Release(Sender:TObject);
end;
procedure TvTempBuffer.Release(Sender:TObject);
begin
MemManager.Free(Fhost);
Free;
end;
Procedure _Copy_Linear(cmd:TvCustomCmdBuffer;buf:TvTempBuffer;image:TvImage2);
var
BufferImageCopy:TVkBufferImageCopy;
size:Ptruint;
begin
cmd.AddDependence(@buf.Release);
size:=image.key.params.extend.width*
image.key.params.extend.height*
image.key.params.extend.depth*
getFormatSize(image.key.cformat);
image.PushBarrier(cmd,
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
vkBufferMemoryBarrier(cmd.cmdbuf,
buf.FHandle,
ord(VK_ACCESS_SHADER_WRITE_BIT),
ord(VK_ACCESS_MEMORY_READ_BIT),
0,size,
ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)
);
BufferImageCopy:=Default(TVkBufferImageCopy);
BufferImageCopy.bufferOffset:=0;
BufferImageCopy.bufferRowLength:=0;
BufferImageCopy.bufferImageHeight:=0;
BufferImageCopy.imageSubresource:=image.GetSubresLayer;
BufferImageCopy.imageExtent.Create(image.key.params.extend.width,
image.key.params.extend.height,
image.key.params.extend.depth);
Case image.key.cformat of
VK_FORMAT_D16_UNORM_S8_UINT,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT_S8_UINT:
BufferImageCopy.imageSubresource.aspectMask:=ord(VK_IMAGE_ASPECT_DEPTH_BIT);
else;
end;
vkCmdCopyBufferToImage(cmd.cmdbuf,
buf.FHandle,
image.FHandle,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
@BufferImageCopy);
end;
type
TTGAHeader=packed record
idlength :Byte;
colourmaptype :Byte;
datatypecode :Byte;
colourmaporigin:Word;
colourmaplength:Word;
colourmapdepth :Byte;
x_origin :Word;
y_origin :Word;
width :Word;
height :Word;
bitsperpixel :Byte;
imagedescriptor:Byte;
end;
Procedure _Load_Thin_1dThin(cmd:TvCustomCmdBuffer;image:TvImage2);
var
buf:TvTempBuffer;
//tp:TilingParameters;
tiler:Tiler1d;
//mtm:Byte;
size,i,x,y:QWORD;
m_bitsPerElement:Word;
//m_macroTileWidth :DWORD;
//m_macroTileHeight:DWORD;
pData,pSrc,pDst:Pointer;
F:THandle;
Header:TTGAHeader;
begin
//tp:=Default(TilingParameters);
//mtm:=$FF; //2 kMacroTileMode_1x1_16
//bankWidth=1 bankHeight=1 macroTileAspect=2 numBanks=16 altBankHeight=2 altNumBanks= 8 altMacroTileAspect=1
//computeSurfaceMacroTileMode(@mtm,13,32,1);
//tp.m_tileMode:=image.key.params.tiling_idx;
//tp.m_minGpuMode:=0; //PS4 NEO
//
//tp.m_linearWidth :=image.key.params.extend.width;
//tp.m_linearHeight :=image.key.params.extend.height;
//tp.m_linearDepth :=image.key.params.extend.depth;
//tp.m_numFragmentsPerPixel:=32;
//tp.m_baseTiledPitch :=0;
//
//tp.m_mipLevel :=0;
//tp.m_arraySlice :=0;
////tp.m_surfaceFlags :SurfaceFlags;
//tp.m_bitsPerFragment :=32;
//tp.m_isBlockCompressed :=False;
//tp.m_tileSwizzleMask :=0;
//
//tiler:=Default(Tiler2d);
//tiler.init(tp);
Case image.key.cformat of
VK_FORMAT_BC1_RGB_UNORM_BLOCK,
VK_FORMAT_BC1_RGB_SRGB_BLOCK,
VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
VK_FORMAT_BC3_UNORM_BLOCK,
VK_FORMAT_BC3_SRGB_BLOCK:
begin
_Load_Linear(cmd,image);
Exit;
end;
else
end;
tiler:=Texture2d_32;
m_bitsPerElement:=getFormatSize(image.key.cformat)*8;
tiler.m_bitsPerElement:=m_bitsPerElement;
tiler.m_linearWidth :=image.key.params.extend.width;
tiler.m_linearHeight:=image.key.params.extend.height;
tiler.m_linearDepth :=image.key.params.extend.depth;
tiler.m_linearSizeBytes:=tiler.m_linearWidth*tiler.m_linearHeight*tiler.m_linearDepth*(m_bitsPerElement div 8);
tiler.m_tileBytes := (kMicroTileWidth * kMicroTileHeight * tiler.m_tileThickness * m_bitsPerElement + 7) div 8;
Case m_bitsPerElement of
32:begin
tiler.m_paddedWidth :=((tiler.m_linearWidth +7) div 8)*8;
tiler.m_paddedHeight:=((tiler.m_linearHeight+7) div 8)*8;
end;
8:begin
tiler.m_paddedWidth :=((tiler.m_linearWidth +31) div 32)*32;
tiler.m_paddedHeight:=((tiler.m_linearHeight+7) div 8)*8;
end;
else
Assert(false);
end;
tiler.m_paddedDepth :=tiler.m_linearDepth;
tiler.m_tiledSizeBytes:=tiler.m_paddedWidth*tiler.m_paddedHeight*tiler.m_paddedDepth*(m_bitsPerElement div 8);
tiler.m_tilesPerRow:=tiler.m_paddedWidth div kMicroTileWidth;
tiler.m_tilesPerSlice:= tiler.m_tilesPerRow * (tiler.m_paddedHeight div kMicroTileHeight);
///buf^.PITCH:=(width+127) div 128;
///buf^.SIZE :=buf^.PITCH*128*((height+63) div 64)*64*4;
//m_tilesPerRow = m_paddedWidth / kMicroTileWidth;
//m_tilesPerSlice = std::max(m_tilesPerRow * (m_paddedHeight / kMicroTileHeight), 1U);
size:=image.key.params.extend.width*
image.key.params.extend.height*(m_bitsPerElement div 8);
buf:=TvTempBuffer.Create(size,ord(VK_BUFFER_USAGE_TRANSFER_SRC_BIT),nil);
buf.Fhost:=MemManager.Alloc(buf.GetRequirements,ord(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
buf.BindMem(buf.Fhost);
pData:=nil;
vkMapMemory(Device.FHandle,
buf.Fhost.FHandle,
buf.Fhost.FOffset,
size,
0,
@pData);
//pData:=AllocMem(size);
Assert(image.key.params.extend.depth=1);
For y:=0 to image.key.params.extend.height-1 do
For x:=0 to image.key.params.extend.width-1 do
begin
i:=0;
tiler.getTiledElementBitOffset(i,x,y,0);
i:=i div 8;
pSrc:=@PByte(image.key.Addr)[i];
pDst:=@PByte(pData)[(y*image.key.params.extend.width+x)*(m_bitsPerElement div 8)];
Move(pSrc^,pDst^,(m_bitsPerElement div 8));
//i:=i div 4;
//pData[y*image.key.params.extend.width+x]:={Random($FFFFFFFF);}PDWORD(image.key.Addr)[i];
end;
//Move(pData^,image.key.Addr^,size);
//FreeMem(pData);
Case m_bitsPerElement of
8:begin
//image.data_usage:=image.data_usage and (not TM_READ);
//Header:=Default(TTGAHeader);
//
//Header.datatypecode :=3;
//
//Header.width :=image.key.params.extend.width;
//Header.height :=image.key.params.extend.height;
//Header.bitsperpixel :=8;
//Header.imagedescriptor:=32;
//
//F:=FileCreate('texture.tga');
//FileWrite(F,Header,SizeOf(TTGAHeader));
//FileWrite(F,pData^,size);
//FileClose(F);
end;
end;
//image.data_usage:=image.data_usage and (not TM_READ);
vkUnmapMemory(Device.FHandle,buf.Fhost.FHandle);
_Copy_Linear(cmd,buf,image);
//_Load_Linear(cmd,image);
//writeln;
end;
Procedure LoadFromBuffer(cmd:TvCustomCmdBuffer;image:TObject);
begin
if (cmd=nil) then Exit;
Case TvImage2(image).key.params.tiling_idx of
kTileModeDisplay_LinearAligned,
kTileModeDisplay_LinearGeneral:
_Load_Linear(cmd,TvImage2(image));
kTileModeDisplay_2dThin: //render target tiling todo
_Load_Linear(cmd,TvImage2(image));
kTileModeDepth_2dThin_64: //depth tiling todo
_Load_Linear(cmd,TvImage2(image));
kTileModeThin_1dThin: //texture
_Load_Thin_1dThin(cmd,TvImage2(image));
kTileModeThin_2dThin:
_Load_Linear(cmd,TvImage2(image)); //TODO
else
Assert(false,'TODO');
end;
end;
end.