fpPS4/spirv/srBuffer.pas
2022-11-15 15:54:47 +03:00

1106 lines
21 KiB
ObjectPascal

unit srBuffer;
{$mode ObjFPC}{$H+}
interface
uses
sysutils,
spirv,
ginodes,
srNode,
srType,
srTypes,
srReg,
srVariable,
srLayout,
srDecorate,
srConfig;
type
ntBuffer=class(ntDescriptor)
class Procedure add_read (node,src:PsrNode); override;
class Procedure rem_read (node,src:PsrNode); override;
//
class Function pwrite_count (node:PsrNode):PDWORD; override;
class function GetStorageName(node:PsrNode):RawByteString; override;
end;
PsrBuffer=^TsrBuffer;
PsrField=^TsrField;
TsrFieldValue=(frNotFit,frIdent,frVectorAsValue,frValueInVector,frValueInArray);
TFieldFetchValue=record
fValue:TsrFieldValue;
pField:PsrField;
end;
TFieldEnumCb=procedure(pField:PsrField) of object;
TsrField=object
type
TFieldFetch=specialize TNodeFetch<PsrField,TsrField>;
var
pLeft,pRight:PsrField;
//----
pBuffer:PsrBuffer;
pParent:PsrField;
offset:PtrUint;
size:PtrUint;
stride:PtrUint;
FCount:PtrUint;
dtype:TsrDataType;
sType,pType:PsrType;
FID:Integer; //alloc late
//
FList:TFieldFetch;
function c(n1,n2:PsrField):Integer; static;
function Cross(o,s:PtrUint):Boolean;
function Find_be(o:PtrUint):PsrField;
function Find_le(o:PtrUint):PsrField;
function First:PsrField;
function Last:PsrField;
function Next(p:PsrField):PsrField;
function Prev(p:PsrField):PsrField;
function Fetch(o:PtrUint):PsrField;
function FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue;
function FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue;
function IsStructUsedRuntimeArray:Boolean;
function IsStructNotUsed:Boolean;
function IsTop:Boolean;
function GetStructDecorate:DWORD;
procedure UpdateSize;
function GetSize:PtrUint;
procedure FillNode(o,s:PtrUint);
function FillSpace:Integer;
end;
TsrBufferType=(btStorageBuffer,btUniformBuffer,btPushConstant);
TsrBuffer=packed object(TsrDescriptor)
pLeft,pRight:PsrBuffer;
//----
fwrite_count:DWORD;
//
align_offset:DWORD;
FEmit:TCustomEmit;
FDList:TRegDNodeList;
bType:TsrBufferType;
key:packed record
pLayout:PsrDataLayout;
AliasId:PtrInt;
end;
FTop:TsrField;
function c(n1,n2:PsrBuffer):Integer; static;
Procedure Init(Emit:TCustomEmit); inline;
Procedure AddDep(t:PsrNode);
Procedure RemDep(t:PsrNode);
function chain_read :DWORD;
function chain_write:DWORD;
function GetStorageName:RawByteString;
function GetTypeChar:Char;
function GetString:RawByteString;
function GetStructName:RawByteString;
function GetSize:PtrUint;
procedure EnumAllField(cb:TFieldEnumCb);
procedure ShiftOffset(Offset:PtrUint);
end;
PsrBufferList=^TsrBufferList;
TsrBufferList=object
type
TNodeFetch=specialize TNodeFetch<PsrBuffer,TsrBuffer>;
var
FEmit:TCustomEmit;
FNTree:TNodeFetch;
FPushConstant:PsrBuffer;
procedure Init(Emit:TCustomEmit); inline;
function Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
function NextAlias(buf:PsrBuffer):PsrBuffer;
Function First:PsrBuffer;
Function Next(node:PsrBuffer):PsrBuffer;
procedure EnumAllField(cb:TFieldEnumCb);
procedure OnFillSpace(node:PsrField);
procedure FillSpace;
procedure OnAllocID(pField:PsrField);
procedure AllocID;
procedure AllocBinding(Var FBinding:Integer);
procedure AllocSourceExtension;
function FindUserDataBuf:PsrBuffer;
procedure ApplyBufferType;
procedure AlignOffset(node:PsrBuffer;offset:PtrUint);
procedure AlignOffset;
procedure OnAllocTypeBinding(pField:PsrField);
procedure AllocTypeBinding;
procedure AllocName;
end;
implementation
class Procedure ntBuffer.add_read(node,src:PsrNode);
begin
inherited;
if src^.IsType(ntChain) then
begin
PsrBuffer(node)^.AddDep(src);
end;
end;
class Procedure ntBuffer.rem_read(node,src:PsrNode);
begin
inherited;
if src^.IsType(ntChain) then
begin
PsrBuffer(node)^.RemDep(src);
end;
end;
//
class Function ntBuffer.pwrite_count(node:PsrNode):PDWORD;
begin
Result:=@PsrBuffer(node)^.fwrite_count;
end;
class function ntBuffer.GetStorageName(node:PsrNode):RawByteString;
begin
Result:=PsrBuffer(node)^.GetStorageName;
end;
//---
function TsrField.c(n1,n2:PsrField):Integer;
begin
Result:=Integer(n1^.offset>n2^.offset)-Integer(n1^.offset<n2^.offset);
end;
function TsrField.Cross(o,s:PtrUint):Boolean;
begin
Result:=((o>=offset) and (o<offset+size)) or
((offset>=o) and (offset<o+s));
end;
function TsrField.Find_be(o:PtrUint):PsrField;
var
node:TsrField;
begin
node:=Default(TsrField);
node.offset:=o;
Result:=FList.Find_be(@node);
end;
function TsrField.Find_le(o:PtrUint):PsrField;
var
node:TsrField;
begin
node:=Default(TsrField);
node.offset:=o;
Result:=FList.Find_le(@node);
end;
function TsrField.First:PsrField;
begin
Result:=FList.Min;
end;
function TsrField.Last:PsrField;
begin
Result:=FList.Max;
end;
function TsrField.Next(p:PsrField):PsrField;
begin
Result:=FList.Next(p);
end;
function TsrField.Prev(p:PsrField):PsrField;
begin
Result:=FList.Prev(p);
end;
function TsrField.Fetch(o:PtrUint):PsrField;
var
node:TsrField;
begin
node:=Default(TsrField);
node.offset:=o;
Result:=FList.Find(@node);
if (Result=nil) then
begin
Assert(pBuffer^.FEmit<>nil);
Result:=pBuffer^.FEmit.Alloc(SizeOf(TsrField));
Result^.pBuffer:=pBuffer;
Result^.pParent:=@Self;
Result^.offset :=o;
Result^.FID :=-1;
FList.Insert(Result);
Inc(FCount);
end;
end;
function TsrField.FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue;
var
node:PsrField;
_stride:PtrUint;
begin
Result:=Default(TFieldFetchValue);
_stride:=0;
if _dtype.isVector then
begin
_stride:=_dtype.Child.BitSize div 8;
end;
Assert(_size=(_dtype.BitSize div 8));
node:=Find_le(_offset);
if (node<>nil) then
begin
if not node^.Cross(_offset,_size) then
begin
node:=Next(node);
if (node<>nil) then
begin
if not node^.Cross(_offset,_size) then
begin
node:=nil;
end;
end;
end;
end;
if (node=nil) then
begin
//new
node:=Fetch(_offset);
node^.size :=_size;
node^.stride:=_stride;
node^.dtype :=_dtype;
Result.fValue:=frIdent;
Result.pField:=node;
end else
Case node^.dtype of
dtTypeArray:
begin
if (node^.offset>_offset) then Exit; //ident or big than
if (node^.offset+node^.size<_offset+_size) then Exit;
if (node^.stride<_size) then Exit; //ident or min stride
Result.fValue:=frValueInArray;
Result.pField:=node;
end;
dtTypeRuntimeArray:
begin
if (node^.offset>_offset) then Exit; //ident or big than
if (node^.stride<_size) then Exit; //ident or min stride
Result.fValue:=frValueInArray;
Result.pField:=node;
Result.fValue:=frNotFit;
end;
else
begin
if node^.dtype.isVector then
begin //ftVector
if _dtype.isVector then
begin
if (node^.offset=_offset) and
(node^.size =_size) and
(node^.stride=_stride) then
begin
Result.fValue:=frIdent; //ident
Result.pField:=node;
end;
end else
begin
if (node^.offset>_offset) then Exit; //ident or big than
_offset:=_offset-node^.offset;
if (node^.stride=_size) and
(_offset mod node^.stride=0) then
begin
Result.fValue:=frValueInVector; //down to vector
Result.pField:=node;
end;
end;
end else
begin //ftValue
if _dtype.isVector then
begin
if (node^.offset=_offset) and
(node^.size =_size) then
begin
Result.fValue:=frVectorAsValue; //vector as value?
Result.pField:=node;
end;
end else
begin
if (node^.offset=_offset) and
(node^.size =_size) then
begin
Result.fValue:=frIdent; //ident
Result.pField:=node;
end;
end;
end;
end;
end;
end;
function TsrField.FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue;
var
node:PsrField;
begin
Result:=Default(TFieldFetchValue);
node:=Find_be(_offset); //RA only last item
if (node<>nil) then
begin
if (node^.offset>_offset) or
(node^.dtype<>dtTypeRuntimeArray) or
(node^.stride<>_stride) then
begin
Result.fValue:=frNotFit;
Result.pField:=nil;
Exit;
end;
end;
node:=Find_le(_offset);
if (node=nil) then
begin
//new
node:=Fetch(_offset);
node^.size :=High(PtrUint)-_offset;
node^.stride :=_stride;
node^.dtype :=dtTypeRuntimeArray;
Result.fValue:=frValueInArray;
Result.pField:=node;
end else
if (node^.stride=_stride) and
(node^.dtype =dtTypeRuntimeArray) and
(node^.offset<=_offset) then //ident or big than
begin
Result.fValue:=frValueInArray;
Result.pField:=node;
end;
end;
function TsrField.IsStructUsedRuntimeArray:Boolean;
var
node:PsrField;
begin
Result:=False;
if (dtype=dtTypeStruct) then
begin
node:=FList.Max;
if (node<>nil) then
begin
size:=node^.offset+node^.size;
end;
Result:=(size=High(PtrUint));
end;
end;
function TsrField.IsStructNotUsed:Boolean;
var
child:PsrField;
begin
Result:=False;
if IsTop then Exit;
if (FCount>1) then Exit;
child:=First;
if (child=nil) then Exit;
if (child^.offset<>0) then Exit;
if (child^.size<>stride) then Exit;
Result:=True;
end;
function TsrField.IsTop:Boolean;
begin
Result:=(pParent=nil);
end;
function TsrField.GetStructDecorate:DWORD;
begin
Result:=DWORD(-1); //dont use
if IsTop then
if (dtype=dtTypeStruct) then //is struct
begin
if (pBuffer^.FStorage<>StorageClass.StorageBuffer) and
(pBuffer^.bType=btStorageBuffer) then
begin
Result:=Decoration.BufferBlock;
end else
begin
Result:=Decoration.Block;
end;
end;
end;
procedure TsrField.UpdateSize;
var
node:PsrField;
begin
node:=FList.Max;
if (node<>nil) then
begin
size:=node^.offset+node^.size;
end;
end;
function TsrField.GetSize:PtrUint;
begin
UpdateSize;
Result:=size;
end;
procedure TsrField.FillNode(o,s:PtrUint);
procedure _Pad(p,v:PtrUint;_dtype:TsrDataType); //inline;
var
node:PsrField;
begin
if (o mod p<>0) and (s>=v) then
begin
node:=Fetch(o);
Assert(node^.dtype=dtUnknow,'WTF');
node^.size:=v;
node^.dtype:=_dtype;
o:=o+v;
s:=s-v;
end;
end;
procedure _Fill(v:PtrUint;_dtype:TsrDataType); //inline;
var
count:PtrUint;
node:PsrField;
begin
count:=s div v;
While (count<>0) do
begin
node:=Fetch(o);
Assert(node^.dtype=dtUnknow,'WTF');
node^.size:=v;
node^.dtype:=_dtype;
o:=o+v;
s:=s-v;
Dec(count);
end;
end;
begin
if (s=0) then Exit;
_Pad ( 2,1,dtUint8);
_Pad ( 4,2,dtHalf16);
_Pad ( 8,4,dtFloat32);
_Pad (16,8,dtVec2f);
_Fill(16,dtVec4f);
_Fill(8 ,dtVec2f);
_Fill(4 ,dtFloat32);
_Fill(2 ,dtHalf16);
_Fill(1 ,dtUint8);
end;
function TsrField.FillSpace:Integer;
var
pNode:PsrField;
Foffset,Fsize:PtrUint;
begin
Result:=0;
pNode:=First;
if (pNode=nil) then Exit;
Foffset:=0;
While (pNode<>nil) do
begin
if (pNode^.dtype=dtUnknow) then
begin
Case pNode^.size of
1:pNode^.dtype:=dtUint8;
2:pNode^.dtype:=dtHalf16;
4:pNode^.dtype:=dtFloat32;
8:pNode^.dtype:=dtVec2f;
16:pNode^.dtype:=dtVec4f;
else
Assert(false);
end;
end;
if (Foffset<pNode^.offset) then
begin
Fsize:=pNode^.offset-Foffset;
FillNode(Foffset,Fsize);
Inc(Result);
end;
Foffset:=pNode^.offset+pNode^.size;
pNode:=Next(pNode);
end;
if (stride<>0) and (dtype in [dtTypeArray,dtTypeRuntimeArray]) then
begin
pNode:=FList.Max;
if (pNode<>nil) then
begin
Foffset:=pNode^.offset+pNode^.size;
Assert(Foffset<=stride);
if (Foffset<stride) then
begin
Fsize:=stride-Foffset;
FillNode(Foffset,Fsize);
Inc(Result);
end;
end;
end;
end;
//--
function TsrBuffer.c(n1,n2:PsrBuffer):Integer;
begin
//first pLayout
Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout<n2^.key.pLayout);
if (Result<>0) then Exit;
//second CastNum
Result:=Integer(n1^.key.AliasId>n2^.key.AliasId)-Integer(n1^.key.AliasId<n2^.key.AliasId);
end;
Procedure TsrBuffer.Init(Emit:TCustomEmit); inline;
begin
FEmit:=Emit;
fntype :=ntBuffer;
bType :=btStorageBuffer;
FStorage:=StorageClass.Uniform;
FBinding:=-1;
FTop.FID:=-1;
FTop.dtype:=dtTypeStruct;
end;
Procedure TsrBuffer.AddDep(t:PsrNode);
var
pRegsStory:PsrRegsStory;
node:PRegDNode;
begin
if (t=nil) or (@Self=nil) then Exit;
pRegsStory:=FEmit.GetRegsStory;
node:=pRegsStory^.AllocDep;
node^.pNode:=t;
FDList.Push_head(node);
end;
Procedure TsrBuffer.RemDep(t:PsrNode);
var
pRegsStory:PsrRegsStory;
node,_prev:PRegDNode;
begin
if (t=nil) or (@Self=nil) then Exit;
node:=FDList.pHead;
_prev:=nil;
While (node<>nil) do
begin
if (node^.pNode=t) then
begin
if (_prev=nil) then
begin
FDList.pHead:=node^.pNext;
end else
begin
_prev^.pNext:=node^.pNext;
end;
pRegsStory:=FEmit.GetRegsStory;
pRegsStory^.FreeDep(node);
Exit;
end;
_prev:=node;
node:=node^.pNext;
end;
Assert(false,'not found!');
end;
function TsrBuffer.chain_read:DWORD;
var
node:PRegDNode;
begin
Result:=0;
node:=FDList.pHead;
While (node<>nil) do
begin
if node^.pNode^.IsType(ntChain) then
begin
Result:=Result+PsrChain(node^.pNode)^.read_count;
end;
node:=node^.pNext;
end;
end;
function TsrBuffer.chain_write:DWORD;
var
node:PRegDNode;
begin
Result:=0;
node:=FDList.pHead;
While (node<>nil) do
begin
if node^.pNode^.IsType(ntChain) then
begin
Result:=Result+PsrChain(node^.pNode)^.write_count;
end;
node:=node^.pNext;
end;
end;
function TsrBuffer.GetStorageName:RawByteString;
begin
Result:='';
Case bType of
btStorageBuffer:Result:='sBuf'+IntToStr(FBinding);
btUniformBuffer:Result:='uBuf'+IntToStr(FBinding);
btPushConstant :Result:='cBuf';
end;
end;
function TsrBuffer.GetTypeChar:Char;
begin
Result:=#0;
Case bType of
btStorageBuffer:Result:='S';
btUniformBuffer:Result:='U';
btPushConstant :Result:='P';
end;
end;
function TsrBuffer.GetString:RawByteString;
var
PID:DWORD;
begin
PID:=0;
if (key.pLayout<>nil) then
begin
PID:=key.pLayout^.FID;
end;
Result:='B'+GetTypeChar+
';PID='+HexStr(PID,8)+
';BND='+HexStr(FBinding,8)+
';LEN='+HexStr(GetSize,8)+
';OFS='+HexStr(align_offset,8);
end;
function TsrBuffer.GetStructName:RawByteString;
begin
Result:='TD'+HexStr(FBinding,8);
end;
function TsrBuffer.GetSize:PtrUint;
begin
Result:=FTop.GetSize;
end;
procedure TsrBuffer.EnumAllField(cb:TFieldEnumCb);
var
curr,node:PsrField;
begin
if (cb=nil) then Exit;
curr:=@FTop;
node:=curr^.First;
repeat
While (node<>nil) do
begin
if (node^.First<>nil) then //child exist
begin
curr:=node;
node:=curr^.First; //down
end else
begin
cb(node);
node:=curr^.Next(node);
end;
end;
cb(curr);
node:=curr;
curr:=curr^.pParent; //up
if (curr=nil) then Break;
node:=curr^.Next(node);
until false;
end;
procedure TsrBuffer.ShiftOffset(Offset:PtrUint);
var
node:PsrField;
begin
if (Offset=0) then Exit;
node:=FTop.Last;
While (node<>nil) do
begin
if (node^.offset+node^.size=High(PtrUint)) then
begin
node^.size:=node^.size-Offset;
end;
node^.offset:=node^.offset+Offset;
node:=FTop.Prev(node);
end;
end;
procedure TsrBufferList.Init(Emit:TCustomEmit); inline;
begin
FEmit:=Emit;
end;
function TsrBufferList.Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
var
node:TsrBuffer;
begin
node:=Default(TsrBuffer);
node.Init(FEmit);
node.key.pLayout:=s;
node.key.AliasId:=n;
Result:=FNTree.Find(@node);
if (Result=nil) then
begin
Result:=FEmit.Alloc(SizeOf(TsrBuffer));
Move(node,Result^,SizeOf(TsrBuffer));
Result^.FTop.pBuffer:=Result;
//
Result^.InitVar(FEmit);
//
FNTree.Insert(Result);
end;
end;
function TsrBufferList.NextAlias(buf:PsrBuffer):PsrBuffer;
begin
Result:=nil;
if (buf=nil) then Exit;
Result:=Fetch(buf^.key.pLayout,buf^.key.AliasId+1);
end;
Function TsrBufferList.First:PsrBuffer;
begin
Result:=FNTree.Min;
end;
Function TsrBufferList.Next(node:PsrBuffer):PsrBuffer;
begin
Result:=FNTree.Next(node);
end;
procedure TsrBufferList.EnumAllField(cb:TFieldEnumCb);
var
node:PsrBuffer;
begin
if (cb=nil) then Exit;
node:=First;
While (node<>nil) do
begin
if node^.IsUsed then
begin
node^.EnumAllField(cb);
end;
node:=Next(node);
end;
end;
procedure TsrBufferList.OnFillSpace(node:PsrField);
begin
node^.FillSpace;
end;
procedure TsrBufferList.FillSpace;
begin
EnumAllField(@OnFillSpace);
end;
procedure TsrBufferList.OnAllocID(pField:PsrField);
var
node:PsrField;
ID:Integer;
begin
ID:=0;
node:=pField^.First;
While (node<>nil) do
begin
if pField^.dtype.IsVector then
begin
ID:=node^.offset div pField^.stride;
node^.FID:=ID;
end else
begin
node^.FID:=ID;
Inc(ID);
end;
node:=pField^.Next(node);
end;
end;
procedure TsrBufferList.AllocID;
begin
EnumAllField(@OnAllocID);
end;
procedure TsrBufferList.AllocBinding(Var FBinding:Integer);
var
pConfig:PsrConfig;
pDecorateList:PsrDecorateList;
node:PsrBuffer;
pVar:PsrVariable;
begin
pConfig:=FEmit.GetConfig;
pDecorateList:=FEmit.GetDecorateList;
node:=First;
While (node<>nil) do
begin
pVar:=node^.pVar;
if (pVar<>nil) and node^.IsUsed then
if (node^.bType<>btPushConstant) then
if (node^.FBinding=-1) then //alloc
begin
pDecorateList^.OpDecorate(pVar,Decoration.Binding,FBinding);
pDecorateList^.OpDecorate(pVar,Decoration.DescriptorSet,pConfig^.DescriptorSet);
node^.FBinding:=FBinding;
Inc(FBinding);
end;
node:=Next(node);
end;
end;
procedure TsrBufferList.AllocSourceExtension;
var
pDebugInfoList:PsrDebugInfoList;
node:PsrBuffer;
pVar:PsrVariable;
begin
pDebugInfoList:=FEmit.GetDebugInfoList;
node:=First;
While (node<>nil) do
begin
pVar:=node^.pVar;
if (pVar<>nil) and node^.IsUsed then
begin
pDebugInfoList^.OpSource(node^.GetString);
end;
node:=Next(node);
end;
end;
function TsrBufferList.FindUserDataBuf:PsrBuffer;
var
node:PsrBuffer;
begin
Result:=nil;
node:=First;
While (node<>nil) do
begin
if node^.IsUsed then
begin
if node^.key.pLayout^.IsUserData then
begin
Exit(node);
end;
end;
node:=Next(node);
end;
end;
procedure TsrBufferList.ApplyBufferType;
var
pConfig:PsrConfig;
node:PsrBuffer;
fchain_write:DWORD;
begin
pConfig:=FEmit.GetConfig;
node:=FindUserDataBuf;
if (node<>nil) and (FPushConstant=nil) then
if (node^.write_count=0) and
(node^.GetSize<=pConfig^.maxPushConstantsSize) then
begin
node^.bType :=btPushConstant;
node^.FStorage:=StorageClass.PushConstant;
FPushConstant :=node;
end;
node:=First;
While (node<>nil) do
begin
if node^.IsUsed and (node^.bType=btStorageBuffer) then
begin
fchain_write:=node^.chain_write;
if (FPushConstant=nil) and
(fchain_write=0) and
(node^.GetSize<=pConfig^.maxPushConstantsSize) then
begin
node^.bType :=btPushConstant;
node^.FStorage:=StorageClass.PushConstant;
FPushConstant :=node;
end else
if (fchain_write=0) and
(node^.GetSize<=pConfig^.maxUniformBufferRange) then
begin
node^.bType :=btUniformBuffer;
node^.FStorage:=StorageClass.Uniform;
end else
if pConfig^.CanUseStorageBufferClass then
begin
node^.FStorage:=StorageClass.StorageBuffer;
end else
begin
node^.FStorage:=StorageClass.Uniform;
end;
end;
node:=Next(node);
end;
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 TsrBufferList.AlignOffset(node:PsrBuffer;offset:PtrUint);
var
P:Pointer;
begin
P:=node^.key.pLayout^.GetData;
offset:=AlignShift(P,offset);
node^.align_offset:=offset;
node^.ShiftOffset(offset);
end;
procedure TsrBufferList.AlignOffset;
var
pConfig:PsrConfig;
node:PsrBuffer;
begin
pConfig:=FEmit.GetConfig;
node:=First;
While (node<>nil) do
begin
if node^.IsUsed then
begin
Case node^.bType of
btStorageBuffer:
begin
AlignOffset(node,pConfig^.minStorageBufferOffsetAlignment);
end;
btUniformBuffer:
begin
AlignOffset(node,pConfig^.minUniformBufferOffsetAlignment);
end;
btPushConstant:
begin
node^.align_offset:=pConfig^.PushConstantsOffset;
node^.ShiftOffset(pConfig^.PushConstantsOffset);
end;
end;
end;
node:=Next(node);
end;
end;
procedure TsrBufferList.OnAllocTypeBinding(pField:PsrField);
var
pDecorateList:PsrDecorateList;
node:PsrField;
SD:DWORD;
begin
if (pField^.sType=nil) then Exit;
if (pField^.sType^.dtype<>dtTypeStruct) then Exit;
pDecorateList:=FEmit.GetDecorateList;
SD:=pField^.GetStructDecorate;
if (SD<>DWORD(-1)) then
begin
pDecorateList^.OpDecorate(pField^.sType,SD,0);
end;
node:=pField^.First;
While (node<>nil) do
begin
pDecorateList^.OpMember(pField^.sType,node^.FID,node^.offset);
node:=pField^.Next(node);
end;
end;
procedure TsrBufferList.AllocTypeBinding;
var
pDecorateList:PsrDecorateList;
node:PsrBuffer;
begin
EnumAllField(@OnAllocTypeBinding);
//
pDecorateList:=FEmit.GetDecorateList;
//
node:=First;
While (node<>nil) do
begin
if node^.IsUsed and (node^.pVar<>nil) then
if (node^.bType=btStorageBuffer) then
begin
if (node^.chain_read=0) then
begin
pDecorateList^.OpDecorate(node^.pVar,Decoration.NonReadable,0);
end;
if (node^.chain_write=0) then
begin
pDecorateList^.OpDecorate(node^.pVar,Decoration.NonWritable,0);
end;
end;
node:=Next(node);
end;
end;
procedure TsrBufferList.AllocName;
var
FDebugInfo:PsrDebugInfoList;
node:PsrBuffer;
begin
FDebugInfo:=FEmit.GetDebugInfoList;
node:=First;
While (node<>nil) do
begin
if node^.IsUsed and (node^.FTop.pType<>nil) then
begin
FDebugInfo^.OpName(node^.FTop.pType,node^.GetStructName);
end;
node:=Next(node);
end;
end;
end.