unit vImageTiling; {$mode objfpc}{$H+} interface uses SysUtils, ps4_tiling, Vulkan, vDevice, vMemory, vBuffer, vImage, vImageManager, vHostBufferManager, vCmdBuffer; procedure pm4_load_from (cmd:TvCustomCmdBuffer;image:TvCustomImage2;IMAGE_USAGE:Byte); procedure pm4_write_back(cmd:TvCustomCmdBuffer;image:TvCustomImage2); Function get_image_size(const key:TvImageKey):Ptruint; implementation Function GetLinearAlignWidth(bpp,width:Ptruint):Ptruint; inline; var align_m:Ptruint; begin align_m:=(64 div bpp)-1; Result:=(width+align_m) and (not align_m); end; function Max(a,b:Ptruint):Ptruint; inline; begin if (a>b) then Result:=a else Result:=b; end; Function GetLinearSize(const key:TvImageKey;align:Boolean):Ptruint; var m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; m_padwidth,m_padheight:Ptruint; m_slice:Ptruint; begin Assert(key.params.samples<=1,'key.params.samples>1'); m_bytePerElement:=getFormatSize(key.cformat); m_level :=key.params.mipLevels; m_width :=key.params.width; m_height:=key.params.height; Result:=0; while (m_level>0) do begin m_padwidth :=m_width; m_padheight:=m_height; if align then begin m_padwidth:=GetLinearAlignWidth(m_bytePerElement,m_padwidth); end; if IsTexelFormat(key.cformat) then begin m_padwidth :=(m_padwidth +3) shr 2; m_padheight:=(m_padheight+3) shr 2; end; m_slice:=m_padwidth* m_padheight* m_bytePerElement; //m_slice:=(m_slice+255) and (not Ptruint(255)); Result:=Result+m_slice; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; Result:=Result* key.params.depth* key.params.arrayLayers; end; Function GetLinearAlignSize(const key:TvImageKey):Ptruint; begin Result:=GetLinearSize(key,true); end; Function Get1dThinAlignWidth(bpp,width:Ptruint):Ptruint; inline; var align_m:Ptruint; begin align_m:=(32 div bpp)-1; Result:=(width+align_m) and (not align_m); end; Function Get1dThinSize(const key:TvImageKey):Ptruint; var m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; m_padwidth,m_padheight:Ptruint; m_slice:Ptruint; begin Assert(key.params.samples<=1,'key.params.samples>1'); m_bytePerElement:=getFormatSize(key.cformat); m_level :=key.params.mipLevels; m_width :=key.params.width; m_height:=key.params.height; Result:=0; while (m_level>0) do begin m_padwidth :=Get1dThinAlignWidth(m_bytePerElement,m_width); m_padheight:=(m_height+7) and (not 7); if IsTexelFormat(key.cformat) then begin m_padwidth :=(m_padwidth +3) shr 2; m_padheight:=(m_padheight+3) shr 2; end; m_slice:=m_padwidth* m_padheight* m_bytePerElement; //m_slice:=(m_slice+255) and (not Ptruint(255)); Result:=Result+m_slice; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; //Result:=(Result+255) and (not Ptruint(255)); Result:=Result* key.params.depth* key.params.arrayLayers; end; function AlignDw(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline; begin Result:=addr-(addr mod alignment); end; type TvTempBuffer=class(TvBuffer) procedure ReleaseTmp(Sender:TObject); register; end; procedure TvTempBuffer.ReleaseTmp(Sender:TObject); register; begin Release(nil); Free; end; procedure load_clear(cmd:TvCustomCmdBuffer;image:TvCustomImage2); var Color:TVkClearColorValue; DepthStencil:TVkClearDepthStencilValue; Range:TVkImageSubresourceRange; begin image.PushBarrier(cmd, ord(VK_ACCESS_TRANSFER_WRITE_BIT), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); case image.key.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: begin DepthStencil:=Default(TVkClearDepthStencilValue); Range:=image.GetSubresRange; { vkCmdClearDepthStencilImage(cmd.FCmdbuf, image.FHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, @DepthStencil, 1, @Range);} end; else begin Color:=Default(TVkClearColorValue); Range:=image.GetSubresRange; { vkCmdClearColorImage(cmd.FCmdbuf, image.FHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, @Color, 1, @Range);} end; end; 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 SaveToTGA(const name:RawByteString;pData:Pointer;width,height,bpp:Ptruint); var F:THandle; Header:TTGAHeader; slice:Ptruint; begin slice:=(width*height*bpp+7) div 8; Header:=Default(TTGAHeader); Header.datatypecode :=3; Header.width :=width; Header.height :=height; Header.bitsperpixel :=bpp; Header.imagedescriptor:=32; F:=FileCreate(name); FileWrite(F,Header,SizeOf(TTGAHeader)); FileWrite(F,pData^,slice); FileClose(F); end; Procedure copy_1dThin(var tiler:Tiler1d;src,dst:Pointer); var m_bytePerElement:Ptruint; m_slice_size:Ptruint; i,x,y,z:QWORD; pSrc,pDst:Pointer; begin m_bytePerElement:=tiler.m_bitsPerElement div 8; m_slice_size:=(tiler.m_linearWidth*tiler.m_linearHeight); // For z:=0 to tiler.m_linearDepth-1 do For y:=0 to tiler.m_linearHeight-1 do For x:=0 to tiler.m_linearWidth-1 do begin i:=0; tiler.getTiledElementByteOffset(i,x,y,z); pSrc:=@PByte(src)[i]; pDst:=@PByte(dst)[(z*m_slice_size+y*tiler.m_linearWidth+x)*m_bytePerElement]; Move(pSrc^,pDst^,m_bytePerElement); end; end; Procedure _Copy_Linear(cmd:TvCustomCmdBuffer;buf:TvTempBuffer;image:TvCustomImage2); var BufferImageCopy:TVkBufferImageCopy; size:Ptruint; BufferImageCopyA:array of TVkBufferImageCopy; m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; m_padwidth,m_padheight:Ptruint; m_slice :Ptruint; m_offset:Ptruint; a,d,b:Ptruint; begin cmd.AddDependence(@buf.ReleaseTmp); m_bytePerElement:=getFormatSize(image.key.cformat); size:=GetLinearSize(image.key,false); image.PushBarrier(cmd, ord(VK_ACCESS_TRANSFER_WRITE_BIT), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); cmd.BufferMemoryBarrier(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.imageSubresource:=image.GetSubresLayer; BufferImageCopy.imageSubresource.layerCount:=1; BufferImageCopy.imageExtent.depth:=1; BufferImageCopyA:=nil; SetLength(BufferImageCopyA,image.key.params.arrayLayers*image.key.params.depth*image.key.params.mipLevels); b:=0; m_offset:=0; for a:=0 to image.key.params.arrayLayers-1 do for d:=0 to image.key.params.depth-1 do begin BufferImageCopy.imageSubresource.baseArrayLayer:=a; BufferImageCopy.imageOffset.z:=d; m_level :=image.key.params.mipLevels; m_width :=image.key.params.width; m_height:=image.key.params.height; while (m_level>0) do begin Assert((m_offset and 3)=0,'align by 4'); BufferImageCopy.bufferOffset:=m_offset; BufferImageCopy.imageSubresource.mipLevel:=image.key.params.mipLevels-m_level; BufferImageCopy.imageExtent.width :=m_width; BufferImageCopy.imageExtent.height:=m_height; BufferImageCopyA[b]:=BufferImageCopy; Inc(b); if IsTexelFormat(image.key.cformat) then begin m_padwidth :=(m_width +3) shr 2; m_padheight:=(m_height+3) shr 2; end else begin m_padwidth :=m_width ; m_padheight:=m_height; end; m_slice:=m_padwidth*m_padheight*m_bytePerElement; m_offset:=m_offset+m_slice; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; end; cmd.CopyBufferToImage(buf.FHandle, image.FHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Length(BufferImageCopyA), @BufferImageCopyA[0]); end; Procedure load_1dThin(cmd:TvCustomCmdBuffer;image:TvCustomImage2); var buf:TvTempBuffer; vmem:TvPointer; tiler:Tiler1d; m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; //m_padwidth,m_padheight:Ptruint; //m_slice:Ptruint; m_full_linear_size:Ptruint; m_base:Pointer; src:Pointer; dst:Pointer; begin Assert(image.key.params.samples<=1,'image.key.params.samples>1'); m_full_linear_size:=GetLinearSize(image.key,False); //m_base:=GetMem(m_full_linear_size); buf:=TvTempBuffer.Create(m_full_linear_size,ord(VK_BUFFER_USAGE_TRANSFER_SRC_BIT),nil); vmem:=MemManager.FetchMemory(buf.GetRequirements,V_PROP_HOST_VISIBLE or V_PROP_DEVICE_LOCAL); if (vmem.FMemory=nil) then begin vmem:=MemManager.FetchMemory(buf.GetRequirements,V_PROP_HOST_VISIBLE); end; buf.BindMem(vmem); //Release ref in ReleaseTmp m_base:=nil; vkMapMemory(Device.FHandle, buf.FBind.FMemory.FHandle, buf.FBind.FOffset, m_full_linear_size, 0, @m_base); dst:=m_base; m_bytePerElement:=getFormatSize(image.key.cformat); tiler.init_surface(m_bytePerElement, ord(IsTexelFormat(image.key.cformat)), image.key.params.tiling.idx, image.key.params.tiling.alt); //TvBuffer m_level :=image.key.params.mipLevels; m_width :=image.key.params.width; m_height:=image.key.params.height; src:=image.key.addr; while (m_level>0) do begin tiler.init_size_2d(m_width,m_height); // if (ptruint(dst-m_base)+tiler.m_linearSizeBytes)>m_full_linear_size then begin Writeln(ptruint(dst-m_base)+tiler.m_linearSizeBytes,'>',m_full_linear_size); Assert(false); end; copy_1dThin(tiler,src,dst); { SaveToTGA('shader_dump\texture_mip'+IntToStr(m_level)+ '_'+IntToStr(m_width)+ 'x'+IntToStr(m_height)+ '.tga', dst, tiler.m_linearWidth, tiler.m_linearHeight, tiler.m_bitsPerElement); } src:=src+tiler.m_tiledSizeBytes; dst:=dst+tiler.m_linearSizeBytes; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; vkUnmapMemory(Device.FHandle,buf.FBind.FMemory.FHandle); //FreeMem(m_base); _Copy_Linear(cmd,buf,image); end; Procedure Load_Linear(cmd:TvCustomCmdBuffer;image:TvCustomImage2); var buf:TvHostBuffer; BufferImageCopy:TVkBufferImageCopy; size:Ptruint; BufferImageCopyA:array of TVkBufferImageCopy; m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; m_padwidth,m_padheight:Ptruint; m_slice :Ptruint; m_offset:Ptruint; a,d,b:Ptruint; begin m_bytePerElement:=getFormatSize(image.key.cformat); size:=GetLinearSize(image.key,(image.key.params.tiling.idx<>kTileModeDisplay_LinearGeneral)); buf:=FetchHostBuffer(cmd, QWORD(image.key.addr), size, ord(VK_BUFFER_USAGE_TRANSFER_SRC_BIT)); m_offset:=buf.FAddr-QWORD(image.key.addr); image.PushBarrier(cmd, ord(VK_ACCESS_TRANSFER_WRITE_BIT), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); cmd.BufferMemoryBarrier(buf.FHandle, ord(VK_ACCESS_SHADER_WRITE_BIT), ord(VK_ACCESS_MEMORY_READ_BIT), m_offset, size, ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT), ord(VK_PIPELINE_STAGE_TRANSFER_BIT) ); BufferImageCopy:=Default(TVkBufferImageCopy); BufferImageCopy.imageSubresource:=image.GetSubresLayer; BufferImageCopy.imageSubresource.layerCount:=1; BufferImageCopy.imageExtent.depth:=1; BufferImageCopyA:=nil; SetLength(BufferImageCopyA,image.key.params.arrayLayers*image.key.params.depth*image.key.params.mipLevels); b:=0; for a:=0 to image.key.params.arrayLayers-1 do for d:=0 to image.key.params.depth-1 do begin BufferImageCopy.imageSubresource.baseArrayLayer:=a; BufferImageCopy.imageOffset.z:=d; m_level :=image.key.params.mipLevels; m_width :=image.key.params.width; m_height:=image.key.params.height; while (m_level>0) do begin Assert((m_offset and 3)=0,'align by 4'); BufferImageCopy.bufferOffset:=m_offset; BufferImageCopy.imageSubresource.mipLevel:=image.key.params.mipLevels-m_level; BufferImageCopy.imageExtent.width :=m_width; BufferImageCopy.imageExtent.height:=m_height; if (image.key.params.tiling.idx=8) then begin BufferImageCopy.bufferRowLength:=GetLinearAlignWidth(m_bytePerElement,m_width); end; BufferImageCopyA[b]:=BufferImageCopy; Inc(b); if IsTexelFormat(image.key.cformat) then begin m_padwidth :=(m_width +3) shr 2; m_padheight:=(m_height+3) shr 2; end else begin m_padwidth :=m_width ; m_padheight:=m_height; end; m_slice:=m_padwidth*m_padheight*m_bytePerElement; m_offset:=m_offset+m_slice; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; end; cmd.CopyBufferToImage(buf.FHandle, image.FHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Length(BufferImageCopyA), @BufferImageCopyA[0]); end; Procedure Writeback_Linear(cmd:TvCustomCmdBuffer;image:TvCustomImage2); var buf:TvHostBuffer; BufferImageCopy:TVkBufferImageCopy; size:Ptruint; BufferImageCopyA:array of TVkBufferImageCopy; m_bytePerElement:Ptruint; m_level,m_width,m_height:Ptruint; m_padwidth,m_padheight:Ptruint; m_slice :Ptruint; m_offset:Ptruint; a,d,b:Ptruint; begin m_bytePerElement:=getFormatSize(image.key.cformat); size:=GetLinearSize(image.key,(image.key.params.tiling.idx<>kTileModeDisplay_LinearGeneral)); buf:=FetchHostBuffer(cmd, QWORD(image.key.addr), size, ord(VK_BUFFER_USAGE_TRANSFER_DST_BIT)); m_offset:=buf.FAddr-QWORD(image.key.addr); image.PushBarrier(cmd, ord(VK_ACCESS_TRANSFER_READ_BIT), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); cmd.BufferMemoryBarrier(buf.FHandle, ord(VK_ACCESS_MEMORY_READ_BIT), ord(VK_ACCESS_TRANSFER_WRITE_BIT), m_offset, size, ord(VK_PIPELINE_STAGE_HOST_BIT), ord(VK_PIPELINE_STAGE_TRANSFER_BIT) ); BufferImageCopy:=Default(TVkBufferImageCopy); BufferImageCopy.imageSubresource:=image.GetSubresLayer; BufferImageCopy.imageSubresource.layerCount:=1; BufferImageCopy.imageExtent.depth:=1; BufferImageCopyA:=nil; SetLength(BufferImageCopyA,image.key.params.arrayLayers*image.key.params.depth*image.key.params.mipLevels); b:=0; for a:=0 to image.key.params.arrayLayers-1 do for d:=0 to image.key.params.depth-1 do begin BufferImageCopy.imageSubresource.baseArrayLayer:=a; BufferImageCopy.imageOffset.z:=d; m_level :=image.key.params.mipLevels; m_width :=image.key.params.width; m_height:=image.key.params.height; while (m_level>0) do begin Assert((m_offset and 3)=0,'align by 4'); BufferImageCopy.bufferOffset:=m_offset; BufferImageCopy.imageSubresource.mipLevel:=image.key.params.mipLevels-m_level; BufferImageCopy.imageExtent.width :=m_width; BufferImageCopy.imageExtent.height:=m_height; if (image.key.params.tiling.idx=8) then begin BufferImageCopy.bufferRowLength:=GetLinearAlignWidth(m_bytePerElement,m_width); end; BufferImageCopyA[b]:=BufferImageCopy; Inc(b); if IsTexelFormat(image.key.cformat) then begin m_padwidth :=(m_width +3) shr 2; m_padheight:=(m_height+3) shr 2; end else begin m_padwidth :=m_width ; m_padheight:=m_height; end; m_slice:=m_padwidth*m_padheight*m_bytePerElement; m_offset:=m_offset+m_slice; Dec(m_level); m_width :=Max(1,m_width shr 1); m_height:=Max(1,m_height shr 1); end; end; cmd.CopyImageToBuffer(image.FHandle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buf.FHandle, Length(BufferImageCopyA), @BufferImageCopyA[0]); end; type t_load_from_cb =procedure(cmd:TvCustomCmdBuffer;image:TvCustomImage2); t_write_back_cb=t_load_from_cb; t_get_size_cb =function(const key:TvImageKey):Ptruint; t_tiling_cbs=record load_from :t_load_from_cb; write_back:t_write_back_cb; get_size :t_get_size_cb; end; var a_tiling_cbs:array[0..63] of t_tiling_cbs; function TileIdx(idx,alt:Byte):Byte; inline; begin Result:=idx; TvTiling(Result).alt:=alt; end; procedure set_tiling_cbs(idx,alt:Byte; l:t_load_from_cb; w:t_write_back_cb; g:t_get_size_cb ); inline; begin with a_tiling_cbs[TileIdx(idx,alt)] do begin load_from :=l; write_back:=w; get_size :=g; end; end; procedure Init; begin set_tiling_cbs(kTileModeDisplay_2dThin ,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDisplay_2dThin ,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDepth_2dThin_256 ,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDepth_2dThin_256 ,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDepth_2dThin_64 ,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDepth_2dThin_64 ,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; // set_tiling_cbs(kTileModeDepth_1dThin ,0,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeDepth_1dThin ,1,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeDisplay_1dThin ,0,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeDisplay_1dThin ,1,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeThin_1dThin ,0,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeThin_1dThin ,1,@load_1dThin,nil,@Get1dThinSize); // set_tiling_cbs(kTileModeDisplay_LinearAligned,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); set_tiling_cbs(kTileModeDisplay_LinearAligned,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); end; procedure pm4_load_from(cmd:TvCustomCmdBuffer;image:TvCustomImage2;IMAGE_USAGE:Byte); var cb:t_load_from_cb; change_rate:t_change_rate; begin if (cmd=nil) or (image=nil) then Exit; if (IMAGE_USAGE and TM_READ)=0 then Exit; change_rate:=image.get_change_rate; if not change_rate.need_read then Exit; cb:=a_tiling_cbs[Byte(image.key.params.tiling)].load_from; if (cb=nil) then begin Writeln(stderr,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); Assert (false ,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); end; cmd.EndRenderPass; image.restore_vm_track; cb(cmd,image); change_rate.mark_init; image.apply_change_rate(change_rate); image.assign_vm_track; end; procedure pm4_write_back(cmd:TvCustomCmdBuffer;image:TvCustomImage2); var cb:t_write_back_cb; begin if (cmd=nil) or (image=nil) then Exit; cb:=a_tiling_cbs[Byte(image.key.params.tiling)].write_back; if (cb=nil) then begin Writeln(stderr,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); Assert (false ,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); end; cmd.EndRenderPass; cb(cmd,image); image.mark_init; image.assign_vm_track; cmd.AddPlannedTrigger(QWORD(image.key.Addr),QWORD(image.key.Addr)+image.size,image.tobj); end; Function get_image_size(const key:TvImageKey):Ptruint; [public, alias:'tiling_get_image_size']; var cb:t_get_size_cb; begin cb:=a_tiling_cbs[Byte(key.params.tiling)].get_size; if (cb=nil) then begin Writeln(stderr,'tiling:'+IntToStr(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); Assert (false ,'tiling:'+IntToStr(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); end; Result:=cb(key); end; { Procedure LoadFromBuffer(cmd:TvCustomCmdBuffer;image:TObject); begin if (cmd=nil) then Exit; Case TvCustomImage2(image).key.params.tiling_idx of kTileModeDisplay_LinearAligned, kTileModeDisplay_LinearGeneral: _Load_Linear(cmd,TvCustomImage2(image)); kTileModeDisplay_2dThin: //render target tiling todo _Load_Linear(cmd,TvCustomImage2(image)); kTileModeDepth_2dThin_64 , kTileModeDepth_2dThin_128, kTileModeDepth_2dThin_256, kTileModeDepth_2dThin_512, kTileModeDepth_2dThin_1K : //depth tiling todo _Load_Linear(cmd,TvCustomImage2(image)); kTileModeDepth_1dThin, kTileModeDisplay_1dThin, kTileModeThin_1dThin, //texture $1B: _Load_Thin_1dThin(cmd,TvCustomImage2(image)); kTileModeThin_2dThin: _Load_Linear(cmd,TvCustomImage2(image)); //TODO else if not SKIP_UNKNOW_TILING then Assert(false,'TODO tiling_idx:'+get_tiling_idx_str(TvCustomImage2(image).key.params.tiling_idx)); end; end; } initialization Init; end.