mirror of https://github.com/red-prig/fpPS4.git
2734 lines
90 KiB
Plaintext
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.
|
|
|