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 (ab) 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); Assert(CX_REG^.CB_COLOR_CONTROL.DEGAMMA_ENABLE=0,'DEGAMMA_ENABLE'); 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.invalid :=1; 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 or TM_READ; 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 or TM_READ; 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; label _unorm, _srgb; 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 : begin if (iu_degamma in hint) then begin goto _srgb; end; _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; end; IMG_NUM_FORMAT_SRGB : begin _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_BC7 :Result:=VK_FORMAT_BC7_SRGB_BLOCK; else begin goto _unorm; end; end; 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 //convert Cube to array of 2D slices Result.params.itype:=ord(VK_IMAGE_TYPE_2D); 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_2D_ARRAY); //convert Cube to array of 2D slices 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 , //convert Cube to array of 2D slices 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; //enables bilinear blend fraction truncation to 1 bit for motioncompensation //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.