mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-26 16:10:25 +00:00
969 lines
21 KiB
ObjectPascal
969 lines
21 KiB
ObjectPascal
unit vShaderExt;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes,
|
|
SysUtils,
|
|
ps4_shader,
|
|
ps4_gpu_regs,
|
|
Vulkan,
|
|
vDevice,
|
|
vPipeline,
|
|
vShader,
|
|
vImage,
|
|
vSetLayoutManager,
|
|
vPipelineLayoutManager{,
|
|
vSetsPoolManager};
|
|
|
|
|
|
type
|
|
TvResourceType=(
|
|
vtRoot,
|
|
vtBufPtr2,
|
|
vtFunPtr2,
|
|
vtVSharp4,
|
|
vtSSharp4,
|
|
vtTSharp4,
|
|
vtTSharp8
|
|
);
|
|
|
|
TvDataLayout=packed record
|
|
rtype:TvResourceType;
|
|
parent:DWORD;
|
|
offset:DWORD;
|
|
end;
|
|
|
|
ADataLayout=array of TvDataLayout;
|
|
|
|
TvFuncCb=procedure(addr:ADataLayout) of object;
|
|
|
|
TvCustomLayout=packed record
|
|
dtype:DWORD;
|
|
bind:DWORD;
|
|
size:DWORD;
|
|
offset:DWORD;
|
|
addr:ADataLayout;
|
|
end;
|
|
|
|
ACustomLayout=array of TvCustomLayout;
|
|
|
|
TvCustomLayoutCb=procedure(const L:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD) of object;
|
|
|
|
TvShaderExt=class(TvShader)
|
|
FDescSetId:Integer;
|
|
|
|
FSetLayout:TvSetLayout;
|
|
|
|
FDataLayouts:ADataLayout;
|
|
FVertLayouts:ACustomLayout;
|
|
FUnifLayouts:ACustomLayout;
|
|
|
|
FPushConst:TvCustomLayout;
|
|
|
|
procedure ClearInfo; override;
|
|
procedure InitSetLayout;
|
|
procedure AddToPipeline(p:TvPipelineLayout);
|
|
procedure OnDescriptorSet(var Target,id:DWORD); override;
|
|
procedure OnSourceExtension(P:PChar); override;
|
|
Procedure AddDataLayout(rtype:TvResourceType;parent,offset:DWORD);
|
|
procedure OnDataLayout(P:PChar);
|
|
Procedure EnumFuncLayout(cb:TvFuncCb);
|
|
function GetLayoutAddr(parent:DWORD):ADataLayout;
|
|
Procedure AddVertLayout(parent,bind:DWORD);
|
|
procedure OnVertLayout(P:PChar);
|
|
Procedure EnumVertLayout(cb:TvCustomLayoutCb;Fset:TVkUInt32;FData:PDWORD);
|
|
Procedure AddBuffLayout(dtype:TVkDescriptorType;parent,bind,size,offset:DWORD);
|
|
Procedure SetPushConst(parent,size:DWORD);
|
|
procedure OnBuffLayout(P:PChar);
|
|
Function GetPushConstData(pUserData:Pointer):Pointer;
|
|
Procedure AddUnifLayout(dtype:TVkDescriptorType;parent,bind:DWORD);
|
|
procedure OnUnifLayout(P:PChar);
|
|
Procedure EnumUnifLayout(cb:TvCustomLayoutCb;Fset:TVkUInt32;FData:PDWORD);
|
|
end;
|
|
|
|
TvShaderStage=(
|
|
vShaderStageLs,
|
|
vShaderStageHs,
|
|
vShaderStageEs,
|
|
vShaderStageGs,
|
|
vShaderStageVs,
|
|
vShaderStagePs,
|
|
vShaderStageCs
|
|
);
|
|
|
|
AvShaderStage=array[TvShaderStage] of TvShaderExt;
|
|
|
|
PvShadersKey=^TvShadersKey;
|
|
TvShadersKey=object
|
|
FShaders:AvShaderStage;
|
|
Procedure SetLSShader(Shader:TvShaderExt);
|
|
Procedure SetHSShader(Shader:TvShaderExt);
|
|
Procedure SetESShader(Shader:TvShaderExt);
|
|
Procedure SetGSShader(Shader:TvShaderExt);
|
|
Procedure SetVSShader(Shader:TvShaderExt);
|
|
Procedure SetPSShader(Shader:TvShaderExt);
|
|
Procedure SetCSShader(Shader:TvShaderExt);
|
|
procedure ExportLayout(var A:AvSetLayout;var B:AvPushConstantRange);
|
|
Procedure ExportStages(Stages:PVkPipelineShaderStageCreateInfo;stageCount:PVkUInt32);
|
|
end;
|
|
|
|
TvShaderGroup=class
|
|
FKey:TvShadersKey;
|
|
FLayout:TvPipelineLayout;
|
|
Procedure Clear;
|
|
Function Compile:Boolean;
|
|
end;
|
|
|
|
TAttrBindExt=packed object
|
|
min_addr:Pointer;
|
|
binding:TVkUInt32;
|
|
stride:TVkUInt32;
|
|
count:TVkUInt32;
|
|
Function GetSize:TVkUInt32;
|
|
end;
|
|
|
|
TvAttrBuilder=object
|
|
FBindDescs:array of TVkVertexInputBindingDescription;
|
|
FAttrDescs:array of TVkVertexInputAttributeDescription;
|
|
FBindExt:array of TAttrBindExt;
|
|
function NewBindDesc(binding,stride:TVkUInt32):TVkUInt32;
|
|
procedure NewAttrDesc(location,binding,offset:TVkUInt32;format:TVkFormat);
|
|
procedure PatchAttr(binding,offset:TVkUInt32);
|
|
Procedure AddVSharp(PV:PVSharpResource4;location:DWord);
|
|
procedure AddAttr(const v:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
end;
|
|
|
|
TBufBindExt=packed record
|
|
fset:TVkUInt32;
|
|
bind:TVkUInt32;
|
|
offset:TVkUInt32;
|
|
|
|
addr:Pointer;
|
|
size:TVkUInt32;
|
|
end;
|
|
|
|
TImageBindExt=packed record
|
|
fset:TVkUInt32;
|
|
bind:TVkUInt32;
|
|
|
|
FImage:TvImageKey;
|
|
FView:TvImageViewKey;
|
|
end;
|
|
|
|
TSamplerBindExt=packed record
|
|
fset:TVkUInt32;
|
|
bind:TVkUInt32;
|
|
|
|
PS:PSSharpResource4;
|
|
end;
|
|
|
|
TvUniformBuilder=object
|
|
FBuffers :array of TBufBindExt;
|
|
FImages :array of TImageBindExt;
|
|
FSamplers:array of TSamplerBindExt;
|
|
|
|
Procedure AddVSharp(PV:PVSharpResource4;fset,bind,offset:DWord);
|
|
Procedure AddBufPtr(P:Pointer;fset,size,bind,offset:DWord);
|
|
|
|
Procedure AddTSharp4(PT:PTSharpResource4;fset,bind:DWord);
|
|
Procedure AddTSharp8(PT:PTSharpResource8;fset,bind:DWord);
|
|
Procedure AddSSharp4(PS:PSSharpResource4;fset,bind:DWord);
|
|
procedure AddAttr(const b:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
end;
|
|
|
|
TvBufOffsetChecker=object
|
|
FResult:Boolean;
|
|
procedure AddAttr(const b:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
end;
|
|
|
|
TvFuncLayout=object
|
|
FList:array of ADataLayout;
|
|
Procedure Add(addr:ADataLayout);
|
|
end;
|
|
|
|
function GetSharpByPatch(pData:Pointer;addr:ADataLayout):Pointer;
|
|
|
|
implementation
|
|
|
|
Function TAttrBindExt.GetSize:TVkUInt32;
|
|
begin
|
|
if (stride=0) then
|
|
begin
|
|
Result:=count;
|
|
end else
|
|
begin
|
|
Result:=stride*count;
|
|
end;
|
|
end;
|
|
|
|
procedure TvShaderExt.ClearInfo;
|
|
begin
|
|
inherited;
|
|
FSetLayout:=nil;
|
|
|
|
FDataLayouts:=Default(ADataLayout);
|
|
FVertLayouts:=Default(ACustomLayout);
|
|
FUnifLayouts:=Default(ACustomLayout);
|
|
|
|
FPushConst:=Default(TvCustomLayout);
|
|
end;
|
|
|
|
procedure TvShaderExt.InitSetLayout;
|
|
var
|
|
i:Integer;
|
|
A:AVkDescriptorSetLayoutBinding;
|
|
begin
|
|
if (FSetLayout<>nil) then Exit;
|
|
A:=Default(AVkDescriptorSetLayoutBinding);
|
|
SetLength(A,Length(FUnifLayouts)); //++ other todo
|
|
|
|
if (Length(FUnifLayouts)<>0) then
|
|
For i:=0 to High(FUnifLayouts) do
|
|
begin
|
|
A[i]:=Default(TVkDescriptorSetLayoutBinding);
|
|
A[i].binding :=FUnifLayouts[i].bind;
|
|
A[i].descriptorType :=TVkDescriptorType(FUnifLayouts[i].dtype);
|
|
A[i].descriptorCount:=1;
|
|
A[i].stageFlags :=ord(FStage);
|
|
end;
|
|
|
|
FSetLayout:=FetchSetLayout(ord(FStage),0,A);
|
|
end;
|
|
|
|
procedure TvShaderExt.AddToPipeline(p:TvPipelineLayout);
|
|
begin
|
|
InitSetLayout;
|
|
|
|
p.AddLayout(FSetLayout);
|
|
if (FPushConst.size<>0) then
|
|
begin
|
|
p.AddPushConst(0,FPushConst.size,ord(FStage));
|
|
end;
|
|
end;
|
|
|
|
procedure TvShaderExt.OnDescriptorSet(var Target,id:DWORD);
|
|
begin
|
|
if (FDescSetId>=0) then id:=FDescSetId;
|
|
end;
|
|
|
|
function _get_hex_dword(P:PChar):DWord;
|
|
var
|
|
Error:word;
|
|
s:string[9];
|
|
begin
|
|
s[0]:=#9;
|
|
s[1]:='$';
|
|
PQWORD(@s[2])^:=PQWORD(P)^;
|
|
Result:=0;
|
|
Val(s,Result,Error);
|
|
end;
|
|
|
|
//0123456789ABCDEF0123456789ABCDEF012345678
|
|
//#B;PID=00000000;OFS=00000000
|
|
//VA;PID=00000004;BND=00000000
|
|
//BP;PID=00000003;BND=00000000;LEN=00000040
|
|
//UI;PID=00000001;BND=00000000
|
|
//US;PID=00000002;BND=00000001
|
|
|
|
procedure TvShaderExt.OnSourceExtension(P:PChar);
|
|
begin
|
|
//Writeln(P);
|
|
Case P^ of
|
|
'#':OnDataLayout(P);
|
|
'V':OnVertLayout(P);
|
|
'B':OnBuffLayout(P);
|
|
'U':OnUnifLayout(P);
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShaderExt.AddDataLayout(rtype:TvResourceType;parent,offset:DWORD);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(FDataLayouts);
|
|
SetLength(FDataLayouts,i+1);
|
|
FDataLayouts[i].rtype :=rtype;
|
|
FDataLayouts[i].parent:=parent;
|
|
FDataLayouts[i].offset:=offset;
|
|
end;
|
|
|
|
procedure TvShaderExt.OnDataLayout(P:PChar);
|
|
begin
|
|
Case P[1] of
|
|
'R':AddDataLayout(vtRoot ,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'B':AddDataLayout(vtBufPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'F':AddDataLayout(vtFunPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'V':AddDataLayout(vtVSharp4,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'S':AddDataLayout(vtSSharp4,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
't':AddDataLayout(vtTSharp4,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'T':AddDataLayout(vtTSharp8,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShaderExt.EnumFuncLayout(cb:TvFuncCb);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
if (Length(FDataLayouts)=0) then Exit;
|
|
For i:=0 to High(FDataLayouts) do
|
|
if (FDataLayouts[i].rtype=vtFunPtr2) then
|
|
begin
|
|
cb(GetLayoutAddr(i));
|
|
end;
|
|
end;
|
|
|
|
function TvShaderExt.GetLayoutAddr(parent:DWORD):ADataLayout;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
Result:=Default(ADataLayout);
|
|
repeat
|
|
if (parent>=Length(FDataLayouts)) then
|
|
begin
|
|
SetLength(Result,0);
|
|
Break;
|
|
end;
|
|
i:=Length(Result);
|
|
SetLength(Result,i+1);
|
|
Result[i]:=FDataLayouts[parent];
|
|
if (parent=0) then Break;
|
|
parent:=FDataLayouts[parent].parent;
|
|
until false;
|
|
end;
|
|
|
|
Procedure AddToCustomLayout(var A:ACustomLayout;const v:TvCustomLayout);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(A);
|
|
SetLength(A,i+1);
|
|
A[i]:=v;
|
|
end;
|
|
|
|
Procedure TvShaderExt.AddVertLayout(parent,bind:DWORD);
|
|
var
|
|
v:TvCustomLayout;
|
|
begin
|
|
v:=Default(TvCustomLayout);
|
|
v.bind:=bind;
|
|
v.addr:=GetLayoutAddr(parent);
|
|
|
|
AddToCustomLayout(FVertLayouts,v);
|
|
end;
|
|
|
|
procedure TvShaderExt.OnVertLayout(P:PChar);
|
|
begin
|
|
Case P[1] of
|
|
'A':AddVertLayout(_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShaderExt.EnumVertLayout(cb:TvCustomLayoutCb;Fset:TVkUInt32;FData:PDWORD);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
if (Length(FVertLayouts)=0) then Exit;
|
|
For i:=0 to High(FVertLayouts) do
|
|
begin
|
|
cb(FVertLayouts[i],Fset,FData);
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShaderExt.AddBuffLayout(dtype:TVkDescriptorType;parent,bind,size,offset:DWORD);
|
|
var
|
|
v:TvCustomLayout;
|
|
begin
|
|
if (dtype=VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) then
|
|
begin
|
|
if (size>$FFFF) then //max UBO
|
|
begin
|
|
dtype:=VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
end else
|
|
begin
|
|
dtype:=VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
end;
|
|
end;
|
|
|
|
v:=Default(TvCustomLayout);
|
|
v.dtype:=ord(dtype);
|
|
v.bind:=bind;
|
|
v.size:=size;
|
|
v.offset:=offset;
|
|
v.addr:=GetLayoutAddr(parent);
|
|
|
|
AddToCustomLayout(FUnifLayouts,v);
|
|
end;
|
|
|
|
Procedure TvShaderExt.SetPushConst(parent,size:DWORD);
|
|
begin
|
|
FPushConst:=Default(TvCustomLayout);
|
|
FPushConst.size:=size;
|
|
FPushConst.addr:=GetLayoutAddr(parent)
|
|
end;
|
|
|
|
//BS;PID=00000002;BND=00000001;LEN=FFFFFFFF;OFS=00000000"
|
|
//0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
|
|
//0 1 2
|
|
procedure TvShaderExt.OnBuffLayout(P:PChar);
|
|
begin
|
|
Case P[1] of
|
|
'P':SetPushConst(_get_hex_dword(@P[7]),_get_hex_dword(@P[$21]));
|
|
'U':AddBuffLayout(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
_get_hex_dword(@P[7]),
|
|
_get_hex_dword(@P[$14]),
|
|
_get_hex_dword(@P[$21]),
|
|
_get_hex_dword(@P[$2E]));
|
|
'S':AddBuffLayout(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
_get_hex_dword(@P[7]),
|
|
_get_hex_dword(@P[$14]),
|
|
_get_hex_dword(@P[$21]),
|
|
_get_hex_dword(@P[$2E]));
|
|
end;
|
|
end;
|
|
|
|
Function TvShaderExt.GetPushConstData(pUserData:Pointer):Pointer;
|
|
begin
|
|
Result:=nil;
|
|
if (pUserData=nil) then Exit;
|
|
if (FPushConst.size=0) then Exit;
|
|
Result:=GetSharpByPatch(pUserData,FPushConst.addr);
|
|
|
|
if (Result=nil) then Exit;
|
|
|
|
Case FPushConst.addr[0].rtype of
|
|
vtVSharp4:Result:=Pointer(PVSharpResource4(Result)^.base);
|
|
vtTSharp4,
|
|
vtTSharp8:Result:=Pointer(PTSharpResource4(Result)^.base shl 8);
|
|
else;
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure TvShaderExt.AddUnifLayout(dtype:TVkDescriptorType;parent,bind:DWORD);
|
|
var
|
|
v:TvCustomLayout;
|
|
begin
|
|
v:=Default(TvCustomLayout);
|
|
v.dtype:=ord(dtype);
|
|
v.bind:=bind;
|
|
v.addr:=GetLayoutAddr(parent);
|
|
|
|
AddToCustomLayout(FUnifLayouts,v);
|
|
end;
|
|
|
|
procedure TvShaderExt.OnUnifLayout(P:PChar);
|
|
begin
|
|
Case P[1] of
|
|
'I':AddUnifLayout(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
'S':AddUnifLayout(VK_DESCRIPTOR_TYPE_SAMPLER ,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShaderExt.EnumUnifLayout(cb:TvCustomLayoutCb;Fset:TVkUInt32;FData:PDWORD);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if (cb=nil) then Exit;
|
|
if (Length(FUnifLayouts)=0) then Exit;
|
|
For i:=0 to High(FUnifLayouts) do
|
|
begin
|
|
cb(FUnifLayouts[i],Fset,FData);
|
|
end;
|
|
end;
|
|
|
|
///
|
|
|
|
function GetSharpByPatch(pData:Pointer;addr:ADataLayout):Pointer;
|
|
var
|
|
i:Integer;
|
|
pSharp:Pointer;
|
|
begin
|
|
Result:=nil;
|
|
if (Length(addr)=0) then Exit;
|
|
|
|
pSharp:=pData;
|
|
|
|
For i:=High(addr) downto 0 do
|
|
begin
|
|
pData:=pData+addr[i].offset;
|
|
|
|
Case addr[i].rtype of
|
|
vtRoot:
|
|
begin
|
|
pSharp:=pData;
|
|
end;
|
|
vtBufPtr2:
|
|
begin
|
|
pData:=Pointer(PPtrUint(pData)^ and (not 3));
|
|
pSharp:=pData;
|
|
end;
|
|
vtVSharp4:
|
|
begin
|
|
pSharp:=pData;
|
|
pData:=Pointer(PVSharpResource4(pData)^.base);
|
|
end;
|
|
vtSSharp4:
|
|
begin
|
|
pSharp:=pData;
|
|
Break;
|
|
end;
|
|
vtTSharp4,
|
|
vtTSharp8:
|
|
begin
|
|
pSharp:=pData;
|
|
pData:=Pointer(PTSharpResource4(pData)^.base shl 8);
|
|
end;
|
|
else
|
|
Assert(false);
|
|
end;
|
|
|
|
end;
|
|
|
|
Result:=pSharp;
|
|
end;
|
|
|
|
//
|
|
|
|
function TvAttrBuilder.NewBindDesc(binding,stride:TVkUInt32):TVkUInt32;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(FBindDescs);
|
|
SetLength(FBindDescs,i+1);
|
|
FBindDescs[i]:=Default(TVkVertexInputBindingDescription);
|
|
FBindDescs[i].binding :=binding;
|
|
FBindDescs[i].stride :=stride;
|
|
FBindDescs[i].inputRate:=VK_VERTEX_INPUT_RATE_VERTEX;
|
|
Result:=i;
|
|
end;
|
|
|
|
procedure TvAttrBuilder.NewAttrDesc(location,binding,offset:TVkUInt32;format:TVkFormat);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(FAttrDescs);
|
|
SetLength(FAttrDescs,i+1);
|
|
FAttrDescs[i].location:=location;
|
|
FAttrDescs[i].binding :=binding ;
|
|
FAttrDescs[i].format :=format ;
|
|
FAttrDescs[i].offset :=offset ;
|
|
end;
|
|
|
|
procedure TvAttrBuilder.PatchAttr(binding,offset:TVkUInt32);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if Length(FAttrDescs)<>0 then
|
|
For i:=0 to High(FAttrDescs) do
|
|
if (FAttrDescs[i].binding=binding) then
|
|
begin
|
|
FAttrDescs[i].offset:=FAttrDescs[i].offset+offset;
|
|
end;
|
|
end;
|
|
|
|
function _ptr_diff(p1,p2:Pointer):TVkUInt32;
|
|
begin
|
|
if (p1>p2) then
|
|
Result:=p1-p2
|
|
else
|
|
Result:=p2-p1;
|
|
end;
|
|
|
|
Procedure TvAttrBuilder.AddVSharp(PV:PVSharpResource4;location:DWord);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
if (PV=nil) then Exit;
|
|
|
|
if Length(FBindExt)<>0 then
|
|
For i:=0 to High(FBindExt) do
|
|
With FBindExt[i] do
|
|
if (stride=PV^.stride) then
|
|
if (_ptr_diff(min_addr,Pointer(PV^.base))<=stride-1) then
|
|
begin
|
|
if (min_addr>Pointer(PV^.base)) then
|
|
begin
|
|
PatchAttr(binding,min_addr-Pointer(PV^.base));
|
|
min_addr:=Pointer(PV^.base);
|
|
end;
|
|
if (count<PV^.num_records) then
|
|
begin
|
|
count:=PV^.num_records;
|
|
end;
|
|
NewAttrDesc(location,binding,Pointer(PV^.base)-min_addr,_get_vsharp_cformat(PV));
|
|
Exit;
|
|
end;
|
|
|
|
i:=Length(FBindExt);
|
|
SetLength(FBindExt,i+1);
|
|
FBindExt[i]:=Default(TAttrBindExt);
|
|
|
|
FBindExt[i].min_addr:=Pointer(PV^.base);
|
|
FBindExt[i].binding :=i;
|
|
FBindExt[i].stride :=PV^.stride;
|
|
FBindExt[i].count :=PV^.num_records;
|
|
|
|
NewBindDesc(i,PV^.stride);
|
|
|
|
NewAttrDesc(location,i,0,_get_vsharp_cformat(PV));
|
|
|
|
end;
|
|
|
|
procedure TvAttrBuilder.AddAttr(const v:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
var
|
|
PV:PVSharpResource4;
|
|
begin
|
|
PV:=GetSharpByPatch(FData,v.addr);
|
|
//print_vsharp(PV);
|
|
AddVSharp(PV,v.bind);
|
|
end;
|
|
|
|
//
|
|
|
|
Procedure TvUniformBuilder.AddVSharp(PV:PVSharpResource4;fset,bind,offset:DWord);
|
|
var
|
|
b:TBufBindExt;
|
|
i,stride,num_records:Integer;
|
|
begin
|
|
Assert(PV<>nil);
|
|
if (PV=nil) then Exit;
|
|
|
|
//print_vsharp(PV);
|
|
|
|
b:=Default(TBufBindExt);
|
|
b.fset:=fset;
|
|
b.bind:=bind;
|
|
b.offset:=offset;
|
|
|
|
b.addr:=Pointer(PV^.base);
|
|
|
|
stride:=PV^.stride;
|
|
num_records:=PV^.num_records;
|
|
if (stride=0) then stride:=1;
|
|
if (num_records=0) then num_records:=1;
|
|
b.size:=stride*num_records;
|
|
|
|
i:=Length(FBuffers);
|
|
SetLength(FBuffers,i+1);
|
|
FBuffers[i]:=b;
|
|
end;
|
|
|
|
Procedure TvUniformBuilder.AddBufPtr(P:Pointer;fset,size,bind,offset:DWord);
|
|
var
|
|
b:TBufBindExt;
|
|
i:Integer;
|
|
begin
|
|
Assert(P<>nil);
|
|
if (P=nil) or (size=0) then Exit;
|
|
|
|
b:=Default(TBufBindExt);
|
|
b.fset:=fset;
|
|
b.bind:=bind;
|
|
b.offset:=offset;
|
|
|
|
b.addr:=P;
|
|
b.size:=size;
|
|
|
|
i:=Length(FBuffers);
|
|
SetLength(FBuffers,i+1);
|
|
FBuffers[i]:=b;
|
|
end;
|
|
|
|
Procedure TvUniformBuilder.AddTSharp4(PT:PTSharpResource4;fset,bind:DWord);
|
|
var
|
|
b:TImageBindExt;
|
|
i:Integer;
|
|
begin
|
|
Assert(PT<>nil);
|
|
if (PT=nil) then Exit;
|
|
|
|
//print_tsharp4(PT);
|
|
|
|
b:=Default(TImageBindExt);
|
|
b.fset:=fset;
|
|
b.bind:=bind;
|
|
|
|
b.FImage:=_get_tsharp4_image_info(PT);
|
|
b.FView :=_get_tsharp4_image_view(PT);
|
|
|
|
i:=Length(FImages);
|
|
SetLength(FImages,i+1);
|
|
FImages[i]:=b;
|
|
end;
|
|
|
|
Procedure TvUniformBuilder.AddTSharp8(PT:PTSharpResource8;fset,bind:DWord);
|
|
var
|
|
b:TImageBindExt;
|
|
i:Integer;
|
|
begin
|
|
Assert(PT<>nil);
|
|
if (PT=nil) then Exit;
|
|
|
|
//print_tsharp8(PT);
|
|
|
|
b:=Default(TImageBindExt);
|
|
b.fset:=fset;
|
|
b.bind:=bind;
|
|
|
|
b.FImage:=_get_tsharp8_image_info(PT);
|
|
b.FView :=_get_tsharp8_image_view(PT);
|
|
|
|
i:=Length(FImages);
|
|
SetLength(FImages,i+1);
|
|
FImages[i]:=b;
|
|
end;
|
|
|
|
procedure TvUniformBuilder.AddAttr(const b:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
var
|
|
P:Pointer;
|
|
begin
|
|
P:=GetSharpByPatch(FData,b.addr);
|
|
Assert(P<>nil);
|
|
if (P=nil) then Exit;
|
|
|
|
Case TVkDescriptorType(b.dtype) of
|
|
VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
Case b.addr[0].rtype of
|
|
vtSSharp4:AddSSharp4(P,fset,b.bind);
|
|
else
|
|
Assert(false);
|
|
end;
|
|
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
Case b.addr[0].rtype of
|
|
vtTSharp4:AddTSharp4(P,fset,b.bind);
|
|
vtTSharp8:AddTSharp8(P,fset,b.bind);
|
|
else
|
|
Assert(false);
|
|
end;
|
|
//VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER=4,
|
|
//VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER=5,
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
Case b.addr[0].rtype of
|
|
vtRoot,
|
|
vtBufPtr2:AddBufPtr(P,Fset,b.size,b.bind,b.offset);
|
|
vtVSharp4:AddVSharp(P,Fset,b.bind,b.offset);
|
|
else
|
|
Assert(false);
|
|
end;
|
|
|
|
else
|
|
Assert(false);
|
|
end;
|
|
|
|
//Writeln('----');
|
|
end;
|
|
|
|
function AlignShift(addr:Pointer;alignment:PtrUInt):PtrUInt; inline;
|
|
begin
|
|
if (alignment>1) then
|
|
begin
|
|
Result:=(PtrUInt(addr) mod alignment);
|
|
end else
|
|
begin
|
|
Result:=0;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvUniformBuilder.AddSSharp4(PS:PSSharpResource4;fset,bind:DWord);
|
|
var
|
|
b:TSamplerBindExt;
|
|
i:Integer;
|
|
begin
|
|
Assert(PS<>nil);
|
|
if (PS=nil) then Exit;
|
|
|
|
//print_ssharp4(PS);
|
|
|
|
b:=Default(TSamplerBindExt);
|
|
b.fset:=fset;
|
|
b.bind:=bind;
|
|
b.PS:=PS;
|
|
|
|
i:=Length(FSamplers);
|
|
SetLength(FSamplers,i+1);
|
|
FSamplers[i]:=b;
|
|
end;
|
|
|
|
//
|
|
|
|
Procedure TvShadersKey.SetLSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_VERTEX_BIT) then
|
|
FShaders[vShaderStageLs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetHSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) then
|
|
FShaders[vShaderStageHs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetESShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) then
|
|
FShaders[vShaderStageEs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetGSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_GEOMETRY_BIT) then
|
|
FShaders[vShaderStageGs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetVSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_VERTEX_BIT) then
|
|
FShaders[vShaderStageVs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetPSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_FRAGMENT_BIT) then
|
|
FShaders[vShaderStagePs]:=Shader;
|
|
end;
|
|
|
|
Procedure TvShadersKey.SetCSShader(Shader:TvShaderExt);
|
|
begin
|
|
if (Shader=nil) then Exit;
|
|
if (Shader.FStage=VK_SHADER_STAGE_COMPUTE_BIT) then
|
|
FShaders[vShaderStageCs]:=Shader;
|
|
end;
|
|
|
|
procedure TvShadersKey.ExportLayout(var A:AvSetLayout;
|
|
var B:AvPushConstantRange);
|
|
var
|
|
i:TvShaderStage;
|
|
c,p:Integer;
|
|
begin
|
|
c:=0;
|
|
p:=0;
|
|
|
|
For i:=Low(TvShaderStage) to High(TvShaderStage) do
|
|
begin
|
|
if (FShaders[i]<>nil) then
|
|
begin
|
|
FShaders[i].InitSetLayout;
|
|
|
|
SetLength(A,c+1);
|
|
A[c]:=FShaders[i].FSetLayout;
|
|
Inc(c);
|
|
|
|
if (FShaders[i].FPushConst.size<>0) then
|
|
begin
|
|
SetLength(B,p+1);
|
|
|
|
B[p]:=Default(TVkPushConstantRange);
|
|
B[p].stageFlags:=ord(FShaders[i].FStage);
|
|
B[p].offset :=FShaders[i].FPushConst.offset;
|
|
B[p].size :=FShaders[i].FPushConst.size;
|
|
|
|
Inc(p);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvShadersKey.ExportStages(Stages:PVkPipelineShaderStageCreateInfo;stageCount:PVkUInt32);
|
|
var
|
|
i:TvShaderStage;
|
|
c:Integer;
|
|
begin
|
|
c:=0;
|
|
For i:=Low(TvShaderStage) to High(TvShaderStage) do
|
|
if (FShaders[i]<>nil) then
|
|
begin
|
|
Stages[c].sType :=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
Stages[c].stage :=FShaders[i].FStage;
|
|
Stages[c].module:=FShaders[i].FHandle;
|
|
Stages[c].pName :=PChar(FShaders[i].FEntry);
|
|
Inc(c);
|
|
end;
|
|
stageCount^:=c;
|
|
end;
|
|
|
|
Procedure TvShaderGroup.Clear;
|
|
begin
|
|
FKey:=Default(TvShadersKey);
|
|
FLayout:=nil;
|
|
end;
|
|
|
|
Function TvShaderGroup.Compile:Boolean;
|
|
var
|
|
A:AvSetLayout;
|
|
B:AvPushConstantRange;
|
|
begin
|
|
Result:=True;
|
|
if (FLayout<>nil) then Exit;
|
|
|
|
A:=Default(AvSetLayout);
|
|
B:=Default(AvPushConstantRange);
|
|
|
|
FKey.ExportLayout(A,B);
|
|
|
|
FLayout:=FetchPipelineLayout(A,B);
|
|
Result:=(FLayout<>nil);
|
|
end;
|
|
|
|
procedure TvBufOffsetChecker.AddAttr(const b:TvCustomLayout;Fset:TVkUInt32;FData:PDWORD);
|
|
var
|
|
P:Pointer;
|
|
a:QWORD;
|
|
begin
|
|
if not FResult then Exit;
|
|
|
|
P:=GetSharpByPatch(FData,b.addr);
|
|
if (P=nil) then Exit;
|
|
|
|
Case TVkDescriptorType(b.dtype) of
|
|
//VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER=4,
|
|
//VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER=5,
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
Case b.addr[0].rtype of
|
|
vtRoot,
|
|
vtBufPtr2:
|
|
begin
|
|
a:=AlignShift(P,limits.minStorageBufferOffsetAlignment);
|
|
if (a<>b.offset) then FResult:=False;
|
|
end;
|
|
vtVSharp4:
|
|
begin
|
|
a:=AlignShift(Pointer(PVSharpResource4(P)^.base),limits.minStorageBufferOffsetAlignment);
|
|
if (a<>b.offset) then FResult:=False;
|
|
end;
|
|
else
|
|
Assert(false);
|
|
end;
|
|
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvFuncLayout.Add(addr:ADataLayout);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(FList);
|
|
SetLength(FList,i+1);
|
|
FList[i]:=addr;
|
|
end;
|
|
|
|
end.
|
|
|
|
|
|
|
|
|