FPPS4/vulkan/vRegs2Vulkan.pas

2734 lines
90 KiB
Plaintext

unit vRegs2Vulkan;
{$mode ObjFPC}{$H+}
interface
uses
sysutils,
math,
bittype,
half16,
sys_bootparam,
Vulkan,
vDevice,
vImage,
vShader,
ps4_shader,
pm4defs,
si_ci_vi_merged_offset,
si_ci_vi_merged_enum,
si_ci_vi_merged_registers,
si_ci_vi_merged_groups;
type
TCMASK_INFO=record
KEY :TvImageKey;
SIZE:Ptruint;
end;
TRT_INFO=record
attachment:TVkUInt32;
FImageInfo:TvImageKey;
FImageView:TvImageViewKey;
COMP_SWAP :Byte;
IMAGE_USAGE:Byte;
CLEAR_COLOR:TVkClearColorValue;
CMASK_INFO:TCMASK_INFO;
blend:TVkPipelineColorBlendAttachmentState;
end;
THTILE_INFO=record
KEY :TvImageKey;
SIZE :Ptruint;
LINEAR :Byte;
TC_COMPATIBLE :Byte;
TILE_SURFACE_ENABLE:Byte;
TILE_STENCIL_ENABLE:Byte;
end;
TDB_INFO=record
Z_READ_ADDR :Pointer;
Z_WRITE_ADDR:Pointer;
STENCIL_READ_ADDR :Pointer;
STENCIL_WRITE_ADDR:Pointer;
CLEAR_VALUE:TVkClearValue;
ds_state:TVkPipelineDepthStencilStateCreateInfo;
DEPTH_USAGE :Byte;
STENCIL_USAGE:Byte;
FImageInfo:TvImageKey;
FImageView:TvImageViewKey;
zorder_stage:TVkPipelineStageFlags;
HTILE_INFO:THTILE_INFO;
end;
TBLEND_INFO=packed record
logicOp :TVkLogicOp;
blendConstants:array[0..3] of TVkFloat;
end;
TRASTERIZATION_INFO=packed record
State :TVkPipelineRasterizationStateCreateInfo;
ClipSpace:TVkBool32;
DepthClip:TVkBool32;
end;
PSH_REG_GFX_GROUP =^TSH_REG_GFX_GROUP; // 0x2C00
PSH_REG_COMPUTE_GROUP=^TSH_REG_COMPUTE_GROUP; // 0x2E00
PCONTEXT_REG_GROUP =^TCONTEXT_REG_GROUP; // 0xA000
PUSERCONFIG_REG_SHORT=^TUSERCONFIG_REG_SHORT;
PGPU_USERDATA=^TGPU_USERDATA;
PGPU_REGS=^TGPU_REGS;
TGPU_REGS=packed object
SG_REG:PSH_REG_GFX_GROUP; // 0x2C00
SC_REG:PSH_REG_COMPUTE_GROUP; // 0x2E00
CX_REG:PCONTEXT_REG_GROUP; // 0xA000
UC_REG:PUSERCONFIG_REG_SHORT; // 0xC000
Function _SHADER_MASK(i:Byte):Byte; inline; //0..7
Function _TARGET_MASK(i:Byte):Byte; inline; //0..7
Function _COMP_MASK(i:Byte):Byte; inline; //0..7
Function COMP_ENABLE:Boolean; inline;
Function RT_ENABLE(i:Byte):Boolean; //0..7
Function GET_HI_RT:Byte; //0..7
Function VP_ENABLE(i:Byte):Boolean; //0..15
Function GET_VPORT(i:Byte):TVkViewport; //0..15
Function GET_SCISSOR(i:Byte):TVkRect2D; //0..15
Function GET_SCREEN:TVkRect2D;
Function GET_SCREEN_SIZE:TVkExtent2D;
Function GET_RT_BLEND(i:Byte):TVkPipelineColorBlendAttachmentState; //0..7
Function GET_BLEND_INFO:TBLEND_INFO;
Function GET_RT_INFO(i:Byte;ignore_mask:Boolean=False):TRT_INFO; //0..7
Function DB_ENABLE:Boolean;
Function GET_DB_INFO:TDB_INFO;
Function GET_RASTERIZATION:TRASTERIZATION_INFO;
Function GET_PROVOKING:TVkProvokingVertexModeEXT;
Function GET_MULTISAMPLE:TVkPipelineMultisampleStateCreateInfo;
function GET_PRIM_RESET:TVkBool32;
function GET_PRIM_TYPE :Integer;
function GET_INDEX_TYPE:TVkIndexType;
function get_reg(i:word):DWORD;
Function get_code_addr(FStage:TvShaderStage):Pointer;
Function get_user_data(FStage:TvShaderStage):Pointer;
procedure export_user_data_rt(dst:PGPU_USERDATA);
procedure export_user_data_cs(dst:PGPU_USERDATA);
end;
TGPU_USERDATA=packed object
A:array[TvShaderStage] of TSPI_USER_DATA;
Function get_user_data(FStage:TvShaderStage):Pointer;
end;
TGPU_SHADERDATA_RT=packed object
SG_REG :TSH_REG_GFX_GROUP; // 0x2C00
SPI_PS_INPUT_ENA :TSPI_PS_INPUT_ENA; // 0xA1B3
SPI_PS_INPUT_ADDR :TSPI_PS_INPUT_ADDR; // 0xA1B4
SPI_INTERP_CONTROL_0 :TSPI_INTERP_CONTROL_0; // 0xA1B5
SPI_PS_IN_CONTROL :TSPI_PS_IN_CONTROL; // 0xA1B6
SPI_PS_INPUT_CNTL :array[0..31] of TSPI_PS_INPUT_CNTL_0; // 0xA191
DB_SHADER_CONTROL :TDB_SHADER_CONTROL; // 0xA203
VGT_INSTANCE_STEP_RATE_0:TVGT_INSTANCE_STEP_RATE_0; // 0xA2A8
VGT_INSTANCE_STEP_RATE_1:TVGT_INSTANCE_STEP_RATE_1; // 0xA2A9
RENDER_TARGET :array[0..7] of TRENDER_TARGET; // 0xA318
UC_REG :TUSERCONFIG_REG_SHORT; // 0xC000
end;
function GET_INDEX_TYPE_SIZE(INDEX_TYPE:TVkIndexType):Byte;
//
function _get_vsharp_cformat(PV:PVSharpResource4):TVkFormat;
function _get_tsharp4_cformat(PT:PTSharpResource4;hint:s_image_usage):TVkFormat;
function _get_tsharp4_image_info(PT:PTSharpResource4;hint:s_image_usage):TvImageKey;
function _get_tsharp8_image_info(PT:PTSharpResource8;hint:s_image_usage):TvImageKey;
function _get_tsharp4_image_view(PT:PTSharpResource4;hint:s_image_usage):TvImageViewKey;
function _get_tsharp8_image_view(PT:PTSharpResource8;hint:s_image_usage):TvImageViewKey;
function _get_ssharp_info(PS:PSSharpResource4):TVkSamplerCreateInfo;
implementation
uses
ps4_Tiling;
Function TGPU_REGS._SHADER_MASK(i:Byte):Byte; inline; //0..7
begin
Result:=(DWORD(CX_REG^.CB_SHADER_MASK) shr (i shl 2)) and 15;
end;
Function TGPU_REGS._TARGET_MASK(i:Byte):Byte; inline; //0..7
begin
Result:=(DWORD(CX_REG^.CB_TARGET_MASK) shr (i shl 2)) and 15;
end;
Function TGPU_REGS._COMP_MASK(i:Byte):Byte; inline; //0..7
begin
Result:=((DWORD(CX_REG^.CB_SHADER_MASK) and DWORD(CX_REG^.CB_TARGET_MASK)) shr (i shl 2)) and 15;
end;
Function TGPU_REGS.COMP_ENABLE:Boolean; inline;
begin
Result:=(DWORD(CX_REG^.CB_SHADER_MASK) and DWORD(CX_REG^.CB_TARGET_MASK))<>0;
end;
Function TGPU_REGS.RT_ENABLE(i:Byte):Boolean; //0..7
begin
Result:=(CX_REG^.RENDER_TARGET[i].BASE<>0) and
(CX_REG^.RENDER_TARGET[i].INFO.FORMAT<>0) and
(_COMP_MASK(i)<>0);
end;
Function TGPU_REGS.GET_HI_RT:Byte; //0..7
var
i:Byte;
begin
Result:=0;
For i:=1 to 7 do
begin
if RT_ENABLE(i) then
begin
Result:=i;
end;
end;
end;
Function TGPU_REGS.VP_ENABLE(i:Byte):Boolean; //0..15
begin
Result:=(PQWORD(@CX_REG^.PA_CL_VPORT_SCALE_OFFSET[i])[0]<>0) or
(PQWORD(@CX_REG^.PA_CL_VPORT_SCALE_OFFSET[i])[1]<>0) or
(PQWORD(@CX_REG^.PA_CL_VPORT_SCALE_OFFSET[i])[2]<>0);
end;
Function TGPU_REGS.GET_VPORT(i:Byte):TVkViewport; //0..15
var
V:TVPORT_SCALE_OFFSET;
VTE_CNTL:TPA_CL_VTE_CNTL;
depthClampDisable:Byte;
begin
Result:=Default(TVkViewport);
V:=CX_REG^.PA_CL_VPORT_SCALE_OFFSET[i];
VTE_CNTL:=CX_REG^.PA_CL_VTE_CNTL;
if (VTE_CNTL.VPORT_X_SCALE_ENA =0) then V.XSCALE :=1;
if (VTE_CNTL.VPORT_X_OFFSET_ENA=0) then V.XOFFSET:=0;
if (VTE_CNTL.VPORT_Y_SCALE_ENA =0) then V.YSCALE :=1;
if (VTE_CNTL.VPORT_Y_OFFSET_ENA=0) then V.YOFFSET:=0;
if (VTE_CNTL.VPORT_Z_SCALE_ENA =0) then V.ZSCALE :=1;
if (VTE_CNTL.VPORT_Z_OFFSET_ENA=0) then V.ZOFFSET:=0;
Assert(VTE_CNTL.VTX_XY_FMT=0,'VTE_CNTL.VTX_XY_FMT');
Assert(VTE_CNTL.VTX_Z_FMT =0,'VTE_CNTL.VTX_Z_FMT' );
Assert(VTE_CNTL.VTX_W0_FMT=1,'VTE_CNTL.VTX_W0_FMT');
Result.x :=V.XOFFSET-V.XSCALE;
Result.y :=V.YOFFSET-V.YSCALE;
Result.width :=V.XSCALE*2;
Result.height :=V.YSCALE*2;
if (CX_REG^.DB_RENDER_CONTROL.DEPTH_CLEAR_ENABLE<>0) then
begin
//force clear all
Result.minDepth:=PSingle(@CX_REG^.DB_DEPTH_CLEAR)^;
Result.maxDepth:=Result.minDepth;
end else
begin
//emulate: [-1,1] to [0,1]
//position.z = (position.z + position.w) * 0.5;
if limits.VK_EXT_depth_clip_control and //or emulate in shader?
(CX_REG^.PA_CL_CLIP_CNTL.DX_CLIP_SPACE_DEF=0) then
begin
//[-1..1]
Result.minDepth:=V.ZOFFSET-V.ZSCALE;
end else
begin
//[0..1]
Result.minDepth:=V.ZOFFSET;
end;
Result.maxDepth:=V.ZOFFSET+V.ZSCALE;
if (CX_REG^.DB_RENDER_OVERRIDE.DISABLE_VIEWPORT_CLAMP=0) then
begin
Result.minDepth:=max(Result.minDepth,CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMIN);
Result.maxDepth:=min(Result.maxDepth,CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMAX);
end;
end;
{
with CX_REG^.PA_CL_CLIP_CNTL do
depthClampDisable:=ZCLIP_NEAR_DISABLE or ZCLIP_FAR_DISABLE;
if (not Boolean(depthClampDisable)) then
if (not SameValue(Result.minDepth,CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMIN)) or
(not SameValue(Result.maxDepth,CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMAX)) then
begin
//VK_EXT_depth_clamp_control
//VkPipelineViewportDepthClampControlCreateInfoEXT
Writeln(stderr,'TODO:VK_EXT_depth_clamp_control');
Writeln(stderr,' minDepth:',Result.minDepth:0:5,' ZMIN:',CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMIN:0:5);
Writeln(stderr,' maxDepth:',Result.maxDepth:0:5,' ZMAX:',CX_REG^.PA_SC_VPORT_ZMIN_MAX[i].ZMAX:0:5);
//Assert(false,'TODO:VK_EXT_depth_clamp_control');
end;
}
end;
Function _fix_scissor_range(i:Word):Word; inline;
begin
Result:=i;
if SmallInt(Result)<0 then Result:=0;
if SmallInt(Result)>16384 then Result:=16384;
end;
function Min(a,b:Integer):Integer; inline;
begin
if (a<b) then Result:=a else Result:=b;
end;
function Max(a,b:Integer):Integer; inline;
begin
if (a>b) then Result:=a else Result:=b;
end;
Function TGPU_REGS.GET_SCISSOR(i:Byte):TVkRect2D; //0..15
var
u:record
Case Byte of
0:(
V_TL:TPA_SC_VPORT_SCISSOR_0_TL;
V_BR:TPA_SC_VPORT_SCISSOR_0_BR;
);
1:(
S_TL:TPA_SC_SCREEN_SCISSOR_TL;
S_BR:TPA_SC_SCREEN_SCISSOR_BR;
);
2:(
W_TL:TPA_SC_WINDOW_SCISSOR_TL;
W_BR:TPA_SC_WINDOW_SCISSOR_BR;
);
3:(
OFS:TPA_SC_WINDOW_OFFSET;
);
end;
ofs:TVkOffset2D;
sum:TVkRect2D;
tmp:TVkRect2D;
begin
if (CX_REG^.PA_SC_CLIPRECT_RULE.CLIP_RULE<>$FFFF) then
begin
Assert(false,'VK_EXT_discard_rectangles');
end;
//Screen Scissor rectangle
u.S_TL:=CX_REG^.PA_SC_SCREEN_SCISSOR_TL;
u.S_BR:=CX_REG^.PA_SC_SCREEN_SCISSOR_BR;
//
sum.offset.x :=Min(SmallInt(u.S_TL.TL_X),16383);
sum.offset.y :=Min(SmallInt(u.S_TL.TL_Y),16383);
sum.extent.width :=Min(SmallInt(u.S_BR.BR_X),16384);
sum.extent.height:=Min(SmallInt(u.S_BR.BR_Y),16384);
//
//Offset from screen coords to window coords
u.ofs:=CX_REG^.PA_SC_WINDOW_OFFSET;
//
ofs.x:=SmallInt(u.ofs.WINDOW_X_OFFSET);
ofs.y:=SmallInt(u.ofs.WINDOW_Y_OFFSET);
//
if (CX_REG^.PA_SU_SC_MODE_CNTL.VTX_WINDOW_OFFSET_ENABLE<>0) then
if (DWORD(u.ofs)<>0) then
begin
Assert(false,'VTX_WINDOW_OFFSET_ENABLE');
end;
//Generic Scissor rectangle specification
u.V_TL:=CX_REG^.PA_SC_GENERIC_SCISSOR.TL;
u.V_BR:=CX_REG^.PA_SC_GENERIC_SCISSOR.BR;
//
tmp.offset.x :=Min(Word(u.V_TL.TL_X),16383);
tmp.offset.y :=Min(Word(u.V_TL.TL_Y),16383);
tmp.extent.width :=Min(Word(u.V_BR.BR_X),16384);
tmp.extent.height:=Min(Word(u.V_BR.BR_Y),16384);
//
if (u.V_TL.WINDOW_OFFSET_DISABLE=0) then
begin
Inc(tmp.offset.x ,ofs.x);
Inc(tmp.offset.y ,ofs.y);
Inc(tmp.extent.width ,ofs.x);
Inc(tmp.extent.height,ofs.y);
end;
//
//apply
sum.offset.x :=Max(sum.offset.x ,tmp.offset.x );
sum.offset.y :=Max(sum.offset.y ,tmp.offset.y );
sum.extent.width :=Min(sum.extent.width ,tmp.extent.width );
sum.extent.height:=Min(sum.extent.height,tmp.extent.height);
//apply
//Window Scissor rectangle specification
u.W_TL:=CX_REG^.PA_SC_WINDOW_SCISSOR_TL;
u.W_BR:=CX_REG^.PA_SC_WINDOW_SCISSOR_BR;
//
tmp.offset.x :=Min(Word(u.W_TL.TL_X),16383);
tmp.offset.y :=Min(Word(u.W_TL.TL_Y),16383);
tmp.extent.width :=Min(Word(u.W_BR.BR_X),16384);
tmp.extent.height:=Min(Word(u.W_BR.BR_Y),16384);
//
if (u.W_TL.WINDOW_OFFSET_DISABLE=0) then
begin
Inc(tmp.offset.x ,ofs.x);
Inc(tmp.offset.y ,ofs.y);
Inc(tmp.extent.width ,ofs.x);
Inc(tmp.extent.height,ofs.y);
end;
//
//apply
sum.offset.x :=Max(sum.offset.x ,tmp.offset.x );
sum.offset.y :=Max(sum.offset.y ,tmp.offset.y );
sum.extent.width :=Min(sum.extent.width ,tmp.extent.width );
sum.extent.height:=Min(sum.extent.height,tmp.extent.height);
//apply
if (CX_REG^.PA_SC_MODE_CNTL_0.VPORT_SCISSOR_ENABLE<>0) then
begin
u.V_TL:=CX_REG^.PA_SC_VPORT_SCISSOR[i].TL;
u.V_BR:=CX_REG^.PA_SC_VPORT_SCISSOR[i].BR;
//
tmp.offset.x :=Min(Word(u.V_TL.TL_X),16383);
tmp.offset.y :=Min(Word(u.V_TL.TL_Y),16383);
tmp.extent.width :=Min(Word(u.V_BR.BR_X),16384);
tmp.extent.height:=Min(Word(u.V_BR.BR_Y),16384);
//
if (u.V_TL.WINDOW_OFFSET_DISABLE=0) then
begin
Inc(tmp.offset.x ,ofs.x);
Inc(tmp.offset.y ,ofs.y);
Inc(tmp.extent.width ,ofs.x);
Inc(tmp.extent.height,ofs.y);
end;
//
//apply
sum.offset.x :=Max(sum.offset.x ,tmp.offset.x );
sum.offset.y :=Max(sum.offset.y ,tmp.offset.y );
sum.extent.width :=Min(sum.extent.width ,tmp.extent.width );
sum.extent.height:=Min(sum.extent.height,tmp.extent.height);
//apply
end;
Result.offset.x :=sum.offset.x;
Result.offset.y :=sum.offset.y;
Result.extent.width :=sum.extent.width -sum.offset.x;
Result.extent.height:=sum.extent.height-sum.offset.y;
end;
Function TGPU_REGS.GET_SCREEN:TVkRect2D;
var
S_TL:TPA_SC_SCREEN_SCISSOR_TL;
S_BR:TPA_SC_SCREEN_SCISSOR_BR;
begin
S_TL:=CX_REG^.PA_SC_SCREEN_SCISSOR_TL;
S_BR:=CX_REG^.PA_SC_SCREEN_SCISSOR_BR;
//
Result.offset.x :=Min(SmallInt(S_TL.TL_X),16383);
Result.offset.y :=Min(SmallInt(S_TL.TL_Y),16383);
Result.extent.width :=Min(SmallInt(S_BR.BR_X),16384);
Result.extent.height:=Min(SmallInt(S_BR.BR_Y),16384);
Result.extent.width :=Result.extent.width -Result.offset.x;
Result.extent.height:=Result.extent.height-Result.offset.y;
end;
Function TGPU_REGS.GET_SCREEN_SIZE:TVkExtent2D;
var
S_BR:TPA_SC_SCREEN_SCISSOR_BR;
begin
S_BR:=CX_REG^.PA_SC_SCREEN_SCISSOR_BR;
//
Result.width :=Min(SmallInt(S_BR.BR_X),16384);
Result.height:=Min(SmallInt(S_BR.BR_Y),16384);
end;
Function GetBlendFactor(i:Byte):TVkBlendFactor;
begin
Case i of
BLEND_ZERO :Result:=VK_BLEND_FACTOR_ZERO;
BLEND_ONE :Result:=VK_BLEND_FACTOR_ONE;
BLEND_SRC_COLOR :Result:=VK_BLEND_FACTOR_SRC_COLOR;
BLEND_ONE_MINUS_SRC_COLOR :Result:=VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
BLEND_SRC_ALPHA :Result:=VK_BLEND_FACTOR_SRC_ALPHA;
BLEND_ONE_MINUS_SRC_ALPHA :Result:=VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
BLEND_DST_ALPHA :Result:=VK_BLEND_FACTOR_DST_ALPHA;
BLEND_ONE_MINUS_DST_ALPHA :Result:=VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
BLEND_DST_COLOR :Result:=VK_BLEND_FACTOR_DST_COLOR;
BLEND_ONE_MINUS_DST_COLOR :Result:=VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
BLEND_SRC_ALPHA_SATURATE :Result:=VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
BLEND_BOTH_SRC_ALPHA :Result:=VK_BLEND_FACTOR_SRC1_ALPHA;
BLEND_BOTH_INV_SRC_ALPHA :Result:=VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
BLEND_CONSTANT_COLOR :Result:=VK_BLEND_FACTOR_CONSTANT_COLOR;
BLEND_ONE_MINUS_CONSTANT_COLOR:Result:=VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
BLEND_SRC1_COLOR :Result:=VK_BLEND_FACTOR_SRC1_COLOR;
BLEND_INV_SRC1_COLOR :Result:=VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
BLEND_SRC1_ALPHA :Result:=VK_BLEND_FACTOR_SRC1_ALPHA;
BLEND_INV_SRC1_ALPHA :Result:=VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
BLEND_CONSTANT_ALPHA :Result:=VK_BLEND_FACTOR_CONSTANT_ALPHA;
BLEND_ONE_MINUS_CONSTANT_ALPHA:Result:=VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
else
Assert(false,'Unknow blend factor:0x'+HexStr(i,1));
end;
end;
Function GetBlendOp(i:Byte):TVkBlendOp;
begin
Case i of
COMB_DST_PLUS_SRC :Result:=VK_BLEND_OP_ADD;
COMB_SRC_MINUS_DST:Result:=VK_BLEND_OP_SUBTRACT;
COMB_MIN_DST_SRC :Result:=VK_BLEND_OP_MIN;
COMB_MAX_DST_SRC :Result:=VK_BLEND_OP_MAX;
COMB_DST_MINUS_SRC:Result:=VK_BLEND_OP_REVERSE_SUBTRACT;
else
Assert(false,'Unknow blend op:0x'+HexStr(i,1));
end;
end;
function GetRTCompCount(FORMAT:Byte):Byte;
begin
Result:=0;
Case FORMAT of
COLOR_8 :Result:=1;
COLOR_16 :Result:=1;
COLOR_8_8 :Result:=2;
COLOR_32 :Result:=1;
COLOR_16_16 :Result:=2;
COLOR_10_11_11 :Result:=3;
COLOR_11_11_10 :Result:=3;
COLOR_10_10_10_2 :Result:=4;
COLOR_2_10_10_10 :Result:=4;
COLOR_8_8_8_8 :Result:=4;
COLOR_32_32 :Result:=2;
COLOR_16_16_16_16 :Result:=4;
COLOR_RESERVED_13 :Result:=3; //32_32_32
COLOR_32_32_32_32 :Result:=4;
COLOR_5_6_5 :Result:=3;
COLOR_1_5_5_5 :Result:=4;
COLOR_5_5_5_1 :Result:=4;
COLOR_4_4_4_4 :Result:=4;
COLOR_8_24 :Result:=2;
COLOR_24_8 :Result:=2;
COLOR_X24_8_32_FLOAT:Result:=3;
end;
end;
type
TCOMP_MAP=array[0..3] of Byte;
function GetCompMap(COMP_SWAP,COUNT:Byte):TCOMP_MAP;
begin
Result:=Default(TCOMP_MAP);
Case COUNT of
1:
Case COMP_SWAP of
SWAP_STD :Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
SWAP_ALT :Result[0]:=ord(VK_COLOR_COMPONENT_G_BIT);
SWAP_STD_REV:Result[0]:=ord(VK_COLOR_COMPONENT_B_BIT);
SWAP_ALT_REV:Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
end;
2:
Case COMP_SWAP of
SWAP_STD :begin
Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_G_BIT);
end;
SWAP_ALT :begin
Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_A_BIT);
end;
SWAP_STD_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_B_BIT);
end;
SWAP_ALT_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_R_BIT);
end;
end;
3:
Case COMP_SWAP of
SWAP_STD :begin
Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_B_BIT);
end;
SWAP_ALT :begin
Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_A_BIT);
end;
SWAP_STD_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_B_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_G_BIT);
end;
SWAP_ALT_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_G_BIT);
end;
end;
4:
Case COMP_SWAP of
SWAP_STD :begin
Result[0]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_B_BIT);
Result[3]:=ord(VK_COLOR_COMPONENT_A_BIT);
end;
SWAP_ALT :begin
Result[0]:=ord(VK_COLOR_COMPONENT_B_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[3]:=ord(VK_COLOR_COMPONENT_A_BIT);
end;
SWAP_STD_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_B_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[3]:=ord(VK_COLOR_COMPONENT_R_BIT);
end;
SWAP_ALT_REV:begin
Result[0]:=ord(VK_COLOR_COMPONENT_A_BIT);
Result[1]:=ord(VK_COLOR_COMPONENT_R_BIT);
Result[2]:=ord(VK_COLOR_COMPONENT_G_BIT);
Result[3]:=ord(VK_COLOR_COMPONENT_B_BIT);
end;
end;
end;
{
Match the physical representation of the final pixel (RGBA)
to the output component number in shader export (0123)
}
//SWAP_STD (R=>0)
//SWAP_ALT (G=>0)
//SWAP_STD_REV (B=>0)
//SWAP_ALT_REV (A=>0)
//SWAP_STD (R=>0, G=>1)
//SWAP_ALT (R=>0, A=>1)
//SWAP_STD_REV (G=>0, R=>1)
//SWAP_ALT_REV (A=>0, R=>1)
//SWAP_STD (R=>0, G=>1, B=>2)
//SWAP_ALT (R=>0, G=>1, A=>2)
//SWAP_STD_REV (B=>0, G=>1, R=>2)
//SWAP_ALT_REV (A=>0, G=>1, R=>2)
//SWAP_STD (R=>0, G=>1, B=>2, A=>3)
//SWAP_ALT (B=>0, G=>1, R=>2, A=>3)
//SWAP_STD_REV (A=>0, B=>1, G=>2, R=>3)
//SWAP_ALT_REV (A=>0, R=>1, G=>2, B=>3)
end;
const
VK_SWIZZLE_I=ord(VK_COMPONENT_SWIZZLE_IDENTITY);
VK_SWIZZLE_Z=ord(VK_COMPONENT_SWIZZLE_ZERO );
VK_SWIZZLE_O=ord(VK_COMPONENT_SWIZZLE_ONE );
VK_SWIZZLE_R=ord(VK_COMPONENT_SWIZZLE_R );
VK_SWIZZLE_G=ord(VK_COMPONENT_SWIZZLE_G );
VK_SWIZZLE_B=ord(VK_COMPONENT_SWIZZLE_B );
VK_SWIZZLE_A=ord(VK_COMPONENT_SWIZZLE_A );
shader_swizzle_map:array[1..4,SWAP_STD..SWAP_ALT_REV] of TvDstSel=(
(
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_O;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_G;y:VK_SWIZZLE_O;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_B;y:VK_SWIZZLE_O;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_A;y:VK_SWIZZLE_O;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O)
),(
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_G;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_A;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_G;y:VK_SWIZZLE_R;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_A;y:VK_SWIZZLE_R;z:VK_SWIZZLE_O;w:VK_SWIZZLE_O)
),(
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_G;z:VK_SWIZZLE_B;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_G;z:VK_SWIZZLE_A;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_B;y:VK_SWIZZLE_G;z:VK_SWIZZLE_R;w:VK_SWIZZLE_O),
(x:VK_SWIZZLE_A;y:VK_SWIZZLE_G;z:VK_SWIZZLE_R;w:VK_SWIZZLE_O)
),(
(x:VK_SWIZZLE_R;y:VK_SWIZZLE_G;z:VK_SWIZZLE_B;w:VK_SWIZZLE_A),
(x:VK_SWIZZLE_B;y:VK_SWIZZLE_G;z:VK_SWIZZLE_R;w:VK_SWIZZLE_A),
(x:VK_SWIZZLE_A;y:VK_SWIZZLE_B;z:VK_SWIZZLE_G;w:VK_SWIZZLE_R),
(x:VK_SWIZZLE_A;y:VK_SWIZZLE_R;z:VK_SWIZZLE_G;w:VK_SWIZZLE_B)
)
);
Function TGPU_REGS.GET_RT_BLEND(i:Byte):TVkPipelineColorBlendAttachmentState; //0..7
var
RENDER_TARGET:TRENDER_TARGET;
BLEND_CONTROL:TCB_BLEND0_CONTROL;
COMP_MAP:TCOMP_MAP;
m:Byte;
begin
Result:=Default(TVkPipelineColorBlendAttachmentState);
RENDER_TARGET:=CX_REG^.RENDER_TARGET[i];
BLEND_CONTROL:=CX_REG^.CB_BLEND_CONTROL[i];
m:=GetRTCompCount(RENDER_TARGET.INFO.FORMAT);
COMP_MAP:=GetCompMap({RENDER_TARGET.INFO.COMP_SWAP}0,m);
//COMP_SWAP depend (B=>0, G=>1, R=>2, A=>3)
m:=_COMP_MASK(i);
if m.TestBit(0) then Result.colorWriteMask:=Result.colorWriteMask or COMP_MAP[0];
if m.TestBit(1) then Result.colorWriteMask:=Result.colorWriteMask or COMP_MAP[1];
if m.TestBit(2) then Result.colorWriteMask:=Result.colorWriteMask or COMP_MAP[2];
if m.TestBit(3) then Result.colorWriteMask:=Result.colorWriteMask or COMP_MAP[3];
//BLEND_CLAMP
if (RENDER_TARGET.INFO.BLEND_BYPASS<>0) then
begin
Result.blendEnable:=VK_FALSE;
end else
if (BLEND_CONTROL.ENABLE=0) then
begin
Result.blendEnable:=VK_FALSE;
end else
begin
Result.blendEnable:=VK_TRUE;
Result.srcColorBlendFactor:=GetBlendFactor(BLEND_CONTROL.COLOR_SRCBLEND);
Result.dstColorBlendFactor:=GetBlendFactor(BLEND_CONTROL.COLOR_DESTBLEND);
Result.colorBlendOp :=GetBlendOp (BLEND_CONTROL.COLOR_COMB_FCN);
if (BLEND_CONTROL.SEPARATE_ALPHA_BLEND=0) then
begin
Result.srcAlphaBlendFactor:=Result.srcColorBlendFactor;
Result.dstAlphaBlendFactor:=Result.dstColorBlendFactor;
Result.alphaBlendOp :=Result.colorBlendOp;
end else //VkPhysicalDeviceFeatures.independentBlend
begin
Result.srcAlphaBlendFactor:=GetBlendFactor(BLEND_CONTROL.ALPHA_SRCBLEND);
Result.dstAlphaBlendFactor:=GetBlendFactor(BLEND_CONTROL.ALPHA_DESTBLEND);
Result.alphaBlendOp :=GetBlendOp (BLEND_CONTROL.ALPHA_COMB_FCN);
end;
end;
end;
function get_logic_op(ROP3:Byte):TVkLogicOp;
begin
Result:=VK_LOGIC_OP_COPY;
case ROP3 of
$00:Result:=VK_LOGIC_OP_CLEAR;
$88:Result:=VK_LOGIC_OP_AND;
$44:Result:=VK_LOGIC_OP_AND_REVERSE;
$CC:Result:=VK_LOGIC_OP_COPY;
$22:Result:=VK_LOGIC_OP_AND_INVERTED;
$AA:Result:=VK_LOGIC_OP_NO_OP;
$66:Result:=VK_LOGIC_OP_XOR;
$EE:Result:=VK_LOGIC_OP_OR;
$11:Result:=VK_LOGIC_OP_NOR;
$99:Result:=VK_LOGIC_OP_EQUIVALENT;
$55:Result:=VK_LOGIC_OP_INVERT;
$DD:Result:=VK_LOGIC_OP_OR_REVERSE;
$33:Result:=VK_LOGIC_OP_COPY_INVERTED;
$BB:Result:=VK_LOGIC_OP_OR_INVERTED;
$77:Result:=VK_LOGIC_OP_NAND;
$FF:Result:=VK_LOGIC_OP_SET;
else
begin
Writeln(stderr,'unknow logic op:0x',HexStr(ROP3,2));
end;
end;
end;
Function TGPU_REGS.GET_BLEND_INFO:TBLEND_INFO;
begin
Result.logicOp:=get_logic_op(CX_REG^.CB_COLOR_CONTROL.ROP3);
Result.blendConstants[0]:=CX_REG^.CB_BLEND_RGBA[0];
Result.blendConstants[1]:=CX_REG^.CB_BLEND_RGBA[1];
Result.blendConstants[2]:=CX_REG^.CB_BLEND_RGBA[2];
Result.blendConstants[3]:=CX_REG^.CB_BLEND_RGBA[3];
end;
const
// Depth modes (for depth buffers)
kTileModeDepth_2dThin_64 = $00000000; ///< Recommended for depth targets with one fragment per pixel.
kTileModeDepth_2dThin_128 = $00000001; ///< Recommended for depth targets with two or four fragments per pixel, or texture-readable.
kTileModeDepth_2dThin_256 = $00000002; ///< Recommended for depth targets with eight fragments per pixel.
kTileModeDepth_2dThin_512 = $00000003; ///< Recommended for depth targets with 512-byte tiles.
kTileModeDepth_2dThin_1K = $00000004; ///< Recommended for depth targets with 1024-byte tiled.
kTileModeDepth_1dThin = $00000005; ///< Not used; included only for completeness.
kTileModeDepth_2dThinPrt_256 = $00000006; ///< Recommended for partially-resident depth surfaces. Does not support aliasing multiple virtual texture pages to the same physical page.
kTileModeDepth_2dThinPrt_1K = $00000007; ///< Not used; included only for completeness.
// Display modes
kTileModeDisplay_LinearAligned = $00000008; ///< Recommended for any surface to be easily accessed on the CPU.
kTileModeDisplay_1dThin = $00000009; ///< Not used; included only for completeness.
kTileModeDisplay_2dThin = $0000000A; ///< Recommended mode for displayable render targets.
kTileModeDisplay_ThinPrt = $0000000B; ///< Supports aliasing multiple virtual texture pages to the same physical page.
kTileModeDisplay_2dThinPrt = $0000000C; ///< Does not support aliasing multiple virtual texture pages to the same physical page.
// Thin modes (for non-displayable 1D/2D/3D surfaces)
kTileModeThin_1dThin = $0000000D; ///< Recommended for read-only non-volume textures.
kTileModeThin_2dThin = $0000000E; ///< Recommended for non-displayable intermediate render targets and read/write non-volume textures.
kTileModeThin_3dThin = $0000000F; ///< Not used; included only for completeness.
kTileModeThin_ThinPrt = $00000010; ///< Recommended for partially-resident textures (PRTs). Supports aliasing multiple virtual texture pages to the same physical page.
kTileModeThin_2dThinPrt = $00000011; ///< Does not support aliasing multiple virtual texture pages to the same physical page.
kTileModeThin_3dThinPrt = $00000012; ///< Does not support aliasing multiple virtual texture pages to the same physical page.
// Thick modes (for 3D textures)
kTileModeThick_1dThick = $00000013; ///< Recommended for read-only volume textures.
kTileModeThick_2dThick = $00000014; ///< Recommended for volume textures to which pixel shaders will write.
kTileModeThick_3dThick = $00000015; ///< Not used; included only for completeness.
kTileModeThick_ThickPrt = $00000016; ///< Supports aliasing multiple virtual texture pages to the same physical page.
kTileModeThick_2dThickPrt = $00000017; ///< Does not support aliasing multiple virtual texture pages to the same physical page.
kTileModeThick_3dThickPrt = $00000018; ///< Does not support aliasing multiple virtual texture pages to the same physical page.
kTileModeThick_2dXThick = $00000019; ///< Recommended for volume textures to which pixel shaders will write.
kTileModeThick_3dXThick = $0000001A; ///< Not used; included only for completeness.
// Hugely inefficient linear display mode -- do not use!
kTileModeDisplay_LinearGeneral = $0000001F; ///< Unsupported; do not use!
function _conv_clr_to_float(num:Byte;value,mask:qword):DWORD;
var
s:Single;
i:Integer;
begin
Result:=0;
Case num of
NUMBER_UNORM,
NUMBER_SRGB:
begin
s:=(value and mask)/mask;
Result:=PDWORD(@s)^;
end;
NUMBER_SNORM:
begin
i:=0;
Case mask of
$FF:i:=PShortInt(@value)^;
$FFFF:i:=PSmallInt(@value)^;
$FFFFFF:i:=PInteger (@value)^;
end;
s:=i/(mask div 2);
Result:=PDWORD(@s)^;
end;
NUMBER_UINT,
NUMBER_USCALED:
begin
Result:=(value and mask);
end;
NUMBER_SINT,
NUMBER_SSCALED:
begin
i:=0;
Case mask of
$FF:i:=PShortInt(@value)^;
$FFFF:i:=PSmallInt(@value)^;
$FFFFFF:i:=PInteger (@value)^;
else;
end;
Result:=PDWORD(@i)^;
end;
NUMBER_FLOAT:
begin
Case mask of
$FFFF:
begin
s:=PHalf16(@value)^;
Result:=PDWORD(@s)^;
end;
$FFFFFF:Result:=value;
else;
end;
end;
else;
end;
end;
type
TCLR_2_10_10_10=bitpacked record
A:bit2;
R:bit10;
G:bit10;
B:bit10;
end;
procedure _conv_clr_2_10_10_10(num:Byte;value:dword;var clr:TVkClearColorValue);
var
i:array[0..3] of Integer;
begin
i[0]:=TCLR_2_10_10_10(value).R;
i[1]:=TCLR_2_10_10_10(value).G;
i[2]:=TCLR_2_10_10_10(value).B;
i[3]:=TCLR_2_10_10_10(value).A;
if (num=NUMBER_SNORM) then
begin
Assert(false,'TODO NUMBER_SNORM');
end;
clr.float32[0]:=i[0];
clr.float32[1]:=i[1];
clr.float32[2]:=i[2];
clr.float32[3]:=i[3];
end;
function GetRenderTargetFormat(FORMAT,NUMBER_TYPE,TILING_ID:Byte):TVkFormat;
begin
Result:=VK_FORMAT_UNDEFINED;
Case FORMAT of
COLOR_8:
Case NUMBER_TYPE of
NUMBER_UNORM:Result:=VK_FORMAT_R8_UNORM;
NUMBER_SNORM:Result:=VK_FORMAT_R8_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R8_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R8_SINT;
else;
end;
COLOR_8_8:
Case NUMBER_TYPE of
NUMBER_UNORM:Result:=VK_FORMAT_R8G8_UNORM;
NUMBER_SNORM:Result:=VK_FORMAT_R8G8_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R8G8_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R8G8_SINT;
else;
end;
COLOR_8_8_8_8:
Case NUMBER_TYPE of
NUMBER_UNORM:Result:=VK_FORMAT_R8G8B8A8_UNORM;
NUMBER_SRGB :Result:=VK_FORMAT_R8G8B8A8_SRGB;
NUMBER_SNORM:Result:=VK_FORMAT_R8G8B8A8_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R8G8B8A8_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R8G8B8A8_SINT;
else;
end;
COLOR_16:
Case NUMBER_TYPE of
NUMBER_UNORM :Result:=VK_FORMAT_R16_UNORM;
NUMBER_SNORM :Result:=VK_FORMAT_R16_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R16_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R16_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R16_SFLOAT;
else;
end;
COLOR_16_16:
Case NUMBER_TYPE of
NUMBER_UNORM :Result:=VK_FORMAT_R16G16_UNORM;
NUMBER_SNORM :Result:=VK_FORMAT_R16G16_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R16G16_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R16G16_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R16G16_SFLOAT;
else;
end;
COLOR_16_16_16_16:
Case NUMBER_TYPE of
NUMBER_UNORM :Result:=VK_FORMAT_R16G16B16A16_UNORM;
NUMBER_SNORM :Result:=VK_FORMAT_R16G16B16A16_SNORM;
NUMBER_UINT :Result:=VK_FORMAT_R16G16B16A16_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R16G16B16A16_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R16G16B16A16_SFLOAT;
else;
end;
COLOR_32:
if IsTileModeDepth(TILING_ID) then
begin
Result:=VK_FORMAT_D32_SFLOAT;
end else
Case NUMBER_TYPE of
NUMBER_UINT :Result:=VK_FORMAT_R32_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R32_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R32_SFLOAT;
else;
end;
COLOR_32_32:
Case NUMBER_TYPE of
NUMBER_UINT :Result:=VK_FORMAT_R32G32_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R32G32_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R32G32_SFLOAT;
else;
end;
COLOR_32_32_32_32:
Case NUMBER_TYPE of
NUMBER_UINT :Result:=VK_FORMAT_R32G32B32A32_UINT;
NUMBER_SINT :Result:=VK_FORMAT_R32G32B32A32_SINT;
NUMBER_FLOAT :Result:=VK_FORMAT_R32G32B32A32_SFLOAT;
else;
end;
COLOR_2_10_10_10:
Case NUMBER_TYPE of
NUMBER_UNORM :Result:=VK_FORMAT_A2R10G10B10_UNORM_PACK32;
else;
end;
COLOR_10_11_11: //R:11 G:11 B:10
Case NUMBER_TYPE of
NUMBER_FLOAT :Result:=VK_FORMAT_B10G11R11_UFLOAT_PACK32;
else;
end;
COLOR_11_11_10: //R:10 G:11 B:11
Case NUMBER_TYPE of
NUMBER_FLOAT :Result:=VK_FORMAT_R10G11B11_UFLOAT_FAKE32; //Not directly handled to a vulkan
else;
end;
else;
end;
if (Result=VK_FORMAT_UNDEFINED) then
begin
Assert(false,'Unknown Render target format:'+IntTostr(FORMAT)+':'+IntTostr(NUMBER_TYPE));
end;
end;
Function TGPU_REGS.GET_RT_INFO(i:Byte;ignore_mask:Boolean=False):TRT_INFO; //0..7
var
scr:TVkExtent2D;
RENDER_TARGET:TRENDER_TARGET;
COMP_MAP:TCOMP_MAP;
W:QWORD;
FORMAT:Byte;
NUMBER_TYPE:Byte;
tmp:Word;
begin
Result:=Default(TRT_INFO);
if (not ignore_mask) and (not RT_ENABLE(i)) then
begin
Result.attachment:=VK_ATTACHMENT_UNUSED;
Result.FImageInfo.cformat :=VK_FORMAT_R8G8B8A8_UNORM;
Result.FImageInfo.params.itype :=ord(VK_IMAGE_TYPE_2D);
Result.FImageInfo.params.width :=1;
Result.FImageInfo.params.height :=1;
Result.FImageInfo.params.depth :=1;
Result.FImageInfo.params.samples :=1;
Result.FImageInfo.params.mipLevels :=1;
Result.FImageInfo.params.arrayLayers:=1;
Result.FImageView.cformat:=VK_FORMAT_R8G8B8A8_UNORM;
Result.FImageView.vtype :=ord(VK_IMAGE_VIEW_TYPE_2D);
Exit;
end;
Result.attachment:=i;
RENDER_TARGET:=CX_REG^.RENDER_TARGET[i];
Result.FImageInfo.Addr:=Pointer(QWORD(RENDER_TARGET.BASE) shl 8);
if (RENDER_TARGET.INFO.LINEAR_GENERAL<>0) then
begin
Result.FImageInfo.Addr:=Pointer(QWORD(Result.FImageInfo.Addr) or Byte(RENDER_TARGET.VIEW.SLICE_START));
end;
scr:=GET_SCREEN_SIZE;
Result.FImageInfo.params.width :=scr.width;
Result.FImageInfo.params.height:=scr.height;
Result.FImageInfo.params.depth :=1;
tmp:=(RENDER_TARGET.PITCH.TILE_MAX+1);
Result.FImageInfo.params.pad_width :=tmp*8;
Result.FImageInfo.params.pad_height:=(RENDER_TARGET.SLICE.TILE_MAX+1)*8 div tmp;
Assert(RENDER_TARGET.INFO.ENDIAN=ENDIAN_NONE,'ENDIAN:'+IntToStr(RENDER_TARGET.INFO.ENDIAN));
//Assert(RENDER_TARGET[i].INFO.COMPRESSION=0); //FMASK and MSAA
FORMAT :=RENDER_TARGET.INFO.FORMAT;
NUMBER_TYPE:=RENDER_TARGET.INFO.NUMBER_TYPE;
if (RENDER_TARGET.INFO.LINEAR_GENERAL<>0) then
begin
Result.FImageInfo.params.tiling.idx:=kTileModeDisplay_LinearGeneral;
end else
begin
Result.FImageInfo.params.tiling.idx:=RENDER_TARGET.ATTRIB.TILE_MODE_INDEX;
end;
Result.FImageInfo.cformat:=GetRenderTargetFormat(FORMAT,
NUMBER_TYPE,
Result.FImageInfo.params.tiling.idx);
if (p_neomode<>0) then
begin
Result.FImageInfo.params.tiling.alt:=RENDER_TARGET.INFO.ALT_TILE_MODE;
end;
Result.FImageInfo.params.itype :=ord(VK_IMAGE_TYPE_2D);
Result.FImageInfo.params.samples :=1 shl (RENDER_TARGET.ATTRIB.NUM_SAMPLES and 3);
Result.FImageInfo.params.mipLevels :=1;
Result.FImageInfo.params.arrayLayers:=1;
Result.FImageView.cformat :=Result.FImageInfo.cformat;
Result.FImageView.vtype :=ord(VK_IMAGE_VIEW_TYPE_2D);
//Result.FImageView.dstSel -> swizzle in shader
if (RENDER_TARGET.INFO.LINEAR_GENERAL=0) then
begin
Result.FImageInfo.params.arrayLayers:=RENDER_TARGET.VIEW.SLICE_MAX+1;
if (RENDER_TARGET.VIEW.SLICE_START>RENDER_TARGET.VIEW.SLICE_MAX) then
begin
Result.FImageView.base_array:=RENDER_TARGET.VIEW.SLICE_MAX;
end else
begin
Result.FImageView.base_array:=RENDER_TARGET.VIEW.SLICE_START;
end;
Result.FImageView.last_array:=Result.FImageView.base_array;
end;
Result.blend:=GET_RT_BLEND(i);
Result.COMP_SWAP:=RENDER_TARGET.INFO.COMP_SWAP;
//RENDER_TARGET.INFO.FAST_CLEAR CMASK
if (RENDER_TARGET.INFO.FAST_CLEAR<>0) then
begin
Result.CMASK_INFO.KEY.Addr:=Pointer(QWORD(RENDER_TARGET.CMASK) shl 8);
computeCmaskInfo(@Result.CMASK_INFO.SIZE,
nil,
@Result.CMASK_INFO.KEY.params.pad_width,
@Result.CMASK_INFO.KEY.params.pad_height,
//
RENDER_TARGET.PITCH,
RENDER_TARGET.VIEW,
RENDER_TARGET.INFO,
RENDER_TARGET.ATTRIB,
//
p_neomode,
Result.FImageInfo.params.height
);
end;
//Initially set READ/WRITE, for CLEAR/WRITE state it is necessary to check CMASK state
Result.IMAGE_USAGE:=TM_READ or TM_WRITE;
//if (Result.blend.blendEnable<>0) then
//begin
// Result.IMAGE_USAGE:=Result.IMAGE_USAGE or TM_READ;
//end;
Case FORMAT of
COLOR_8,
COLOR_8_8,
COLOR_8_8_8_8:
begin
COMP_MAP:=GetCompMap({RENDER_TARGET.INFO.COMP_SWAP}0,4);
//VK_COLOR_COMPONENT_R_BIT=$00000001, 0001
//VK_COLOR_COMPONENT_G_BIT=$00000002, 0010
//VK_COLOR_COMPONENT_B_BIT=$00000004, 0100
//VK_COLOR_COMPONENT_A_BIT=$00000008 1000
W:=RENDER_TARGET.CLEAR_WORD;
//Writeln((W shr (BsrDWord(COMP_MAP[0]) shl 3)) and 255);
//Writeln((W shr (BsrDWord(COMP_MAP[1]) shl 3)) and 255);
//Writeln((W shr (BsrDWord(COMP_MAP[2]) shl 3)) and 255);
//Writeln((W shr (BsrDWord(COMP_MAP[3]) shl 3)) and 255);
Result.CLEAR_COLOR.uint32[0]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[0]) shl 3),$FF);
Result.CLEAR_COLOR.uint32[1]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[1]) shl 3),$FF);
Result.CLEAR_COLOR.uint32[2]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[2]) shl 3),$FF);
Result.CLEAR_COLOR.uint32[3]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[3]) shl 3),$FF);
end;
COLOR_16,
COLOR_16_16,
COLOR_16_16_16_16:
begin
COMP_MAP:=GetCompMap({RENDER_TARGET.INFO.COMP_SWAP}0,4);
W:=RENDER_TARGET.CLEAR_WORD;
Result.CLEAR_COLOR.uint32[0]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[0]) shl 4),$FFFF);
Result.CLEAR_COLOR.uint32[1]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[1]) shl 4),$FFFF);
Result.CLEAR_COLOR.uint32[2]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[2]) shl 4),$FFFF);
Result.CLEAR_COLOR.uint32[3]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[3]) shl 4),$FFFF);
end;
COLOR_32,
COLOR_32_32:
begin
COMP_MAP:=GetCompMap({RENDER_TARGET.INFO.COMP_SWAP}0,4);
W:=RENDER_TARGET.CLEAR_WORD;
Result.CLEAR_COLOR.uint32[0]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[0]) shl 5),$FFFFFFFF);
Result.CLEAR_COLOR.uint32[1]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[1]) shl 5),$FFFFFFFF);
Result.CLEAR_COLOR.uint32[2]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[2]) shl 5),$FFFFFFFF);
Result.CLEAR_COLOR.uint32[3]:=_conv_clr_to_float(NUMBER_TYPE,W shr (BsrDWord(COMP_MAP[3]) shl 5),$FFFFFFFF);
end;
COLOR_32_32_32_32:; //128bit ignore
COLOR_2_10_10_10:
begin
W:=RENDER_TARGET.CLEAR_WORD;
_conv_clr_2_10_10_10(NUMBER_TYPE,W,Result.CLEAR_COLOR);
end
else
{Assert(false)}; //TODO
end;
if (RENDER_TARGET.ATTRIB.FORCE_DST_ALPHA_1<>0) then
begin
Assert(false,'RENDER_TARGET.ATTRIB.FORCE_DST_ALPHA_1<>0');
//Result.FImageView.dstSel.a:=ord(VK_COMPONENT_SWIZZLE_ONE);
end;
end;
Function TGPU_REGS.DB_ENABLE:Boolean;
begin
Result:=(
(CX_REG^.DB_DEPTH_CONTROL.STENCIL_ENABLE<>0) and
(CX_REG^.DB_STENCIL_INFO.FORMAT<>0)
) or
(
(CX_REG^.DB_DEPTH_CONTROL.Z_ENABLE<>0) and
(CX_REG^.DB_Z_INFO.FORMAT<>0)
);
end;
const
STENCIL_OP_STR:array[STENCIL_KEEP..STENCIL_XNOR] of Pchar=(
'KEEP',
'ZERO',
'ONES',
'REPLACE_TEST',
'REPLACE_OP',
'ADD_CLAMP',
'SUB_CLAMP',
'INVERT',
'ADD_WRAP',
'SUB_WRAP',
'AND',
'OR',
'XOR',
'NAND',
'NOR',
'XNOR'
);
Function GetStencilOpAndCheck(op :Byte;
hint:pchar;
DEPTH_CONTROL :TDB_DEPTH_CONTROL;
STENCILREFMASK:TDB_STENCILREFMASK
):TVkStencilOp;
begin
//test
case op of
STENCIL_ONES :begin //reference=$FF
if (DEPTH_CONTROL.STENCILFUNC=REF_NEVER) or
(DEPTH_CONTROL.STENCILFUNC=REF_ALWAYS) or
(STENCILREFMASK.STENCILTESTVAL=$FF) then
begin
//
end else
begin
Assert(false,'Unsupport stencil op['+hint+']:'+STENCIL_OP_STR[op]);
end;
end;
STENCIL_REPLACE_OP:begin //reference=STENCILOPVAL
if (DEPTH_CONTROL.STENCILFUNC=REF_NEVER) or
(DEPTH_CONTROL.STENCILFUNC=REF_ALWAYS) or
(STENCILREFMASK.STENCILTESTVAL=STENCILREFMASK.STENCILOPVAL) then
begin
//
end else
begin
Assert(false,'Unsupport stencil op['+hint+']:'+STENCIL_OP_STR[op]);
end;
end;
STENCIL_ADD_CLAMP ,
STENCIL_SUB_CLAMP ,
STENCIL_INVERT ,
STENCIL_ADD_WRAP ,
STENCIL_SUB_WRAP :Assert(STENCILREFMASK.STENCILOPVAL=1,
'Error stencil op['+hint+']:'+STENCIL_OP_STR[op]+
' STENCILOPVAL[0x'+HexStr(STENCILREFMASK.STENCILOPVAL,2)+'] must be = 1');
STENCIL_AND , // STENCILOPVAL
STENCIL_OR , // STENCILOPVAL
STENCIL_XOR , // STENCILOPVAL
STENCIL_NAND , // STENCILOPVAL
STENCIL_NOR , // STENCILOPVAL
STENCIL_XNOR : // STENCILOPVAL
Assert(false,'Unsupport stencil op:['+hint+']:'+STENCIL_OP_STR[op]);
else;
end;
case op of
STENCIL_KEEP :Result:=VK_STENCIL_OP_KEEP;
STENCIL_ZERO :Result:=VK_STENCIL_OP_ZERO;
STENCIL_ONES :Result:=VK_STENCIL_OP_REPLACE; //reference=$FF
STENCIL_REPLACE_TEST:Result:=VK_STENCIL_OP_REPLACE; //reference=STENCILTESTVAL
STENCIL_REPLACE_OP :Result:=VK_STENCIL_OP_REPLACE; //reference=STENCILOPVAL
STENCIL_ADD_CLAMP :Result:=VK_STENCIL_OP_INCREMENT_AND_CLAMP; //+1? STENCILOPVAL
STENCIL_SUB_CLAMP :Result:=VK_STENCIL_OP_DECREMENT_AND_CLAMP; //-1? STENCILOPVAL
STENCIL_INVERT :Result:=VK_STENCIL_OP_INVERT;
STENCIL_ADD_WRAP :Result:=VK_STENCIL_OP_INCREMENT_AND_WRAP; //+1? STENCILOPVAL
STENCIL_SUB_WRAP :Result:=VK_STENCIL_OP_DECREMENT_AND_WRAP; //-1? STENCILOPVAL
else;
end;
end;
Function _GetStencilRef(op:Byte;STENCILREFMASK:TDB_STENCILREFMASK):Integer; inline;
begin
case op of
STENCIL_ONES :Result:=$FF;
STENCIL_REPLACE_TEST:Result:=STENCILREFMASK.STENCILTESTVAL;
STENCIL_REPLACE_OP :Result:=STENCILREFMASK.STENCILOPVAL;
else
Result:=-1; //no change
end;
end;
procedure _set_st_ref(var cur:Integer;i:Integer); inline;
begin
if (i<>-1) then
begin
Assert((cur=-1) or (cur=i),'stencil param conflict');
cur:=i;
end;
end;
Function GetStencilRef(STENCIL_CONTROL:TDB_STENCIL_CONTROL;
DEPTH_CONTROL :TDB_DEPTH_CONTROL;
STENCILREFMASK :TDB_STENCILREFMASK):Byte;
var
cur:Integer;
begin
Result:=0;
//
if (DEPTH_CONTROL.STENCILFUNC=REF_NEVER) or
(DEPTH_CONTROL.STENCILFUNC=REF_ALWAYS) then
begin
cur:=-1;
end else
begin
cur:=STENCILREFMASK.STENCILTESTVAL;
end;
//
_set_st_ref(cur,_GetStencilRef(STENCIL_CONTROL.STENCILZPASS,STENCILREFMASK));
_set_st_ref(cur,_GetStencilRef(STENCIL_CONTROL.STENCILFAIL ,STENCILREFMASK));
_set_st_ref(cur,_GetStencilRef(STENCIL_CONTROL.STENCILZFAIL,STENCILREFMASK));
//
if (cur<>-1) then
begin
Result:=cur;
end;
end;
Function GetStencilRef_BF(STENCIL_CONTROL:TDB_STENCIL_CONTROL;
DEPTH_CONTROL :TDB_DEPTH_CONTROL;
STENCILREFMASK :TDB_STENCILREFMASK_BF):Byte; inline;
begin
Result:=GetStencilRef(TDB_STENCIL_CONTROL(DWORD(STENCIL_CONTROL) shr (4*3)), //FF->BF
DEPTH_CONTROL,
TDB_STENCILREFMASK(STENCILREFMASK));
end;
const
DB_Z_FORMATS:array[0..3,0..1] of TVkFormat=
(
//STENCIL_INVALID ,STENCIL_8
(VK_FORMAT_UNDEFINED ,VK_FORMAT_S8_UINT ), //Z_INVALID
(VK_FORMAT_D16_UNORM ,VK_FORMAT_D16_UNORM_S8_UINT ), //Z_16
(VK_FORMAT_X8_D24_UNORM_PACK32,VK_FORMAT_D24_UNORM_S8_UINT ), //Z_24
(VK_FORMAT_D32_SFLOAT ,VK_FORMAT_D32_SFLOAT_S8_UINT) //Z_32_FLOAT
);
DB_Z_ORDER:array[0..3] of TVkPipelineStageFlags=(
ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), //LATE_Z
ord(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) or //EARLY_Z_THEN_LATE_Z
ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), //RE_Z
ord(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) or //EARLY_Z_THEN_RE_Z
ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT)
);
Function TGPU_REGS.GET_DB_INFO:TDB_INFO;
var
scr:TVkExtent2D;
RENDER_CONTROL :TDB_RENDER_CONTROL;
DEPTH_CONTROL :TDB_DEPTH_CONTROL;
STENCIL_CONTROL :TDB_STENCIL_CONTROL;
STENCILREFMASK :TDB_STENCILREFMASK;
STENCILREFMASK_BF:TDB_STENCILREFMASK_BF;
SHADER_CONTROL :TDB_SHADER_CONTROL;
DB_Z_INFO :TDB_Z_INFO;
DB_DEPTH_VIEW :TDB_DEPTH_VIEW;
DB_STENCIL_INFO :TDB_STENCIL_INFO;
DB_HTILE_SURFACE :TDB_HTILE_SURFACE;
begin
Result:=Default(TDB_INFO);
RENDER_CONTROL :=CX_REG^.DB_RENDER_CONTROL;
DEPTH_CONTROL :=CX_REG^.DB_DEPTH_CONTROL;
STENCIL_CONTROL :=CX_REG^.DB_STENCIL_CONTROL;
STENCILREFMASK :=CX_REG^.DB_STENCILREFMASK;
STENCILREFMASK_BF:=CX_REG^.DB_STENCILREFMASK_BF;
SHADER_CONTROL :=CX_REG^.DB_SHADER_CONTROL;
DB_Z_INFO :=CX_REG^.DB_Z_INFO;
DB_DEPTH_VIEW :=CX_REG^.DB_DEPTH_VIEW;
DB_STENCIL_INFO :=CX_REG^.DB_STENCIL_INFO;
DB_HTILE_SURFACE :=CX_REG^.DB_HTILE_SURFACE;
//
if (DEPTH_CONTROL.Z_ENABLE<>0) then
begin
if (DB_DEPTH_VIEW.Z_READ_ONLY<>0) then
begin
//readonly
Result.DEPTH_USAGE:=TM_READ;
end else
if (RENDER_CONTROL.DEPTH_CLEAR_ENABLE<>0) then
begin
//clear
Result.DEPTH_USAGE:=TM_WRITE or TM_CLEAR;
end else
begin
//read before
Result.DEPTH_USAGE:=TM_READ or TM_WRITE;
end;
end;
if (DEPTH_CONTROL.STENCIL_ENABLE<>0) then
begin
if (DB_DEPTH_VIEW.STENCIL_READ_ONLY<>0) then
begin
//readonly
Result.STENCIL_USAGE:=TM_READ;
end else
if (RENDER_CONTROL.STENCIL_CLEAR_ENABLE<>0) then
begin
//clear
Result.STENCIL_USAGE:=TM_WRITE or TM_CLEAR;
end else
begin
//read before
Result.STENCIL_USAGE:=TM_READ or TM_WRITE;
end;
end;
Assert(RENDER_CONTROL.DEPTH_COPY =0,'RENDER_CONTROL.DEPTH_COPY' );
Assert(RENDER_CONTROL.STENCIL_COPY =0,'RENDER_CONTROL.STENCIL_COPY' );
Assert(RENDER_CONTROL.COPY_CENTROID=0,'RENDER_CONTROL.COPY_CENTROID');
Assert(RENDER_CONTROL.COPY_SAMPLE =0,'RENDER_CONTROL.COPY_SAMPLE' );
Result.CLEAR_VALUE.depthStencil.depth :=PSingle(@CX_REG^.DB_DEPTH_CLEAR)^;
Result.CLEAR_VALUE.depthStencil.stencil:=CX_REG^.DB_STENCIL_CLEAR.CLEAR;
/////
Result.ds_state.sType:=VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
Result.ds_state.depthTestEnable :=DEPTH_CONTROL.Z_ENABLE; //1:1
Result.ds_state.depthWriteEnable :=DEPTH_CONTROL.Z_WRITE_ENABLE; //1:1
Result.ds_state.depthBoundsTestEnable:=DEPTH_CONTROL.DEPTH_BOUNDS_ENABLE; //1:1
Result.ds_state.stencilTestEnable :=DEPTH_CONTROL.STENCIL_ENABLE; //1:1
if ((Result.DEPTH_USAGE and TM_CLEAR)=0) then
begin
Result.ds_state.depthCompareOp:=TVkCompareOp(DEPTH_CONTROL.ZFUNC); //1:1
//
Result.ds_state.minDepthBounds:=PSingle(@CX_REG^.DB_DEPTH_BOUNDS_MIN)^;
Result.ds_state.maxDepthBounds:=PSingle(@CX_REG^.DB_DEPTH_BOUNDS_MAX)^;
end else
begin
//force clear all
Result.ds_state.depthCompareOp:=VK_COMPARE_OP_ALWAYS;
//
Result.ds_state.depthBoundsTestEnable:=VK_FALSE;
end;
Assert(DEPTH_CONTROL.ENABLE_COLOR_WRITES_ON_DEPTH_FAIL =0,'ENABLE_COLOR_WRITES_ON_DEPTH_FAIL' );
Assert(DEPTH_CONTROL.DISABLE_COLOR_WRITES_ON_DEPTH_PASS=0,'DISABLE_COLOR_WRITES_ON_DEPTH_PASS');
//CX_REG^.PA_CL_CLIP_CNTL
if ((Result.STENCIL_USAGE and TM_CLEAR)<>0) then
begin
//force clear all
//VK_COMPARE_OP_NEVER|VK_STENCIL_OP_KEEP
end else
begin
Result.ds_state.front.failOp :=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILFAIL ,'STENCILFAIL ',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.front.passOp :=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILZPASS,'STENCILZPASS',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.front.depthFailOp:=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILZFAIL,'STENCILZFAIL',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.front.compareOp :=TVkCompareOp(DEPTH_CONTROL.STENCILFUNC); //1:1
Result.ds_state.front.compareMask:=STENCILREFMASK.STENCILMASK;
Result.ds_state.front.writeMask :=STENCILREFMASK.STENCILWRITEMASK;
Result.ds_state.front.reference :=GetStencilRef(STENCIL_CONTROL,DEPTH_CONTROL,STENCILREFMASK);
if (DEPTH_CONTROL.BACKFACE_ENABLE=0) then
begin
//BACKFACE DISABLE
Result.ds_state.back:=Result.ds_state.front;
end else
begin
//BACKFACE ENABLE
Result.ds_state.back.failOp :=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILFAIL_BF ,'STENCILFAIL_BF ',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.back.passOp :=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILZPASS_BF,'STENCILZPASS_BF',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.back.depthFailOp:=GetStencilOpAndCheck(STENCIL_CONTROL.STENCILZFAIL_BF,'STENCILZFAIL_BF',DEPTH_CONTROL,STENCILREFMASK);
Result.ds_state.back.compareOp :=TVkCompareOp(DEPTH_CONTROL.STENCILFUNC_BF); //1:1
Result.ds_state.back.compareMask:=STENCILREFMASK_BF.STENCILMASK_BF;
Result.ds_state.back.writeMask :=STENCILREFMASK_BF.STENCILWRITEMASK_BF;
Result.ds_state.back.reference :=GetStencilRef_BF(STENCIL_CONTROL,DEPTH_CONTROL,STENCILREFMASK_BF);
end;
end;
////
Result.Z_READ_ADDR :=Pointer(QWORD(CX_REG^.DB_Z_READ_BASE ) shl 8);
Result.Z_WRITE_ADDR:=Pointer(QWORD(CX_REG^.DB_Z_WRITE_BASE) shl 8);
if (DEPTH_CONTROL.Z_ENABLE<>0) then
if (DB_DEPTH_VIEW.Z_READ_ONLY=0) then
begin
if (Result.Z_READ_ADDR<>Result.Z_WRITE_ADDR) then
begin
Writeln(stderr,'Z_R_ADDR:'+HexStr(Result.Z_READ_ADDR)+'<>Z_W_ADDR:'+HexStr(Result.Z_WRITE_ADDR));
Assert (false ,'Z_R_ADDR:'+HexStr(Result.Z_READ_ADDR)+'<>Z_W_ADDR:'+HexStr(Result.Z_WRITE_ADDR));
end;
end;
Result.STENCIL_READ_ADDR :=Pointer(QWORD(CX_REG^.DB_STENCIL_READ_BASE ) shl 8);
Result.STENCIL_WRITE_ADDR:=Pointer(QWORD(CX_REG^.DB_STENCIL_WRITE_BASE) shl 8);
if (DEPTH_CONTROL.STENCIL_ENABLE<>0) then
if (DB_DEPTH_VIEW.STENCIL_READ_ONLY=0) then
begin
if (Result.STENCIL_READ_ADDR<>Result.STENCIL_WRITE_ADDR) then
begin
Writeln(stderr,'S_R_ADDR:'+HexStr(Result.STENCIL_READ_ADDR)+'<>S_W_ADDR:'+HexStr(Result.STENCIL_WRITE_ADDR));
Assert (false ,'S_R_ADDR:'+HexStr(Result.STENCIL_READ_ADDR)+'<>S_W_ADDR:'+HexStr(Result.STENCIL_WRITE_ADDR));
end;
end;
//Z_EXPORT_ENABLE -> shader export mrtz.R
//STENCIL_TEST_VAL_EXPORT_ENABLE -> shader export mrtz.G bits [0:7]
//STENCIL_OP_VAL_EXPORT_ENABLE -> shader export mrtz.G bits [8:15]
//MASK_EXPORT_ENABLE -> shader export mrtz.B
//COVERAGE_TO_MASK_ENABLE -> shader export mrtz.A
//VK_EXT_depth_range_unrestricted
Assert(CX_REG^.DB_RENDER_OVERRIDE.DISABLE_VIEWPORT_CLAMP=0,'DISABLE_VIEWPORT_CLAMP');
//SHADER_CONTROL.CONSERVATIVE_Z_EXPORT -> SPIRV DepthGreater/DepthLess
//CX_REG^.PA_SU_VTX_CNTL.PIX_CENTER -> SPIRV PixelCenterInteger
//SHADER_CONTROL.DEPTH_BEFORE_SHADER -> SPIRV EarlyFragmentTests
//CX_REG^.CB_COLOR_CONTROL
//CX_REG^.DB_RENDER_OVERRIDE.FORCE_SHADER_Z_ORDER
Result.zorder_stage:=DB_Z_ORDER[SHADER_CONTROL.Z_ORDER];
if (SHADER_CONTROL.DEPTH_BEFORE_SHADER<>0) then
begin
Result.zorder_stage:=Result.zorder_stage or ord(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
end;
//
if (DB_STENCIL_INFO.FORMAT<>0) then
begin
Assert(DB_Z_INFO.TILE_MODE_INDEX=DB_STENCIL_INFO.TILE_MODE_INDEX,'DB_Z_INFO.TILE_MODE_INDEX<>DB_STENCIL_INFO.TILE_MODE_INDEX');
end;
//
Result.FImageInfo.cformat:=DB_Z_FORMATS[DB_Z_INFO.FORMAT,DB_STENCIL_INFO.FORMAT];
Result.FImageInfo.Addr :=Result.Z_READ_ADDR;
Result.FImageInfo.Addr2 :=Result.STENCIL_READ_ADDR;
scr:=GET_SCREEN_SIZE;
Result.FImageInfo.params.width :=scr.width;
Result.FImageInfo.params.height:=scr.height;
Result.FImageInfo.params.depth :=1;
Result.FImageInfo.params.tiling.idx:=DB_Z_INFO.TILE_MODE_INDEX;
Result.FImageInfo.params.itype :=ord(VK_IMAGE_TYPE_2D);
Result.FImageInfo.params.samples :=1 shl (DB_Z_INFO.NUM_SAMPLES and 3);
Result.FImageInfo.params.mipLevels :=1;
Result.FImageInfo.params.arrayLayers:=DB_DEPTH_VIEW.SLICE_MAX+1;
Result.FImageInfo.params.pad_width :=(CX_REG^.DB_DEPTH_SIZE.PITCH_TILE_MAX +1)*8;
Result.FImageInfo.params.pad_height:=(CX_REG^.DB_DEPTH_SIZE.HEIGHT_TILE_MAX+1)*8;
//
Result.FImageView.cformat :=Result.FImageInfo.cformat;
Result.FImageView.vtype :=ord(VK_IMAGE_VIEW_TYPE_2D);
if (DB_DEPTH_VIEW.SLICE_START>DB_DEPTH_VIEW.SLICE_MAX) then
begin
Result.FImageView.base_array:=DB_DEPTH_VIEW.SLICE_MAX;
end else
begin
Result.FImageView.base_array:=DB_DEPTH_VIEW.SLICE_START;
end;
Result.FImageView.last_array:=Result.FImageView.base_array;
////
if (DB_Z_INFO.TILE_SURFACE_ENABLE<>0) and
(CX_REG^.DB_HTILE_DATA_BASE<>0) then
begin
Result.HTILE_INFO.KEY.ADDR:=Pointer(QWORD(CX_REG^.DB_HTILE_DATA_BASE) shl 8);
Result.HTILE_INFO.LINEAR:=DB_HTILE_SURFACE.LINEAR;
if (p_neomode<>0) then
begin
Result.HTILE_INFO.TC_COMPATIBLE:=DB_HTILE_SURFACE.TC_COMPATIBLE;
end;
Result.HTILE_INFO.TILE_SURFACE_ENABLE:=1;
Result.HTILE_INFO.TILE_STENCIL_ENABLE:=ord(DB_STENCIL_INFO.TILE_STENCIL_DISABLE=0);
if (Result.HTILE_INFO.TILE_STENCIL_ENABLE<>0) then
begin
Result.HTILE_INFO.KEY.Addr2:=Result.HTILE_INFO.KEY.ADDR;
end;
computeHtileInfo(@Result.HTILE_INFO.SIZE,
nil,
@Result.HTILE_INFO.KEY.params.pad_width,
@Result.HTILE_INFO.KEY.params.pad_height,
//
Result.FImageInfo.params.pad_width,
Result.FImageInfo.params.pad_height,
DB_DEPTH_VIEW.SLICE_MAX,
//
Boolean(Result.HTILE_INFO.LINEAR),
Boolean(Result.HTILE_INFO.TC_COMPATIBLE),
DB_Z_INFO.TILE_MODE_INDEX
);
Result.HTILE_INFO.KEY.params.pad_width:=Result.HTILE_INFO.KEY.params.pad_width div 16;
Result.HTILE_INFO.KEY.cformat:=VK_FORMAT_R32_UINT;
Result.HTILE_INFO.KEY.params.itype :=ord(VK_IMAGE_TYPE_2D);
if (Result.HTILE_INFO.LINEAR<>0) then
begin
Result.HTILE_INFO.KEY.params.tiling.idx:=kTileModeDisplay_LinearAligned;
Result.HTILE_INFO.KEY.params.tiling.alt:=Result.HTILE_INFO.TC_COMPATIBLE;
end else
begin
Result.HTILE_INFO.KEY.params.tiling.idx:=DB_Z_INFO.TILE_MODE_INDEX;
Result.HTILE_INFO.KEY.params.tiling.alt:=Result.HTILE_INFO.TC_COMPATIBLE;
end;
Result.HTILE_INFO.KEY.params.samples :=1;
Result.HTILE_INFO.KEY.params.mipLevels :=1;
Result.HTILE_INFO.KEY.params.width :=Result.HTILE_INFO.KEY.params.pad_width;
Result.HTILE_INFO.KEY.params.height :=Result.HTILE_INFO.KEY.params.pad_height;
Result.HTILE_INFO.KEY.params.depth :=1;
Result.HTILE_INFO.KEY.params.arrayLayers:=1;
end;
end;
function get_polygon_mode(SU_SC_MODE_CNTL:TPA_SU_SC_MODE_CNTL):TVkPolygonMode;
var
t:Byte;
begin
if (SU_SC_MODE_CNTL.POLY_MODE=0) then
begin
Exit(VK_POLYGON_MODE_FILL);
end;
//fillModeNonSolid
if (SU_SC_MODE_CNTL.CULL_FRONT=0) then
begin
t:=SU_SC_MODE_CNTL.POLYMODE_FRONT_PTYPE;
end else
if (SU_SC_MODE_CNTL.CULL_BACK=0) then
begin
t:=SU_SC_MODE_CNTL.POLYMODE_BACK_PTYPE;
end else
begin
t:=2;
end;
case t of
0:Result:=VK_POLYGON_MODE_POINT;
1:Result:=VK_POLYGON_MODE_LINE;
2:Result:=VK_POLYGON_MODE_FILL;
else
Result:=VK_POLYGON_MODE_FILL;
end;
end;
function get_cull_mode(SU_SC_MODE_CNTL:TPA_SU_SC_MODE_CNTL):TVkCullModeFlags;
begin
Result:=TVkCullModeFlags(SU_SC_MODE_CNTL.CULL_FRONT or (SU_SC_MODE_CNTL.CULL_BACK shl 1));
end;
Function TGPU_REGS.GET_RASTERIZATION:TRASTERIZATION_INFO;
var
SU_SC_MODE_CNTL:TPA_SU_SC_MODE_CNTL;
PA_CL_CLIP_CNTL:TPA_CL_CLIP_CNTL;
depthClampDisable:Byte;
begin
SU_SC_MODE_CNTL:=CX_REG^.PA_SU_SC_MODE_CNTL;
PA_CL_CLIP_CNTL:=CX_REG^.PA_CL_CLIP_CNTL;
Result:=Default(TRASTERIZATION_INFO);
Result.State.sType:=VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
if (SG_REG^.SPI_SHADER_PGM_LO_PS<>0) or
(SG_REG^.SPI_SHADER_PGM_HI_PS.MEM_BASE<>0) then
if (CX_REG^.DB_RENDER_CONTROL.DEPTH_CLEAR_ENABLE=0) and
(CX_REG^.DB_RENDER_CONTROL.STENCIL_CLEAR_ENABLE=0) then
begin
Result.State.rasterizerDiscardEnable:=PA_CL_CLIP_CNTL.DX_RASTERIZATION_KILL;
end;
//VK_EXT_depth_clip_control:TVkPipelineViewportDepthClipControlCreateInfoEXT
Result.ClipSpace:=ord(PA_CL_CLIP_CNTL.DX_CLIP_SPACE_DEF=0); //[-1..1]
if (UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE=DI_PT_RECTLIST) then
begin
//force disable clip/clamp
Result.DepthClip:=VK_FALSE;
depthClampDisable:=ord(True);
Result.State.cullMode:=ord(VK_CULL_MODE_NONE);
end else
if (CX_REG^.DB_RENDER_CONTROL.DEPTH_CLEAR_ENABLE<>0) then
begin
//force clear all
Result.DepthClip:=VK_FALSE;
depthClampDisable:=ord(False);
Result.State.cullMode:=ord(VK_CULL_MODE_NONE);
end else
begin
//VK_EXT_depth_clip_enable:TVkPipelineRasterizationDepthClipStateCreateInfoEXT
Result.DepthClip:=ord(PA_CL_CLIP_CNTL.CLIP_DISABLE=0);
depthClampDisable:=PA_CL_CLIP_CNTL.ZCLIP_NEAR_DISABLE or PA_CL_CLIP_CNTL.ZCLIP_FAR_DISABLE;
Result.State.cullMode:=get_cull_mode(SU_SC_MODE_CNTL);
end;
Result.State.depthClampEnable :=ord(not Boolean(depthClampDisable));
Result.State.polygonMode :=get_polygon_mode(SU_SC_MODE_CNTL);
Result.State.frontFace :=TVkFrontFace (SU_SC_MODE_CNTL.FACE); //1:1
Result.State.lineWidth :=(CX_REG^.PA_SU_LINE_CNTL.WIDTH/8);
if (DWORD(CX_REG^.PA_SU_POLY_OFFSET_DB_FMT_CNTL)<>0) then
begin
Result.State.depthBiasClamp:=PSingle(@CX_REG^.PA_SU_POLY_OFFSET_CLAMP)^;
if (SU_SC_MODE_CNTL.CULL_FRONT=0) then
begin
Result.State.depthBiasEnable :=SU_SC_MODE_CNTL.POLY_OFFSET_FRONT_ENABLE;
Result.State.depthBiasConstantFactor:=PSingle(@CX_REG^.PA_SU_POLY_OFFSET_FRONT_OFFSET)^;
Result.State.depthBiasSlopeFactor :=(PSingle(@CX_REG^.PA_SU_POLY_OFFSET_FRONT_SCALE)^/16);
end else
if (SU_SC_MODE_CNTL.CULL_BACK=0) then
begin
Result.State.depthBiasEnable :=SU_SC_MODE_CNTL.POLY_OFFSET_BACK_ENABLE;
Result.State.depthBiasConstantFactor:=PSingle(@CX_REG^.PA_SU_POLY_OFFSET_BACK_OFFSET)^;
Result.State.depthBiasSlopeFactor :=(PSingle(@CX_REG^.PA_SU_POLY_OFFSET_BACK_SCALE)^/16);
end;
end;
end;
Function TGPU_REGS.GET_PROVOKING:TVkProvokingVertexModeEXT;
begin
Result:=TVkProvokingVertexModeEXT(CX_REG^.PA_SU_SC_MODE_CNTL.PROVOKING_VTX_LAST);
end;
Function TGPU_REGS.GET_MULTISAMPLE:TVkPipelineMultisampleStateCreateInfo;
var
ps_iter_samples,num_samples:Integer;
begin
Result:=Default(TVkPipelineMultisampleStateCreateInfo);
Result.sType:=VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
if (CX_REG^.DB_EQAA.PS_ITER_SAMPLES<>0) or
(CX_REG^.PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES<>0) then
begin
ps_iter_samples:=1 shl CX_REG^.DB_EQAA.PS_ITER_SAMPLES;
num_samples :=1 shl CX_REG^.PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES;
Result.sampleShadingEnable :=VK_TRUE;
Result.rasterizationSamples :=TVkSampleCountFlagBits(num_samples);
Result.minSampleShading :=ps_iter_samples/num_samples;
Result.pSampleMask :=nil; //TODO
Result.alphaToCoverageEnable:=CX_REG^.DB_ALPHA_TO_MASK.ALPHA_TO_MASK_ENABLE;
Result.alphaToOneEnable :=VK_FALSE;
end else
begin
Result.rasterizationSamples:=VK_SAMPLE_COUNT_1_BIT;
end;
end;
function TGPU_REGS.GET_PRIM_RESET:TVkBool32;
var
val,mask:DWORD;
begin
Result:=CX_REG^.VGT_MULTI_PRIM_IB_RESET_EN.RESET_EN;
if (Result<>0) then
begin
mask:=0;
case (UC_REG^.VGT_INDEX_TYPE.INDEX_TYPE and 1) of
VGT_INDEX_16:mask:=$0000FFFF;
VGT_INDEX_32:mask:=$FFFFFFFF;
end;
val:=(CX_REG^.VGT_MULTI_PRIM_IB_RESET_INDX and mask);
Assert(val=mask,'unsupport reset index:0x'+HexStr(val,8));
end;
end;
function TGPU_REGS.GET_PRIM_TYPE:Integer;
begin
case UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE of
DI_PT_POINTLIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ;
DI_PT_LINELIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ;
DI_PT_LINESTRIP :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) ;
DI_PT_TRILIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) ;
DI_PT_TRIFAN :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ;
DI_PT_TRISTRIP :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) ;
DI_PT_PATCH :Result:=ord(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ;
DI_PT_LINELIST_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY) ;
DI_PT_LINESTRIP_ADJ:Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY) ;
DI_PT_TRILIST_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY) ;
DI_PT_TRISTRIP_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY);
DI_PT_RECTLIST ,
DI_PT_LINELOOP ,
DI_PT_QUADLIST ,
DI_PT_QUADSTRIP ,
DI_PT_POLYGON :Result:=UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE; //need to emulate
else
Assert(False,'unknow prim type:0x'+HexStr(UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE,1));
end;
end;
// VGT_DI_PRIM_TYPE
//DI_PT_NONE | kPrimitiveTypeNone |
//DI_PT_POINTLIST | kPrimitiveTypePointList | VK_PRIMITIVE_TOPOLOGY_POINT_LIST
//DI_PT_LINELIST | kPrimitiveTypeLineList | VK_PRIMITIVE_TOPOLOGY_LINE_LIST
//DI_PT_LINESTRIP | kPrimitiveTypeLineStrip | VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
//DI_PT_TRILIST | kPrimitiveTypeTriList | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
//DI_PT_TRIFAN | kPrimitiveTypeTriFan | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
//DI_PT_TRISTRIP | kPrimitiveTypeTriStrip | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
//DI_PT_PATCH | kPrimitiveTypePatch | VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
//DI_PT_LINELIST_ADJ | kPrimitiveTypeLineListAdjacency | VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
//DI_PT_LINESTRIP_ADJ | kPrimitiveTypeLineStripAdjacency | VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
//DI_PT_TRILIST_ADJ | kPrimitiveTypeTriListAdjacency | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
//DI_PT_TRISTRIP_ADJ | kPrimitiveTypeTriStripAdjacency | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
//DI_PT_RECTLIST | kPrimitiveTypeRectList |
//DI_PT_LINELOOP | kPrimitiveTypeLineLoop |
//DI_PT_QUADLIST | kPrimitiveTypeQuadList |
//DI_PT_QUADSTRIP | kPrimitiveTypeQuadStrip |
//DI_PT_POLYGON | kPrimitiveTypePolygon |
function TGPU_REGS.GET_INDEX_TYPE:TVkIndexType;
begin
if (CX_REG^.VGT_DMA_INDEX_TYPE.SWAP_MODE<>0) then
begin
Assert(false,'swapMode:'+IntToStr(CX_REG^.VGT_DMA_INDEX_TYPE.SWAP_MODE));
end;
Result:=TVkIndexType(UC_REG^.VGT_INDEX_TYPE.INDEX_TYPE and 1);
end;
function GET_INDEX_TYPE_SIZE(INDEX_TYPE:TVkIndexType):Byte; inline;
const
_s:array[0..1] of Byte=(2,4);
begin
Result:=_s[ord(INDEX_TYPE) and 1];
end;
function TGPU_REGS.get_reg(i:word):DWORD;
begin
case i of
$2C00..$2D8C:Result:=PDWORD(SG_REG)[i-$2C00];
$2E00..$2E7F:Result:=PDWORD(SC_REG)[i-$2E00];
$A000..$A38F:Result:=PDWORD(CX_REG)[i-$A000];
$C079:Result:=PDWORD(@UC_REG^.CP_COHER_BASE_HI )^;
$C07C:Result:=PDWORD(@UC_REG^.CP_COHER_CNTL )^;
$C07D:Result:=PDWORD(@UC_REG^.CP_COHER_SIZE )^;
$C07E:Result:=PDWORD(@UC_REG^.CP_COHER_BASE )^;
$C08C:Result:=PDWORD(@UC_REG^.CP_COHER_SIZE_HI )^;
$C200:Result:=PDWORD(@UC_REG^.GRBM_GFX_INDEX )^;
$C240:Result:=PDWORD(@UC_REG^.VGT_ESGS_RING_SIZE)^;
$C241:Result:=PDWORD(@UC_REG^.VGT_GSVS_RING_SIZE)^;
$C242:Result:=PDWORD(@UC_REG^.VGT_PRIMITIVE_TYPE)^;
$C243:Result:=PDWORD(@UC_REG^.VGT_INDEX_TYPE )^;
$C24C:Result:=PDWORD(@UC_REG^.VGT_NUM_INDICES )^;
$C24D:Result:=PDWORD(@UC_REG^.VGT_NUM_INSTANCES )^;
else
Result:=0;
end;
end;
Function TGPU_REGS.get_code_addr(FStage:TvShaderStage):Pointer;
begin
Result:=nil;
case FStage of
//vShaderStageLs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_LS,SG_REG^.SPI_SHADER_PGM_HI_LS.MEM_BASE);
//vShaderStageHs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_HS,SG_REG^.SPI_SHADER_PGM_HI_HS.MEM_BASE);
//vShaderStageEs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_ES,SG_REG^.SPI_SHADER_PGM_HI_ES.MEM_BASE);
//vShaderStageGs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_GS,SG_REG^.SPI_SHADER_PGM_HI_GS.MEM_BASE);
vShaderStageVs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_VS,SG_REG^.SPI_SHADER_PGM_HI_VS.MEM_BASE);
vShaderStagePs:Result:=getCodeAddress(SG_REG^.SPI_SHADER_PGM_LO_PS,SG_REG^.SPI_SHADER_PGM_HI_PS.MEM_BASE);
vShaderStageCs:Result:=getCodeAddress(SC_REG^.COMPUTE_PGM_LO ,SC_REG^.COMPUTE_PGM_HI.DATA);
end;
end;
Function TGPU_REGS.get_user_data(FStage:TvShaderStage):Pointer;
begin
Result:=nil;
case FStage of
vShaderStageLs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_LS;
vShaderStageHs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_HS;
vShaderStageEs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_ES;
vShaderStageGs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_GS;
vShaderStageVs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_VS;
vShaderStagePs:Result:=@SG_REG^.SPI_SHADER_USER_DATA_PS;
vShaderStageCs:Result:=@SC_REG^.COMPUTE_USER_DATA;
end;
end;
procedure TGPU_REGS.export_user_data_rt(dst:PGPU_USERDATA);
begin
dst^.A[vShaderStageLs]:=SG_REG^.SPI_SHADER_USER_DATA_LS;
dst^.A[vShaderStageHs]:=SG_REG^.SPI_SHADER_USER_DATA_HS;
dst^.A[vShaderStageEs]:=SG_REG^.SPI_SHADER_USER_DATA_ES;
dst^.A[vShaderStageGs]:=SG_REG^.SPI_SHADER_USER_DATA_GS;
dst^.A[vShaderStageVs]:=SG_REG^.SPI_SHADER_USER_DATA_VS;
dst^.A[vShaderStagePs]:=SG_REG^.SPI_SHADER_USER_DATA_PS;
end;
procedure TGPU_REGS.export_user_data_cs(dst:PGPU_USERDATA);
begin
dst^.A[vShaderStageCs]:=SC_REG^.COMPUTE_USER_DATA;
end;
Function TGPU_USERDATA.get_user_data(FStage:TvShaderStage):Pointer;
begin
Result:=@A[FStage];
end;
///
function _get_vsharp_cformat(PV:PVSharpResource4):TVkFormat;
begin
Result:=VK_FORMAT_UNDEFINED;
if (PV=nil) then Exit;
Case PV^.nfmt of
BUF_NUM_FORMAT_RESERVED_6:
Exit(VK_FORMAT_UNDEFINED);
else;
end;
case PV^.dfmt of
BUF_DATA_FORMAT_INVALID,
BUF_DATA_FORMAT_RESERVED_15:
Exit(VK_FORMAT_UNDEFINED);
else;
end;
Case PV^.nfmt of
BUF_NUM_FORMAT_UNORM:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_UNORM;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_UNORM;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_UNORM;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_UNORM;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_UNORM;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_UNORM;
BUF_DATA_FORMAT_2_10_10_10 :Result:=VK_FORMAT_A2R10G10B10_UNORM_PACK32;
else;
end;
BUF_NUM_FORMAT_SNORM:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SNORM;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SNORM;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SNORM;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SNORM;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SNORM;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SNORM;
else;
end;
BUF_NUM_FORMAT_USCALED:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_USCALED;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_USCALED;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_USCALED;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_USCALED;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_USCALED;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_USCALED;
else;
end;
BUF_NUM_FORMAT_SSCALED:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SSCALED;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SSCALED;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SSCALED;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SSCALED;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SSCALED;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SSCALED;
else;
end;
BUF_NUM_FORMAT_UINT:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_UINT;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_UINT;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_UINT;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_UINT;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_UINT;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_UINT;
BUF_DATA_FORMAT_32 :Result:=VK_FORMAT_R32_UINT;
BUF_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_UINT;
BUF_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_UINT;
BUF_DATA_FORMAT_32_32_32_32:Result:=VK_FORMAT_R32G32B32A32_UINT;
else;
end;
BUF_NUM_FORMAT_SINT:
case PV^.dfmt of
BUF_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SINT;
BUF_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SINT;
BUF_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SINT;
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SINT;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SINT;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SINT;
BUF_DATA_FORMAT_32 :Result:=VK_FORMAT_R32_SINT;
BUF_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_SINT;
BUF_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_SINT;
BUF_DATA_FORMAT_32_32_32_32:Result:=VK_FORMAT_R32G32B32A32_SINT;
else;
end;
BUF_NUM_FORMAT_FLOAT:
case PV^.dfmt of
BUF_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SFLOAT;
BUF_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SFLOAT;
BUF_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SFLOAT;
BUF_DATA_FORMAT_32 :Result:=VK_FORMAT_R32_SFLOAT;
BUF_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_SFLOAT;
BUF_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_SFLOAT;
BUF_DATA_FORMAT_32_32_32_32:Result:=VK_FORMAT_R32G32B32A32_SFLOAT;
else;
end;
else;
end;
Assert(Result<>VK_FORMAT_UNDEFINED,'[_get_vsharp_cformat] dfmt:'+_get_buf_dfmt_str(PV^.dfmt)+' nfmt:'+_get_buf_nfmt_str(PV^.nfmt));
end;
function _img_is_msaa(b:Byte):Boolean; inline;
begin
Case b of
SQ_RSRC_IMG_2D_MSAA ,
SQ_RSRC_IMG_2D_MSAA_ARRAY:Result:=True;
else
Result:=False;
end;
end;
function _get_tsharp4_cformat(PT:PTSharpResource4;hint:s_image_usage):TVkFormat;
begin
Result:=VK_FORMAT_UNDEFINED;
if (PT=nil) then Exit;
Case PT^.nfmt of
IMG_NUM_FORMAT_RESERVED_6 ,
IMG_NUM_FORMAT_RESERVED_8 ,
IMG_NUM_FORMAT_RESERVED_10,
IMG_NUM_FORMAT_RESERVED_11,
IMG_NUM_FORMAT_RESERVED_12,
IMG_NUM_FORMAT_RESERVED_13,
IMG_NUM_FORMAT_RESERVED_14,
IMG_NUM_FORMAT_RESERVED_15:
Exit(VK_FORMAT_UNDEFINED);
else;
end;
Case PT^.dfmt of
IMG_DATA_FORMAT_INVALID ,
IMG_DATA_FORMAT_RESERVED_15,
IMG_DATA_FORMAT_RESERVED_23,
IMG_DATA_FORMAT_RESERVED_24,
IMG_DATA_FORMAT_RESERVED_25,
IMG_DATA_FORMAT_RESERVED_26,
IMG_DATA_FORMAT_RESERVED_27,
IMG_DATA_FORMAT_RESERVED_28,
IMG_DATA_FORMAT_RESERVED_29,
IMG_DATA_FORMAT_RESERVED_30,
IMG_DATA_FORMAT_RESERVED_31,
IMG_DATA_FORMAT_1_REVERSED :
Exit(VK_FORMAT_UNDEFINED);
else;
end;
Case PT^.nfmt of
IMG_NUM_FORMAT_UNORM :
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_UNORM;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_UNORM;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_UNORM;
IMG_DATA_FORMAT_16 :
if (not (iu_storage in hint)) and
IsTileModeDepth(PT^.tiling_idx) then
begin
Result:=VK_FORMAT_D16_UNORM;
end else
begin
Result:=VK_FORMAT_R16_UNORM;
end;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_UNORM;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_UNORM;
IMG_DATA_FORMAT_5_6_5 :Result:=VK_FORMAT_R5G6B5_UNORM_PACK16; //real -> B5G6R5
IMG_DATA_FORMAT_4_4_4_4 :Result:=VK_FORMAT_B4G4R4A4_UNORM_PACK16; //real -> A4B4G4R4
IMG_DATA_FORMAT_BC1 :Result:=VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
IMG_DATA_FORMAT_BC2 :Result:=VK_FORMAT_BC2_UNORM_BLOCK;
IMG_DATA_FORMAT_BC3 :Result:=VK_FORMAT_BC3_UNORM_BLOCK;
IMG_DATA_FORMAT_BC4 :Result:=VK_FORMAT_BC4_UNORM_BLOCK;
IMG_DATA_FORMAT_BC5 :Result:=VK_FORMAT_BC5_UNORM_BLOCK;
IMG_DATA_FORMAT_BC6 :Result:=VK_FORMAT_BC6H_UFLOAT_BLOCK;
IMG_DATA_FORMAT_BC7 :Result:=VK_FORMAT_BC7_UNORM_BLOCK;
IMG_DATA_FORMAT_2_10_10_10 :Result:=VK_FORMAT_A2R10G10B10_UNORM_PACK32;
else;
end;
IMG_NUM_FORMAT_SRGB :
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SRGB;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SRGB;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SRGB;
IMG_DATA_FORMAT_BC1 :Result:=VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
IMG_DATA_FORMAT_BC2 :Result:=VK_FORMAT_BC2_SRGB_BLOCK;
IMG_DATA_FORMAT_BC3 :Result:=VK_FORMAT_BC3_SRGB_BLOCK;
IMG_DATA_FORMAT_BC4 :Result:=VK_FORMAT_BC4_UNORM_BLOCK;
IMG_DATA_FORMAT_BC5 :Result:=VK_FORMAT_BC5_UNORM_BLOCK;
IMG_DATA_FORMAT_BC6 :Result:=VK_FORMAT_BC6H_UFLOAT_BLOCK;
IMG_DATA_FORMAT_BC7 :Result:=VK_FORMAT_BC7_SRGB_BLOCK;
IMG_DATA_FORMAT_2_10_10_10 :Result:=VK_FORMAT_A2R10G10B10_UNORM_PACK32;
else;
end;
IMG_NUM_FORMAT_SNORM :
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SNORM;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SNORM;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SNORM;
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SNORM;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SNORM;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SNORM;
IMG_DATA_FORMAT_BC4 :Result:=VK_FORMAT_BC4_SNORM_BLOCK;
IMG_DATA_FORMAT_BC5 :Result:=VK_FORMAT_BC5_SNORM_BLOCK;
IMG_DATA_FORMAT_BC6 :Result:=VK_FORMAT_BC6H_SFLOAT_BLOCK;
else;
end;
IMG_NUM_FORMAT_USCALED:
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_USCALED;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_USCALED;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_USCALED;
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_USCALED;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_USCALED;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_USCALED;
else;
end;
IMG_NUM_FORMAT_SSCALED:
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SSCALED;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SSCALED;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SSCALED;
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SSCALED;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SSCALED;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SSCALED;
else;
end;
IMG_NUM_FORMAT_UINT :
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_UINT;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_UINT;
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_UINT;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_UINT;
IMG_DATA_FORMAT_16_16_16_16 :Result:=VK_FORMAT_R16G16B16A16_UINT;
IMG_DATA_FORMAT_32 :
if (not (iu_storage in hint)) and
IsTileModeDepth(PT^.tiling_idx) then
begin
Result:=VK_FORMAT_D32_SFLOAT;
end else
begin
Result:=VK_FORMAT_R32_UINT;
end;
IMG_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_UINT;
IMG_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_UINT;
IMG_DATA_FORMAT_32_32_32_32 :Result:=VK_FORMAT_R32G32B32A32_UINT;
IMG_DATA_FORMAT_1_5_5_5 :Result:=VK_FORMAT_A1R5G5B5_UNORM_PACK16;
IMG_DATA_FORMAT_5_5_5_1 :Result:=VK_FORMAT_R5G5B5A1_UNORM_PACK16;
IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK16_S16_F1:Result:=VK_FORMAT_R16_UINT;
IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=VK_FORMAT_R16_UINT;
IMG_DATA_FORMAT_FMASK32_S16_F2:Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK64_S16_F4:Result:=VK_FORMAT_R64_UINT;
IMG_DATA_FORMAT_FMASK64_S16_F8:Result:=VK_FORMAT_R64_UINT;
else;
end;
IMG_NUM_FORMAT_SINT :
case PT^.dfmt of
IMG_DATA_FORMAT_8 :Result:=VK_FORMAT_R8_SINT;
IMG_DATA_FORMAT_8_8 :Result:=VK_FORMAT_R8G8_SINT;
IMG_DATA_FORMAT_8_8_8_8 :Result:=VK_FORMAT_R8G8B8A8_SINT;
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SINT;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SINT;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SINT;
IMG_DATA_FORMAT_32 :
if (not (iu_storage in hint)) and
IsTileModeDepth(PT^.tiling_idx) then
begin
Result:=VK_FORMAT_D32_SFLOAT;
end else
begin
Result:=VK_FORMAT_R32_SINT;
end;
IMG_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_SINT;
IMG_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_SINT;
IMG_DATA_FORMAT_32_32_32_32 :Result:=VK_FORMAT_R32G32B32A32_SINT;
IMG_DATA_FORMAT_1_5_5_5 :Result:=VK_FORMAT_A1R5G5B5_UNORM_PACK16;
IMG_DATA_FORMAT_5_5_5_1 :Result:=VK_FORMAT_R5G5B5A1_UNORM_PACK16;
IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=VK_FORMAT_R8_UINT;
IMG_DATA_FORMAT_FMASK16_S16_F1:Result:=VK_FORMAT_R16_UINT;
IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=VK_FORMAT_R16_UINT;
IMG_DATA_FORMAT_FMASK32_S16_F2:Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=VK_FORMAT_R32_UINT;
IMG_DATA_FORMAT_FMASK64_S16_F4:Result:=VK_FORMAT_R64_UINT;
IMG_DATA_FORMAT_FMASK64_S16_F8:Result:=VK_FORMAT_R64_UINT;
else;
end;
IMG_NUM_FORMAT_FLOAT :
case PT^.dfmt of
IMG_DATA_FORMAT_16 :Result:=VK_FORMAT_R16_SFLOAT;
IMG_DATA_FORMAT_16_16 :Result:=VK_FORMAT_R16G16_SFLOAT;
IMG_DATA_FORMAT_16_16_16_16:Result:=VK_FORMAT_R16G16B16A16_SFLOAT;
IMG_DATA_FORMAT_32 :
if (not (iu_storage in hint)) and
IsTileModeDepth(PT^.tiling_idx) then
begin
Result:=VK_FORMAT_D32_SFLOAT;
end else
begin
Result:=VK_FORMAT_R32_SFLOAT;
end;
IMG_DATA_FORMAT_32_32 :Result:=VK_FORMAT_R32G32_SFLOAT;
IMG_DATA_FORMAT_32_32_32 :Result:=VK_FORMAT_R32G32B32_SFLOAT;
IMG_DATA_FORMAT_32_32_32_32:Result:=VK_FORMAT_R32G32B32A32_SFLOAT;
IMG_DATA_FORMAT_5_9_9_9 :Result:=VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;
IMG_DATA_FORMAT_10_11_11 :Result:=VK_FORMAT_B10G11R11_UFLOAT_PACK32;
IMG_DATA_FORMAT_11_11_10 :Result:=VK_FORMAT_R10G11B11_UFLOAT_FAKE32;
else;
end;
else;
end;
Assert(Result<>VK_FORMAT_UNDEFINED,'[_get_tsharp4_cformat] dfmt:'+_get_tex_dfmt_str(PT^.dfmt)+' nfmt:'+_get_tex_nfmt_str(PT^.nfmt));
end;
function _get_tsharp4_image_info(PT:PTSharpResource4;hint:s_image_usage):TvImageKey;
begin
Result:=Default(TvImageKey);
if (PT=nil) then Exit;
Result.Addr:=Pointer(QWORD(PT^.base) shl 8);
Result.cformat:=_get_tsharp4_cformat(PT,hint);
if (Result.cformat=VK_FORMAT_UNDEFINED) then
begin
Result.params.invalid:=1;
end;
Case PT^._type of
SQ_RSRC_IMG_1D,
SQ_RSRC_IMG_1D_ARRAY :Result.params.itype:=ord(VK_IMAGE_TYPE_1D);
SQ_RSRC_IMG_2D,
SQ_RSRC_IMG_2D_ARRAY,
SQ_RSRC_IMG_2D_MSAA,
SQ_RSRC_IMG_2D_MSAA_ARRAY:Result.params.itype:=ord(VK_IMAGE_TYPE_2D);
SQ_RSRC_IMG_3D :Result.params.itype:=ord(VK_IMAGE_TYPE_3D);
SQ_RSRC_IMG_CUBE :
begin
Result.params.itype:=ord(VK_IMAGE_TYPE_2D);
Result.params.cube :=1;
end;
else;
begin
Writeln(stderr,'Unknow tsharp4 type:0x'+HexStr(PT^._type,1));
Result.params.itype :=ord(VK_IMAGE_TYPE_2D);
Result.params.invalid:=1;
end;
end;
Result.params.pow2pad :=PT^.pow2pad;
Result.params.tiling.idx:=PT^.tiling_idx;
Result.params.tiling.alt:=0;
Result.params.width :=PT^.width +1;
Result.params.height :=PT^.height+1;
Result.params.depth :=1;
if _img_is_msaa(PT^._type) then
begin
Result.params.samples :=PT^.last_level+1;
Result.params.mipLevels:=1;
end else
begin
Result.params.samples :=1;
Result.params.mipLevels:=PT^.last_level+1;
end;
Result.params.arrayLayers:=1;
Result.params.pitch :=Result.params.width;
//TODO: Calculate padding by tilling mode
Result.params.pad_width :=Result.params.width;
Result.params.pad_height:=Result.params.height;
end;
function _get_tsharp8_image_info(PT:PTSharpResource8;hint:s_image_usage):TvImageKey;
begin
Result:=_get_tsharp4_image_info(PTSharpResource4(PT),hint);
//
Result.params.pitch:=PT^.pitch+1;
//
if (p_neomode<>0) then
begin
Result.params.tiling.alt:=PT^.alt_tile_mode;
end;
//
Case PT^._type of
SQ_RSRC_IMG_3D:
begin
Result.params.depth:=PT^.depth+1;
end;
else;
end;
//
Case PT^._type of
SQ_RSRC_IMG_CUBE,
SQ_RSRC_IMG_1D_ARRAY,
SQ_RSRC_IMG_2D_ARRAY,
SQ_RSRC_IMG_2D_MSAA_ARRAY:
begin
Result.params.arrayLayers:=PT^.last_array+1;
end;
else;
end;
end;
function _get_dst_sel_swizzle(b:Byte):Byte;
begin
Case b of
0:Result:=VK_SWIZZLE_Z;
1:Result:=VK_SWIZZLE_O;
4:Result:=VK_SWIZZLE_R;
5:Result:=VK_SWIZZLE_G;
6:Result:=VK_SWIZZLE_B;
7:Result:=VK_SWIZZLE_A;
else
Result:=VK_SWIZZLE_Z; //incorrect value is interpreted as 0
end;
end;
//perf_mod:bit3; //0=0/16, 1=2/16, 2=5/16, 3=7/16, 4=9/16, 5=11/16, 6=14/16, 7=16/16
//interlaced:bit1; //texture is interlaced
//tiling_idx:bit5; //index into lookup table of surface tiling settings
//pow2pad:bit1; //memory footprint is padded to power of 2 dimensions
function _get_lod(w:Word):TVkFloat; forward;
function RGBA_TO_BGRA(i:WORD):WORD; inline;
begin
//000F -> 0F00
//0F00 -> 000F
//MASK -> F0F0
//1234 -> 3412
Result:=
(RorWord(i,8) and $0F0F) or
(i and $F0F0);
end;
function BGRA_TO_ABGR(i:WORD):WORD; inline;
begin
Result:=RorWord(i,4);
end;
function _get_tsharp4_image_view(PT:PTSharpResource4;hint:s_image_usage):TvImageViewKey;
begin
Result:=Default(TvImageViewKey);
if (PT=nil) then Exit;
Result.cformat:=_get_tsharp4_cformat(PT,hint);
Case PT^._type of
SQ_RSRC_IMG_1D :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_1D);
SQ_RSRC_IMG_2D :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_2D);
SQ_RSRC_IMG_3D :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_3D);
SQ_RSRC_IMG_CUBE :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_CUBE);
SQ_RSRC_IMG_1D_ARRAY :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_1D_ARRAY);
SQ_RSRC_IMG_2D_ARRAY :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
SQ_RSRC_IMG_2D_MSAA :Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_2D);
SQ_RSRC_IMG_2D_MSAA_ARRAY:Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
else
begin
Writeln(stderr,'Unknow tsharp4 type:0x'+HexStr(PT^._type,1));
Result.vtype :=ord(VK_IMAGE_VIEW_TYPE_2D);
Result.invalid:=1;
end;
end;
Result.dstSel.x:=_get_dst_sel_swizzle(PT^.dst_sel_x);
Result.dstSel.y:=_get_dst_sel_swizzle(PT^.dst_sel_y);
Result.dstSel.z:=_get_dst_sel_swizzle(PT^.dst_sel_z);
Result.dstSel.w:=_get_dst_sel_swizzle(PT^.dst_sel_w);
Case Result.cformat of
VK_FORMAT_R5G6B5_UNORM_PACK16:
begin
//real -> B5G6R5
WORD(Result.dstSel):=RGBA_TO_BGRA(WORD(Result.dstSel));
end;
VK_FORMAT_B4G4R4A4_UNORM_PACK16:
begin
//real -> A4B4G4R4
WORD(Result.dstSel):=BGRA_TO_ABGR(WORD(Result.dstSel));
end
else;
end;
if not _img_is_msaa(PT^._type) then
begin
Result.base_level:=PT^.base_level;
Result.last_level:=PT^.last_level;
end;
Result.minLod:=_get_lod(PT^.min_lod);
//Result.base_level:=0; /////
//Result.last_level:=0; /////
end;
function _get_tsharp8_image_view(PT:PTSharpResource8;hint:s_image_usage):TvImageViewKey;
begin
Result:=_get_tsharp4_image_view(PTSharpResource4(PT),hint);
//
Case PT^._type of
SQ_RSRC_IMG_CUBE:
begin
Result.base_array:=PT^.base_array;
Result.last_array:=PT^.last_array;
//
if (Result.last_array-Result.base_array)>5 then
begin
Result.vtype:=ord(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
end;
end;
SQ_RSRC_IMG_1D_ARRAY ,
SQ_RSRC_IMG_2D_ARRAY ,
SQ_RSRC_IMG_2D_MSAA_ARRAY:
begin
Result.base_array:=PT^.base_array;
Result.last_array:=PT^.last_array;
end;
else;
end;
//
end;
function _get_xy_filter(b:Byte):TVkFilter;
begin
Case b of
TEX_XYFilter_Point :Result:=VK_FILTER_NEAREST;
TEX_XYFilter_Linear :Result:=VK_FILTER_LINEAR;
TEX_XYFilter_AnisoPoint :Result:=VK_FILTER_NEAREST;
TEX_XYFilter_AnisoLinear:Result:=VK_FILTER_LINEAR;
else
Result:=VK_FILTER_NEAREST;
end;
end;
function _get_mip_filter(b:Byte):TVkSamplerMipmapMode;
begin
Case b of
TEX_MipFilter_None :Result:=VK_SAMPLER_MIPMAP_MODE_NEAREST;
TEX_MipFilter_Point :Result:=VK_SAMPLER_MIPMAP_MODE_NEAREST;
TEX_MipFilter_Linear :Result:=VK_SAMPLER_MIPMAP_MODE_LINEAR;
TEX_MipFilter_Point_Aniso_Adj:Result:=VK_SAMPLER_MIPMAP_MODE_NEAREST;
else
Result:=VK_SAMPLER_MIPMAP_MODE_NEAREST;
end;
end;
function _get_clamp(b:Byte):TVkSamplerAddressMode;
begin
Case b of
SQ_TEX_WRAP :Result:=VK_SAMPLER_ADDRESS_MODE_REPEAT;
SQ_TEX_MIRROR :Result:=VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
SQ_TEX_CLAMP_LAST_TEXEL :Result:=VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
SQ_TEX_MIRROR_ONCE_LAST_TEXEL :Result:=VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
SQ_TEX_CLAMP_HALF_BORDER :Result:=VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
SQ_TEX_MIRROR_ONCE_HALF_BORDER:Result:=VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
SQ_TEX_CLAMP_BORDER :Result:=VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
SQ_TEX_MIRROR_ONCE_BORDER :Result:=VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
else
Result:=VK_SAMPLER_ADDRESS_MODE_REPEAT;
end;
end;
function _get_lod_bias(bias:word;sec:Byte):TVkFloat;
var
b,s:TVkFloat;
begin
with Tlod_bias_bits(bias) do
begin
b:=(-1*sign)+int+(frac/256);
end;
with Tlod_bias_sec_bits(sec) do
begin
s:=(-1*sign)+int+(frac/16);
end;
Result:=b+s;
end;
function _is_aniso_enabled(mag_filter,min_filter:Byte):TVkBool32;
begin
Result:=ord((mag_filter=TEX_XYFilter_AnisoPoint) or
(mag_filter=TEX_XYFilter_AnisoLinear) or
(min_filter=TEX_XYFilter_AnisoPoint) or
(min_filter=TEX_XYFilter_AnisoLinear));
end;
function _get_aniso_ratio(max_aniso_ratio:Byte):TVkFloat;
begin
Case max_aniso_ratio of
SQ_TEX_ANISO_RATIO_1 :Result:=1;
SQ_TEX_ANISO_RATIO_2 :Result:=2;
SQ_TEX_ANISO_RATIO_4 :Result:=4;
SQ_TEX_ANISO_RATIO_8 :Result:=8;
SQ_TEX_ANISO_RATIO_16:Result:=16;
else
Result:=0;
end;
end;
function _get_lod(w:Word):TVkFloat;
begin
with Tlod_bits(w) do
begin
Result:=int+(frac/256);
end;
end;
//aniso_threshold:bit3; //Threshold before sampling anisotropically (enum)
//mc_coord_trunc:bit1;
//force_degamma:bit1; //Force de-gamma after filtering regardless of format
//aniso_bias:bit6; //Anisotropy bias factor; unsigned fixed point 1.5
//trunc_coord:bit1;
//disable_cube_wrap:bit1; //Disable sampling/filtering across face boundaries
//filter_mode:bit2; //LERP, min, or max filter; default: LERP
//perf_mip:bit4; //Bri-linear factor
//perf_z:bit4;
//z_filter:bit2; //Filter in Z coordinate direction for volume textures
//border_color_ptr:bit12; //Offset into global border color buffer
//border_color_type:bit2; //Opaque-black, transparent-black, white, or color ptr
//VkSamplerCustomBorderColorCreateInfoEXT
function _get_border_color(color_type:Byte):TVkBorderColor;
begin
Case color_type of
TEX_BorderColor_TransparentBlack:Result:=VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; //VK_BORDER_COLOR_INT_TRANSPARENT_BLACK
TEX_BorderColor_OpaqueBlack :Result:=VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; //VK_BORDER_COLOR_INT_OPAQUE_BLACK
TEX_BorderColor_OpaqueWhite :Result:=VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; //VK_BORDER_COLOR_INT_OPAQUE_WHITE
TEX_BorderColor_Register :Result:=VK_BORDER_COLOR_FLOAT_CUSTOM_EXT; //VK_BORDER_COLOR_INT_CUSTOM_EXT
else
Result:=VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
end;
end;
function _get_ssharp_info(PS:PSSharpResource4):TVkSamplerCreateInfo;
begin
Result:=Default(TVkSamplerCreateInfo);
if (PS=nil) then Exit;
Result.sType:=VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
Result.magFilter:=_get_xy_filter(PS^.xy_mag_filter);
Result.minFilter:=_get_xy_filter(PS^.xy_min_filter);
Result.mipmapMode:=_get_mip_filter(PS^.mip_filter);
Result.addressModeU:=_get_clamp(PS^.clamp_x);
Result.addressModeV:=_get_clamp(PS^.clamp_y);
Result.addressModeW:=_get_clamp(PS^.clamp_z);
Result.mipLodBias:=_get_lod_bias(PS^.lod_bias,PS^.lod_bias_sec);
Result.anisotropyEnable:=_is_aniso_enabled(PS^.xy_mag_filter,PS^.xy_min_filter);
Result.maxAnisotropy:=_get_aniso_ratio(PS^.max_aniso_ratio);
Result.compareEnable:=ord(PS^.depth_compare_func<>SQ_TEX_DEPTH_COMPARE_NEVER);
Result.compareOp :=TVkCompareOp(PS^.depth_compare_func); //1:1
Result.minLod:=_get_lod(PS^.min_lod);
Result.maxLod:=_get_lod(PS^.max_lod);
Result.borderColor:=_get_border_color(PS^.border_color_type);
Result.unnormalizedCoordinates:=PS^.force_unorm_coords;
end;
end.