diff --git a/spirv/emit_alloc.pas b/spirv/emit_alloc.pas index 544787bd..1a3e9e1c 100644 --- a/spirv/emit_alloc.pas +++ b/spirv/emit_alloc.pas @@ -112,7 +112,16 @@ begin Op.OpTypeArray, Op.OpTypeRuntimeArray: begin - DecorateList.OpDecorate(node,Decoration.ArrayStride,node^.array_stride); + if (node^.array_stride<>0) then + begin + DecorateList.OpDecorate(node,Decoration.ArrayStride,node^.array_stride); + end; + // + if (node^.is_array_image) then + begin + AddCapability(Capability.RuntimeDescriptorArray); + HeaderList.SPV_EXT_descriptor_indexing; + end; end; Op.OpTypeFloat: diff --git a/spirv/emit_fetch.pas b/spirv/emit_fetch.pas index de6b8fae..5b3cede3 100644 --- a/spirv/emit_fetch.pas +++ b/spirv/emit_fetch.pas @@ -79,8 +79,9 @@ type function MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); function AddPositionsInput(count:Byte):PsrVariable; - function FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; + function FetchUniformSimple(src:PsrDataLayout;pType:PsrType):PsrNode; function FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; + function FetchImageRuntimeArray(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; function FetchSampler(src:PsrDataLayout):PsrNode; function FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; end; @@ -696,7 +697,7 @@ end; //// -function TEmitFetch.FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; +function TEmitFetch.FetchUniformSimple(src:PsrDataLayout;pType:PsrType):PsrNode; var u:PsrUniform; v:PsrVariable; @@ -718,7 +719,17 @@ var begin pType:=TypeList.Fetch(dtype); pType:=TypeList.FetchImage(pType,info); - Result:=FetchUniform(src,pType); + Result:=FetchUniformSimple(src,pType); +end; + +function TEmitFetch.FetchImageRuntimeArray(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; +var + pType:PsrType; +begin + pType:=TypeList.Fetch(dtype); + pType:=TypeList.FetchImage(pType,info); + pType:=TypeList.FetchRuntimeArray(pType); + Result:=UniformList.Fetch(src,pType); end; function TEmitFetch.FetchSampler(src:PsrDataLayout):PsrNode; @@ -726,7 +737,7 @@ var pType:PsrType; begin pType:=TypeList.Fetch(dtTypeSampler); - Result:=FetchUniform(src,pType); + Result:=FetchUniformSimple(src,pType); end; function TEmitFetch.FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; diff --git a/spirv/emit_mimg.pas b/spirv/emit_mimg.pas index 4e7ff816..d52fb42d 100644 --- a/spirv/emit_mimg.pas +++ b/spirv/emit_mimg.pas @@ -12,9 +12,11 @@ uses ps4_pssl, srNode, srType, + srTypes, srReg, srLayout, srOp, + srUniform, emit_fetch; type @@ -1006,13 +1008,15 @@ begin begin coord:=GatherCoord_u(roffset,info); - //scalar or vector - node:=OpImageWrite(line,Tgrp,coord,dst); - lod:=Gather_value(roffset,dtUint32); - node^.AddLiteral(ImageOperands.Lod,'Lod'); - node^.AddParam(lod); + //lod:=OpNonUniform(lod); TODO + + //fetch image by index + Tgrp:=PsrUniform(Tgrp)^.FetchArrayChain(line,lod); + + //scalar or vector + node:=OpImageWrite(line,Tgrp,coord,dst); end; else Assert(false,'MIMG?'+IntToStr(FSPI.MIMG.OP)); @@ -1146,7 +1150,8 @@ begin emit_image_load(Tgrp,@info); end; - IMAGE_STORE..IMAGE_STORE_MIP_PCK: //stored + IMAGE_STORE, + IMAGE_STORE_PCK: //stored begin info.tinfo.Sampled:=2; Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); @@ -1154,6 +1159,15 @@ begin emit_image_store(Tgrp,@info); end; + IMAGE_STORE_MIP, + IMAGE_STORE_MIP_PCK: //stored mip + begin + info.tinfo.Sampled:=2; + Tgrp:=FetchImageRuntimeArray(pLayout,info.dtype,info.tinfo); + + emit_image_store(Tgrp,@info); + end; + IMAGE_GET_RESINFO: //get info by mip begin info.tinfo.Sampled:=1; diff --git a/spirv/emit_op.pas b/spirv/emit_op.pas index 320a3350..aff81fe4 100644 --- a/spirv/emit_op.pas +++ b/spirv/emit_op.pas @@ -48,12 +48,12 @@ type function OpStore(nLine, dst,src:PsrNode):PsrNode; override; // function OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrNode):PSpirvOp; - function OpLoadTo(nLine:PspirvOp;pType:PsrType;src:PsrNode):PsrRegNode; + function OpLoadTo(pType:PsrType;src:PsrNode;ppLine:PPspirvOp=nil):PsrRegNode; // function OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp; function OpConstruct(pLine:PspirvOp;dst:PsrRegNode):PSpirvOp; function OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrNode;src:PsrVariable):PSpirvOp; - function OpAccessChainTo(pLine:PspirvOp;vType:PsrType;src:PsrVariable;idx0:PsrNode):PsrNode; + function OpAccessChainTo(vType:PsrType;src:PsrVariable;idx0:PsrNode;ppLine:PPspirvOp=nil):PsrNode; function OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp; function OpLoopMerge(pLine,pLabel0,pLabel1:PspirvOp):PSpirvOp; function OpBranch(pLine,pLabel:PspirvOp):PSpirvOp; @@ -428,11 +428,11 @@ begin Result:=PSpirvOp(OpLoad(pLine,dtype,dst,src)); end; -function TEmitOp.OpLoadTo(nLine:PspirvOp;pType:PsrType;src:PsrNode):PsrRegNode; +function TEmitOp.OpLoadTo(pType:PsrType;src:PsrNode;ppLine:PPspirvOp=nil):PsrRegNode; begin Result:=NewReg(pType^.dtype); // - OpLoad(line,pType,Result,src); + _set_line(ppLine,PspirvOp(OpLoad(_get_line(ppLine),pType,Result,src))); end; function TEmitOp.OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp; @@ -474,14 +474,15 @@ begin //index add later end; -function TEmitOp.OpAccessChainTo(pLine:PspirvOp;vType:PsrType;src:PsrVariable;idx0:PsrNode):PsrNode; +function TEmitOp.OpAccessChainTo(vType:PsrType;src:PsrVariable;idx0:PsrNode;ppLine:PPspirvOp=nil):PsrNode; Var node:PSpirvOp; begin Result:=NewRefNode; // - node:=OpAccessChain(line,vType,Result,src); + node:=OpAccessChain(_get_line(ppLine),vType,Result,src); node^.AddParam(idx0); + _set_line(ppLine,node); end; function TEmitOp.OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp; diff --git a/spirv/srDecorate.pas b/spirv/srDecorate.pas index 7e47fa77..e61e7775 100644 --- a/spirv/srDecorate.pas +++ b/spirv/srDecorate.pas @@ -14,7 +14,15 @@ type PsrHeaderList=^TsrHeaderList; TsrHeaderList=object(TsrOpBlockCustom) FGLSL_std_450:PSpirvOp; - function emit_glsl_ext:PSpirvOp; + // + FSPV_EXT_descriptor_indexing:Boolean; + // + function OpExtension(const n:RawByteString):PSpirvOp; + function OpExtInstImport(const n:RawByteString):PSpirvOp; + // + function GLSL_std_450:PSpirvOp; + // + procedure SPV_EXT_descriptor_indexing; end; PsrDecorate=^TsrDecorate; @@ -53,17 +61,43 @@ implementation // -function TsrHeaderList.emit_glsl_ext:PSpirvOp; +function TsrHeaderList.OpExtension(const n:RawByteString):PSpirvOp; +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpExtension); + node^.AddString(n); + Result:=node; +end; + +function TsrHeaderList.OpExtInstImport(const n:RawByteString):PSpirvOp; +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpExtInstImport); + node^.pDst:=Emit.NewRefNode; + node^.AddString(n); + Result:=node; +end; + +function TsrHeaderList.GLSL_std_450:PSpirvOp; begin if (FGLSL_std_450=nil) then begin - FGLSL_std_450:=AddSpirvOp(Op.OpExtInstImport); - FGLSL_std_450^.pDst:=Emit.NewRefNode; - FGLSL_std_450^.AddString('GLSL.std.450'); + FGLSL_std_450:=OpExtInstImport('GLSL.std.450'); end; Result:=FGLSL_std_450; end; +procedure TsrHeaderList.SPV_EXT_descriptor_indexing; +begin + if not FSPV_EXT_descriptor_indexing then + begin + OpExtension('SPV_EXT_descriptor_indexing'); + FSPV_EXT_descriptor_indexing:=True; + end; +end; + // function TsrDecorate.c(n1,n2:PsrDecorate):Integer; diff --git a/spirv/srInterface.pas b/spirv/srInterface.pas index 05bc2add..90cd4d1f 100644 --- a/spirv/srInterface.pas +++ b/spirv/srInterface.pas @@ -462,7 +462,7 @@ function TEmitInterface.AddSGlslOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; var ext,node:PSpirvOp; begin - ext:=HeaderList.emit_glsl_ext; + ext:=HeaderList.GLSL_std_450; node:=AddSpirvOp(pLine,Op.OpExtInst); node^.AddParam(ext^.pDst); node^.AddLiteral(OpId,GlslOp.GetStr(OpId)); diff --git a/spirv/srOp.pas b/spirv/srOp.pas index 60b86aeb..f3f9c381 100644 --- a/spirv/srOp.pas +++ b/spirv/srOp.pas @@ -510,7 +510,7 @@ begin Result:=False; if not can_clear then Exit; - Assert(read_count=0,IntToStr(OpId)); + Assert(read_count=0,Op.GetStr(OpId)); if is_write_op(OpId) then begin diff --git a/spirv/srTypes.pas b/spirv/srTypes.pas index 4c7c90c1..5822aafa 100644 --- a/spirv/srTypes.pas +++ b/spirv/srTypes.pas @@ -45,8 +45,11 @@ type function GetItem(i:Word):PsrNode; function GetDWORD(i:Word):DWORD; function array_stride:DWORD; + function is_array_image:Boolean; + function array_image_info:TsrTypeImageInfo; function array_count:DWORD; function storage_class:DWORD; + function is_image:Boolean; function image_info:TsrTypeImageInfo; function GetPrintName:RawByteString; end; @@ -196,6 +199,44 @@ begin Result:=child^.fsize; end; +function TsrType.is_array_image:Boolean; +var + child:PsrType; +begin + Result:=False; + + Case fdtype of + dtTypeArray:; + dtTypeRuntimeArray:; + else + Exit; + end; + + child:=GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + + Result:=child^.is_image; +end; + +function TsrType.array_image_info:TsrTypeImageInfo; +var + child:PsrType; +begin + Result:=Default(TsrTypeImageInfo); + + Case fdtype of + dtTypeArray:; + dtTypeRuntimeArray:; + else + Exit; + end; + + child:=GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + + Result:=child^.image_info; +end; + function TsrType.array_count:DWORD; var pConst:PsrType; @@ -214,8 +255,12 @@ begin Result:=GetDWORD(0); end; -function TsrType.image_info:TsrTypeImageInfo; +function TsrType.is_image:Boolean; +begin + Result:=(fdtype=dtTypeImage); +end; +function TsrType.image_info:TsrTypeImageInfo; begin Result:=Default(TsrTypeImageInfo); if (fdtype<>dtTypeImage) then Exit; diff --git a/spirv/srUniform.pas b/spirv/srUniform.pas index a4903f3c..274d9cea 100644 --- a/spirv/srUniform.pas +++ b/spirv/srUniform.pas @@ -12,6 +12,7 @@ uses srRefId, srType, srTypes, + srReg, srLayout, srVariable, srCapability, @@ -50,6 +51,15 @@ type function GetPrintName:RawByteString; end; + PsrArrayChain=^TsrArrayChain; + TsrArrayChain=packed object(TsrRegUniform) + pNext:PsrArrayChain; + // + idx0:PsrNode; + end; + + TsrArrayChainList=specialize TNodeStack; + PsrUniform=^TsrUniform; TsrUniform=object(TsrDescriptor) public @@ -61,9 +71,14 @@ type fwrite_count:DWORD; // FReg:TsrRegUniform; + FArrayChainList:TsrArrayChainList; public - Procedure Init; inline; + FEmit:TCustomEmit; + Procedure Init(Emit:TCustomEmit); inline; function pReg:PsrRegUniform; inline; + function FetchArrayChain(pLine:Pointer;idx0:PsrNode):PsrArrayChain; + function chain_read:DWORD; + function chain_write:DWORD; function GetStorageName:RawByteString; function GetTypeChar:String2; function GetRw:Char; @@ -87,6 +102,9 @@ type implementation +uses + emit_op; + class function ntRegUniform.Down(node:PsrNode):Pointer; begin Result:=PsrRegUniform(node)^.FVar; @@ -179,11 +197,13 @@ begin Result:=Integer(n1^.FType>n2^.FType)-Integer(n1^.FTypenil) then @@ -202,6 +248,8 @@ begin begin image_info:=FType^.image_info; + _image_info: + if (image_info.Dim=Dim.Buffer) then begin Case image_info.Sampled of @@ -218,15 +266,50 @@ begin end; end; end; + // dtTypeSampler:Result:='uSmp'+IntToStr(FBinding); + // + dtTypeRuntimeArray: + begin + pChild:=pType^.GetItem(0)^.AsType(ntType); //Image + + if (pChild^.dtype=dtTypeImage) then + begin + image_info:=pChild^.image_info; + + goto _image_info; + end; + + end; else; end; end; +//TU +//TS +//TR + +//IU +//IS +//IR + +//US + +//RU + +function GetSampledTypeChar(Sampled:Byte):Char; +begin + Case Sampled of + 1:Result:='U'; //VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER | VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + 2:Result:='S'; //VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER | VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + else Result:='R'; //runtime texel buffer + end; +end; function TsrUniform.GetTypeChar:String2; var image_info:TsrTypeImageInfo; + pChild:PsrType; begin Result:=''; if (FType<>nil) then @@ -237,33 +320,88 @@ begin if (image_info.Dim=Dim.Buffer) then begin - Case image_info.Sampled of - 1:Result:='UB'; //VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - 2:Result:='SB'; //VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER - else Result:='RB'; //runtime texel buffer - end; + Result:='T'+GetSampledTypeChar(image_info.Sampled); end else begin - Case image_info.Sampled of - 1:Result:='UI'; //VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE - 2:Result:='SI'; //VK_DESCRIPTOR_TYPE_STORAGE_IMAGE - else Result:='RI'; //runtime image - end; + Result:='I'+GetSampledTypeChar(image_info.Sampled); end; end; + // dtTypeSampler:Result:='US'; //VK_DESCRIPTOR_TYPE_SAMPLER - else; + // + dtTypeRuntimeArray: + begin + pChild:=pType^.GetItem(0)^.AsType(ntType); //Image + + if (pChild^.dtype=dtTypeImage) then + begin + image_info:=pChild^.image_info; + + if (image_info.Dim=Dim.Buffer) then + begin + Assert(false,'GetTypeChar'); + end else + begin + Result:='R'+GetSampledTypeChar(image_info.Sampled); + end; + end; + + end; + else + Assert(false,'GetTypeChar'); end; end; +function TsrUniform.chain_read:DWORD; +var + node:PsrArrayChain; +begin + Result:=0; + if FReg.IsUsed then + begin + Result:=FReg.read_count; + end; + // + node:=FArrayChainList.pHead; + While (node<>nil) do + begin + if node^.IsUsed then + begin + Result:=Result+node^.read_count; + end; + node:=node^.pNext; + end; +end; + +function TsrUniform.chain_write:DWORD; +var + node:PsrArrayChain; +begin + Result:=0; + if FReg.IsUsed then + begin + Result:=FReg.write_count; + end; + // + node:=FArrayChainList.pHead; + While (node<>nil) do + begin + if node^.IsUsed then + begin + Result:=Result+node^.write_count; + end; + node:=node^.pNext; + end; +end; + function TsrUniform.GetRw:Char; begin Result:='0'; - if (FReg.read_count<>0) then + if (chain_read<>0) then begin Result:='1'; end; - if (FReg.write_count<>0) then + if (chain_write<>0) then begin Result:=Char(ord(Result) or ord('2')); end; @@ -294,7 +432,7 @@ var node:TsrUniform; begin node:=Default(TsrUniform); - node.Init; + node.Init(FEmit); node.pLayout:=s; node.FType :=t; Result:=FNTree.Find(@node); @@ -358,11 +496,11 @@ begin if (image_info.Sampled=2) then //storage image begin - if (node^.FReg.read_count=0) then + if (node^.chain_read=0) then begin pDecorateList^.OpDecorate(pVar,Decoration.NonReadable,0); end; - if (node^.FReg.write_count=0) then + if (node^.chain_write=0) then begin pDecorateList^.OpDecorate(pVar,Decoration.NonWritable,0); end; diff --git a/vulkan/vRectGS.pas b/vulkan/vRectGS.pas index 7e33308f..aeca7b29 100644 --- a/vulkan/vRectGS.pas +++ b/vulkan/vRectGS.pas @@ -94,9 +94,9 @@ begin //load positions For i:=0 to 2 do begin - pChain:=SprvEmit.OpAccessChainTo(SprvEmit.line,pVec4f,InputPos,UintId[i]); + pChain:=SprvEmit.OpAccessChainTo(pVec4f,InputPos,UintId[i]); // - Positions[i]:=SprvEmit.OpLoadTo(SprvEmit.line,pVec4f,pChain); + Positions[i]:=SprvEmit.OpLoadTo(pVec4f,pChain); end; //extract @@ -143,9 +143,9 @@ begin //Send vertex by index For i:=0 to 2 do begin - pChain:=SprvEmit.OpAccessChainTo(SprvEmit.line,pVec4f,InputPos,pIndex); + pChain:=SprvEmit.OpAccessChainTo(pVec4f,InputPos,pIndex); // - Positions[i]:=SprvEmit.OpLoadTo(SprvEmit.line,pVec4f,pChain); + Positions[i]:=SprvEmit.OpLoadTo(pVec4f,pChain); // SprvEmit.OpStore(SprvEmit.line,OutputPos,Positions[i]); diff --git a/vulkan/vShaderExt.pas b/vulkan/vShaderExt.pas index 36659c4b..1343d988 100644 --- a/vulkan/vShaderExt.pas +++ b/vulkan/vShaderExt.pas @@ -73,6 +73,9 @@ type procedure OnVertLayout(P:PChar); procedure OnBuffLayout(P:PChar); procedure OnUnifLayout(P:PChar); + procedure OnTexlLayout(P:PChar); + procedure OnImgsLayout(P:PChar); + procedure OnRuntLayout(P:PChar); procedure OnFuncLayout(P:PChar); end; @@ -451,9 +454,12 @@ begin 'V':OnVertLayout(P); 'B':OnBuffLayout(P); 'U':OnUnifLayout(P); + 'T':OnTexlLayout(P); + 'I':OnImgsLayout(P); + 'R':OnRuntLayout(P); 'F':OnFuncLayout(P); else - Assert(false,'TODO OnSourceExtension:"'+P^+'"'); + Assert(false,'TODO: OnSourceExtension:"'+P^+'"'); end; end; @@ -482,7 +488,7 @@ begin '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])); else - Assert(false,'TODO OnDataLayout:"'+P[1]+'"'); + Assert(false,'TODO: OnDataLayout:"'+P[1]+'"'); end; end; @@ -492,7 +498,7 @@ begin Case P[1] of 'D':AddImmData(_get_hex_dword(@P[3])); else - Assert(false,'TODO OnIExtLayout:"'+P[1]+'"'); + Assert(false,'TODO: OnIExtLayout:"'+P[1]+'"'); end; end; @@ -544,7 +550,8 @@ begin with TvShaderExt(FOwner) do Case P[1] of 'A':AddVertLayout(_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); - else; + else + Assert(false,'TODO: OnVertLayout:"'+P[1]+'"'); end; end; @@ -613,7 +620,8 @@ begin _get_hex_dword(@P[$21]), _get_hex_dword(@P[$2E]), _get_hex_char (@P[$3B])); - else; + else + Assert(false,'TODO: OnBuffLayout:"'+P[1]+'"'); end; end; @@ -648,7 +656,7 @@ begin AddToCustomLayout(FUnifLayouts,v); end; -//UI;PID=00000001;BND=00000000;MRW=1 +//IU;PID=00000001;BND=00000000;MRW=1 //US;PID=00000002;BND=00000001;MRW=1 //0123456789ABCDEF0123456789ABCDEF01 //0 1 2 @@ -657,18 +665,38 @@ procedure TvShaderParserExt.OnUnifLayout(P:PChar); begin with TvShaderExt(FOwner) do Case P[1] of - 'I':AddUnifLayout(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - _get_hex_dword(@P[7]), - _get_hex_dword(@P[$14]), - _get_hex_char (@P[$21])); 'S':AddUnifLayout(VK_DESCRIPTOR_TYPE_SAMPLER, _get_hex_dword(@P[7]), _get_hex_dword(@P[$14]), _get_hex_char (@P[$21])); - else; + else + Assert(false,'TODO: OnUnifLayout:"'+P[1]+'"'); end; end; +procedure TvShaderParserExt.OnTexlLayout(P:PChar); +begin + Assert(false,'TODO: OnTexlLayout:"'+P[1]+'"'); +end; + +procedure TvShaderParserExt.OnImgsLayout(P:PChar); +begin + with TvShaderExt(FOwner) do + Case P[1] of + 'U':AddUnifLayout(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + _get_hex_dword(@P[7]), + _get_hex_dword(@P[$14]), + _get_hex_char (@P[$21])); + else + Assert(false,'TODO: OnImgsLayout:"'+P[1]+'"'); + end; +end; + +procedure TvShaderParserExt.OnRuntLayout(P:PChar); +begin + Assert(false,'TODO: OnRuntLayout:"'+P[1]+'"'); +end; + Procedure TvShaderExt.EnumUnifLayout(cb:TvCustomLayoutCb;Fset:TVkUInt32;pUserData,pImmData:PDWORD); var i:Integer; @@ -697,7 +725,8 @@ begin with TvShaderExt(FOwner) do Case P[1] of 'F':AddFuncLayout(_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); - else; + else + Assert(false,'TODO: OnFuncLayout:"'+P[1]+'"'); end; end;