Bladeren bron

* finished code generator implementation for shader files (classes need some more tests)

master
Bergmann89 11 jaren geleden
bovenliggende
commit
3411c92c3d
14 gewijzigde bestanden met toevoegingen van 1020 en 212 verwijderingen
  1. +31
    -7
      uengShaderFile.pas
  2. +2
    -1
      uengShaderFileConstants.pas
  3. +5
    -5
      uengShaderFileExpression.pas
  4. +87
    -12
      uengShaderFileHelper.pas
  5. +67
    -1
      uengShaderFileTypes.pas
  6. +18
    -17
      uengShaderGenerator.pas
  7. +490
    -86
      uengShaderGeneratorArgs.pas
  8. +1
    -1
      uengShaderPart.pas
  9. +97
    -2
      uengShaderPartCall.pas
  10. +24
    -4
      uengShaderPartClass.pas
  11. +5
    -1
      uengShaderPartCntr.pas
  12. +3
    -60
      uengShaderPartMeta.pas
  13. +12
    -12
      uengShaderPartParameter.pas
  14. +178
    -3
      uengShaderPartProc.pas

+ 31
- 7
uengShaderFile.pas Bestand weergeven

@@ -23,7 +23,7 @@ uses
type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderFileLogEvent = procedure(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String) of object;
TengShaderFile = class(TengShaderCodeGenerator)
TengShaderFile = class(TengShaderGenerator)
{ Code Loading & Storage }
private
fFilename: String;
@@ -31,7 +31,7 @@ type
fFileWriter: IutlFileWriter;
fClasses: TengShaderPartClassMap;
private
function GetGenerator(const aName: String): TengShaderCodeGenerator;
function GetGenerator(const aName: String): TengShaderGenerator;
function GetGeneratorCount: Integer;
function GetGeneratorNames(const aIndex: Integer): String;
procedure UpdateClasses;
@@ -54,7 +54,7 @@ type
protected
procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override;
public
property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator;
property Generator [const aName: String]: TengShaderGenerator read GetGenerator;
property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames;
property GeneratorCount: Integer read GetGeneratorCount;
property OnLog: TengShaderFileLogEvent read fOnLog write fOnLog;
@@ -67,12 +67,12 @@ type
implementation

uses
uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper;
uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper, uengShaderPartProc;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderFile////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderFile.GetGenerator(const aName: String): TengShaderCodeGenerator;
function TengShaderFile.GetGenerator(const aName: String): TengShaderGenerator;
begin
result := fClasses[aName];
if not Assigned(result) then
@@ -170,7 +170,7 @@ begin
walker.Owner := self;
walker.SearchFlags := [sfSearchChildren, sfIgnoreOwner];
walker.ResultTypes := CengShaderPartArr.Create(TengShaderFile);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
walker.Run(self);
for p in sr do
(p as TengShaderFile).CopyProperties(self);
@@ -260,10 +260,34 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderFile.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
var
sr: TengSearchResults;
walker: TengSearchWalker;
main: TengShaderPartMain;
begin
inherited GenerateCodeIntern(aArgs);
if (aArgs.Root = self) then begin
// TODO generate main routine code (if exists)
sr := TengSearchResults.Create;
walker := TengSearchWalker.Create(sr);
try
walker.SearchFlags := [sfSearchChildren, sfEvaluateIf];
walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
walker.Run(self);
main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr, []) as TengShaderPartMain);
if Assigned(main) then begin
aArgs.PushFlags((aArgs.Flags * [gfAddProcedureItem, gfAddParameterItem]) + [gfGenerateProcedureCode]);
try
main.GenerateCodeIntern(aArgs);
finally
aArgs.PopFlags;
end;
end;
finally
FreeAndNil(walker);
FreeAndNil(sr);
end;
end;
end;



+ 2
- 1
uengShaderFileConstants.pas Bestand weergeven

@@ -25,7 +25,7 @@ const

TOKEN_CLASS = TOKEN_CHAR_IDENT + 'CLASS'; //{$CLASS PhongLight $EXTENDS Normal Glow}
TOKEN_EXTENDS = TOKEN_CHAR_IDENT + 'EXTENDS';
TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED} {$INHERITED BaseClass}
TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED BaseClassMethod 'param1' 'param2'}

TOKEN_INCLUDE = TOKEN_CHAR_IDENT + 'INCLUDE'; //{$INCLUDE 'Normal.frag'}

@@ -85,6 +85,7 @@ const
TOKEN_SPLIT_CHARS = [' ', #9, TOKEN_OP_GROUP_BEGIN, TOKEN_OP_GROUP_END];
COMMAND_END_TOKENS = [TOKEN_CHAR_COMMANT_END, TOKEN_CHAR_SCOPE_BEGIN, TOKEN_CHAR_SCOPE_END];

LAYOUT_MIN_VERSION = 150;
VERSION_EXTRA_COMPAT = 'compatibility'; //{$META $VERSION 'compatibility'}

implementation


+ 5
- 5
uengShaderFileExpression.pas Bestand weergeven

@@ -692,14 +692,14 @@ begin
sr := TengSearchResults.Create;
walker := TengKeyValuePairSearchWalker.Create(sr);
try
walker.Name := param.Name;
walker.SearchFlags := [sfSearchChildrenLazy, sfSearchParents];
walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic);
walker.Name := param.Name;
walker.SearchFlags := [sfSearchChildrenLazy, sfSearchParents];
walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
walker.Run(fParent);
tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col);
tmp := ExtractSearchResult(fParent, param.Name, sr, [ifWarning, ifRaiseEx], param.Line, param.Col);
result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col);
finally
FreeAndNil(walker);


+ 87
- 12
uengShaderFileHelper.pas Bestand weergeven

@@ -8,15 +8,33 @@ interface
uses
uengShaderPart, uengShaderFileParser;

type
TInfoFlag = (
ifWarning,
ifRaiseEx
);
TInfoFlags = set of TInfoFlag;

function IsValidIdentifier(const aIdent: String): Boolean;
function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String;
function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer = -1; aCol: Integer = -1; aFilename: String = ''): TengShaderPart;
function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
function ExtractSearchResult(
const aSender: TengShaderPart;
const aIdent: String;
const aList: TengShaderPartList;
const aFlags: TInfoFlags = [ifWarning, ifRaiseEx];
aLine: Integer = -1;
aCol: Integer = -1;
aFilename: String = ''): TengShaderPart;

type
TengSearchFlag = (
sfSearchChildren, // search in children
sfEvaluateIf, // evaluate if and search in suitable subtree
sfIgnoreIf, // do not search in if items
sfSearchChildrenLazy, // set sfSearchChildren in next recursion level
sfSearchParents, // search in Parents
sfSearchInherited, // search in inherited classes
sfIgnoreOwner // ignore owner of search walker
);
TengSearchFlags = set of TengSearchFlag;
@@ -65,11 +83,21 @@ type
property Name: String read fName write fName;
end;

TengProcSearchWalker = class(TengSearchWalker)
private
fName: String;
protected
function Check(const aPart: TengShaderPart): Boolean; override;
public
property Name: String read fName write fName;
constructor Create(const aResults: TengSearchResults);
end;

implementation

uses
sysutils,
uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair;
uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, uengShaderPartIf;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function IsValidIdentifier(const aIdent: String): Boolean;
@@ -106,9 +134,21 @@ begin
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean;
var
t: CengShaderPart;
begin
result := true;
for t in aTypes do
if (aShaderPart is t) then
exit;
result := (Length(aTypes) = 0);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList;
aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart;
const aFlags: TInfoFlags; aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart;
var
s: String;
i: Integer;
@@ -122,10 +162,13 @@ begin
if (aFilename = '') then
aFilename := aSender.Filename;
end;
if (aList.Count <= 0) then
raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender);
if (aList.Count <= 0) then begin
if (ifRaiseEx in aFlags) then
raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender);
exit;
end;
result := aList[aList.Count-1];
if (aList.Count > 1) and Assigned(aSender) then begin
if (aList.Count > 1) and Assigned(aSender) and (ifWarning in aFlags) then begin
s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, result.Filename, result.Line + 1, result.Col]) + sLineBreak +
'previously declared here:' + sLineBreak;
i := aList.Count - 2;
@@ -183,7 +226,7 @@ var
end;

var
c: TengShaderPart;
p: TengShaderPart;
nextArgs: TArgs;
begin
if not Assigned(aPart) then
@@ -193,6 +236,7 @@ begin
else
args.Flags := fSearchFlags;

// visit parent
nextArgs := args;
if (sfSearchChildrenLazy in nextArgs.Flags) then
nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy];
@@ -201,12 +245,25 @@ begin
if VisitParent then
Visit(aPart.Parent, aPart, @nextArgs);

// visit children
if (sfSearchChildren in args.Flags) then begin
for c in aPart do begin
if Check(c) then
fResults.Add(c);
if VisitChild(c) then
Visit(c, aPart, @args);
if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin
if (sfEvaluateIf in args.Flags) then begin
if Expression.GetValue
then p := IfPart
else p := ElsePart;
if Assigned(p) then
Visit(p, aPart, @args);
exit;
end else if (sfIgnoreIf in args.Flags) then
exit;
end;

for p in aPart do begin
if Check(p) then
fResults.Add(p);
if VisitChild(p) then
Visit(p, aPart, @args);
end;
end;
end;
@@ -242,5 +299,23 @@ begin
((aPart as TengShaderPartKeyValuePair).Name = fName);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengProcSearchWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengProcSearchWalker.Check(const aPart: TengShaderPart): Boolean;
begin
result :=
inherited Check(aPart) and
(aPart is TengShaderPartProc) and
((aPart as TengShaderPartProc).Name = fName);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengProcSearchWalker.Create(const aResults: TengSearchResults);
begin
inherited Create(aResults);
ResultTypes := CengShaderPartArr.Create(TengShaderPartProc);
end;

end.


+ 67
- 1
uengShaderFileTypes.pas Bestand weergeven

@@ -9,7 +9,7 @@ uses
Classes, SysUtils

{$IFDEF USE_BITSPACE_UTILS}
, uutlSerialization, uutlCommon
, uutlSerialization, uutlCommon, uutlGenerics
{$ENDIF}
;

@@ -36,6 +36,33 @@ type

end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengMetaType = (
metaUnknown,
metaNormal,
metaVersion,
metaExtension,
metaLayout);
TengMetaData = class(TObject)
private
fMetaType: TengMetaType;
fName: String;
fValues: TStringList;
function GetCount: Integer;
function GetValues: TStrings;
public
property MetaType: TengMetaType read fMetaType;
property Name: String read fName;
property Count: Integer read GetCount;
property Values: TStrings read GetValues;

procedure Assign(const aValues: TengMetaData);

constructor Create(const aName: String; const aType: TengMetaType);
destructor Destroy; override;
end;
TengMetaDataList = specialize TutlSimpleList<TengMetaData>;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Exceptions////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -159,6 +186,45 @@ implementation
uses
uengShaderPart;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengMetaData//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengMetaData.GetCount: Integer;
begin
result := fValues.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengMetaData.GetValues: TStrings;
begin
result := fValues;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengMetaData.Assign(const aValues: TengMetaData);
begin
fName := aValues.Name;
fMetaType := aValues.MetaType;
fValues.Clear;
fValues.AddStrings(aValues.Values);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengMetaData.Create(const aName: String; const aType: TengMetaType);
begin
inherited Create;
fName := aName;
fMetaType := aType;
fValues := TStringList.Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengMetaData.Destroy;
begin
FreeAndNil(fValues);
inherited Destroy;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//EengExpressionInternal////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 18
- 17
uengShaderGenerator.pas Bestand weergeven

@@ -12,7 +12,7 @@ uses

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderCodeGenerator = class(TengShaderPartScope)
TengShaderGenerator = class(TengShaderPartScope)
{ Code Loading & Storage }
private
fPropertyMap: TengShaderPartPropertyMap;
@@ -26,7 +26,7 @@ type
procedure SetPropertyByName(const aName: String; aValue: Variant);
protected
procedure AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean = true);
procedure CopyProperties(const aGen: TengShaderCodeGenerator);
procedure CopyProperties(const aGen: TengShaderGenerator);
procedure UpdateProperties; virtual;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
public
@@ -48,15 +48,15 @@ type
implementation

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderCodeGenerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderGenerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.GetPropertyByIndex(const aIndex: Integer): Variant;
function TengShaderGenerator.GetPropertyByIndex(const aIndex: Integer): Variant;
begin
result := fPropertyMap.ValueAt[aIndex].Value;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.GetPropertyByName(const aName: String): Variant;
function TengShaderGenerator.GetPropertyByName(const aName: String): Variant;
var
l: TengShaderPartPropertyList;
begin
@@ -67,25 +67,25 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.GetPropertyCount: Integer;
function TengShaderGenerator.GetPropertyCount: Integer;
begin
result := fPropertyMap.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.GetPropertyNames(const aIndex: Integer): String;
function TengShaderGenerator.GetPropertyNames(const aIndex: Integer): String;
begin
result := fPropertyMap.KeyValuePairs[aIndex].Key;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant);
procedure TengShaderGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant);
begin
fPropertyMap.ValueAt[aIndex].Value := aValue;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.SetPropertyByName(const aName: String; aValue: Variant);
procedure TengShaderGenerator.SetPropertyByName(const aName: String; aValue: Variant);
var
l: TengShaderPartPropertyList;
begin
@@ -96,7 +96,7 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean);
procedure TengShaderGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean);
var
l: TengShaderPartPropertyList;
p: TengShaderPartProperty;
@@ -121,7 +121,7 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.CopyProperties(const aGen: TengShaderCodeGenerator);
procedure TengShaderGenerator.CopyProperties(const aGen: TengShaderGenerator);
var
l: TengShaderPartPropertyList;
p: TengShaderPartProperty;
@@ -132,26 +132,27 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.UpdateProperties;
procedure TengShaderGenerator.UpdateProperties;
begin
fPropertyMap.Clear;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
function TengShaderGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
begin
result := inherited ParseIntern(aArgs, aParams);
UpdateProperties;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderCodeGenerator.GenerateCode(const aCode: TengShaderCode);
procedure TengShaderGenerator.GenerateCode(const aCode: TengShaderCode);
var
args: TengShaderGeneratorArgs;
begin
args := TengShaderGeneratorArgs.Create(self);
try
inherited GenerateCodeIntern(args);
fPropertyMap.ApplyValues;
GenerateCodeIntern(args);
args.GenerateCode(aCode);
finally
FreeAndNil(args);
@@ -159,14 +160,14 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart);
constructor TengShaderGenerator.Create(const aParent: TengShaderPart);
begin
inherited Create(aParent);
fPropertyMap := TengShaderPartPropertyMap.Create(true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengShaderCodeGenerator.Destroy;
destructor TengShaderGenerator.Destroy;
begin
FreeAndNil(fPropertyMap);
inherited Destroy;


+ 490
- 86
uengShaderGeneratorArgs.pas Bestand weergeven

@@ -17,33 +17,52 @@ uses
type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengGenerateFlag = (
gfGenerateParameterItemCode, // generate code for parameter items
gfAddParameterItem // add parameter items to generator args
gfGenerateProcedureCode, // generate procedure code
gfGenerateProcedureCall, // generate procedure call
gfGenerateInlineCode, // generate procedure as inline code
gfGenerateParameterCode, // generate code for parameter items
gfAddProcedureItem, // add procedure item to generator args
gfAddParameterItem // add parameter items to generator args
);
TengGenerateFlags = set of TengGenerateFlag;
TengGenerateFlagsStack = specialize TutlSimpleList<TengGenerateFlags>;

TengPopCodeFlag = (
pcfAppend,
pcfPrepend,
pcfAddEmptyLine
);
TengPopCodeFlags = set of TengPopCodeFlag;

TengShaderGeneratorArgs = class(TObject)
private type
TengGeneratorToken = (
gtNormal, // normal text
gtLineBreak, // line break
gtCommandEnd, // command end (like ';')
gtBlockBegin, // code block begin (to calculate indent)
gtBlockEnd, // code block end (to calculate indent)
gtToken // code token (like '$INCLUDE' or '$IF')
gtNormal = 0, // normal text
gtLineBreak = 1, // line break
gtCommandEnd = 2, // command end (like ';')
gtBlockBegin = 3, // code block begin (to calculate indent)
gtBlockEnd = 4, // code block end (to calculate indent)
gtToken = 5 // code token (like '$INCLUDE' or '$IF')
);

TCodePart = class(TObject)
private
fText: String;
fIndent: Integer;
fToken: TengGeneratorToken;
function GetText: String;
function GetDebugText: String;
function GetCode: String;
public
property Text: String read GetText;
property Token: TengGeneratorToken read fToken;
constructor Create(const aToken: TengGeneratorToken; const aText: String);
property Text: String read fText write fText;
property Code: String read GetCode;
property DebugText: String read GetDebugText;
property Indent: Integer read fIndent;
property Token: TengGeneratorToken read fToken;
constructor Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer = 0);
end;
TCodePartList = specialize TutlSimpleList<TCodePart>;

public type
TCodeStackItem = class(TObject)
private
fItems: TCodePartList;
@@ -53,33 +72,64 @@ type
property IsEmpty: Boolean read GetIsEmpty;

procedure GenerateCode(const aCode: TengShaderCode);
procedure Merge(const aItem: TCodeStackItem; aIndex: Integer);

constructor Create;
destructor Destroy; override;
end;

private type
TCodeStack = specialize TutlSimpleList<TCodeStackItem>;
TParameterMap = specialize TutlMap<string, TengShaderPart>;
TProcedureList = specialize TutlSimpleList<TengShaderPart>;
TProcParamStack = specialize TutlSimpleList<TStrings>;

private
fInlineReturnCounter: Integer;
fCode: TCodeStack;
fRoot: TengShaderPart;
fFlags: TengGenerateFlags;
fFlagStack: TengGenerateFlagsStack;
fMetaDataList: TengMetaDataList;
fParameters: TParameterMap;
fProcedures: TProcedureList;
fProcParams: TProcParamStack;

fMaxParameterLength: Integer;

function GetFlags: TengGenerateFlags;
function GetProcParams: TStrings;

procedure GenerateParameterCode(const aTypes: CengShaderPartArr);
procedure GenerateProcedureCode;
procedure GenerateMetaCode;
public
property Root: TengShaderPart read fRoot;
property Flags: TengGenerateFlags read fFlags;
property Root: TengShaderPart read fRoot;
property Flags: TengGenerateFlags read GetFlags;
property ProcParams: TStrings read GetProcParams;
property MaxParameterLength: Integer read fMaxParameterLength;

procedure PushCode;
procedure PopCode;
procedure PushFlags(const aFlags: TengGenerateFlags);
procedure PushProcParams(const aParams: TStrings);

procedure PopCode(const aFlags: TengPopCodeFlags);
procedure PopFlags;
procedure PopProcParams;

function AddText(const aText: String): TengShaderGeneratorArgs;
function AddToken(const aToken: String): TengShaderGeneratorArgs;
function AddCommandEnd(const aToken: String): TengShaderGeneratorArgs;
function AddLineBreak: TengShaderGeneratorArgs;
function BeginBlock(const aIndent: Integer = 0): TengShaderGeneratorArgs;
function EndBlock: TengShaderGeneratorArgs;

procedure AddText(const aText: String);
procedure AddToken(const aToken: String);
procedure AddCommandEnd(const aToken: String);
procedure AddLineBreak;
procedure BeginBlock;
procedure EndBlock;
procedure AddMeta(const aMeta: TengMetaData);
procedure AddParameter(const aParam: TengShaderPart);
procedure AddProcedure(const aProc: TengShaderPart);

procedure AddMeta(const aMeta: TengShaderPart);
procedure AddParam(const aParam: TengShaderPart);
function ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer;
procedure ReplaceIdents(const aOld, aNew: TStrings);
procedure ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String);

procedure GenerateCode(const aCode: TengShaderCode);

@@ -90,12 +140,16 @@ type
implementation

uses
Math;
Math, RegExpr,
uengShaderFileHelper, uengShaderFileConstants, uengShaderPartParameter, uengShaderPartProc;

const
WHITESPACES = [' ', #9];

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderGeneratorArgs.TCodePart///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderGeneratorArgs.TCodePart.GetText: String;
function TengShaderGeneratorArgs.TCodePart.GetCode: String;
begin
case fToken of
gtNormal,
@@ -109,11 +163,27 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderGeneratorArgs.TCodePart.Create(const aToken: TengGeneratorToken; const aText: String);
function TengShaderGeneratorArgs.TCodePart.GetDebugText: String;
begin
case fToken of
gtNormal: result := '[N]' + fText;
gtLineBreak: result := sLineBreak;
gtCommandEnd: result := '[C]' + fText;
gtBlockBegin: result := format('[B%d]', [fIndent]);
gtBlockEnd: result := '[E]';
gtToken: result := '[T' + fText + ']';
else
result := '[' + IntToStr(Integer(fToken)) + ']' + fText
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderGeneratorArgs.TCodePart.Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer);
begin
inherited Create;
fToken := aToken;
fText := aText;
fToken := aToken;
fText := aText;
fIndent := aIndent;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -131,15 +201,10 @@ type
gfToken, // current line has a token in it
gfTokenOnly, // current line has only a token (or whitespaces) in it
gfPrevIsEmpty, // previouse line was empty (or whitespaces only)
gfCodeIsEmpty, // nothing has added to code
gfAddToPrevLine, // add current line to previous line
gfAddNextLine // add next line to current line (set gfAddToPrevLine on linebreak)
gfCodeIsEmpty // nothing has added to code
);
TGenFlags = set of TGenFlag;

const
WHITESPACES = [' ', #9];

var
i: Integer;
f: TGenFlags;
@@ -171,7 +236,7 @@ var
inc(aStartIndex);
end;
if (result >= High(Integer)) then
result := -1;
result := 0;
end;

function TrimLeftLen(const aStr: String; aLen: Integer): String;
@@ -189,23 +254,22 @@ var

function PrepareStr(const aStr: String; const aOffset: Integer): String;
begin
if (aOffset < 0)
then result := StringOfChar(' ', -aOffset) + aStr
else result := TrimLeftLen(aStr, aOffset);
if (aOffset > 0)
then result := StringOfChar(' ', aOffset) + aStr
else result := TrimLeftLen(aStr, -aOffset);
end;

procedure IndentBlock(aStartIndex: Integer; const aIndent: Integer);
var
o: Integer;
begin
o := GetMinOffset(aStartIndex) - aIndent;
if (o <= 0) then
exit;
o := aIndent - GetMinOffset(aStartIndex);
while (aStartIndex < aCode.Count) do begin
aCode[aStartIndex] := PrepareStr(aCode[aStartIndex], o);
inc(aStartIndex);
end;
line := PrepareStr(line, o);
if (Trim(line) <> '') then
line := PrepareStr(line, o);
end;

procedure ProgressBlock(const aIndent: Integer);
@@ -221,33 +285,18 @@ var

case cp.Token of
gtLineBreak: begin

// line has whitespaces only
if (Trim(line) = '') then begin
if (f * [gfToken, gfPrevIsEmpty] = []) then begin
if (f * [gfTokenOnly, gfPrevIsEmpty] = []) then begin
aCode.Add(line);
Include(f, gfPrevIsEmpty);
end;
if not (gfTokenOnly in f) then
Exclude(f, gfAddToPrevLine);

// line has text
end else begin
if (gfAddToPrevLine in f) and not (gfCodeIsEmpty in f) then begin
aCode[aCode.Count-1] := aCode[aCode.Count-1] + TrimLeft(line)
end else begin
aCode.Add(line);
Exclude(f, gfPrevIsEmpty);
Exclude(f, gfCodeIsEmpty);
end;
Exclude(f, gfAddToPrevLine);
aCode.Add(line);
Exclude(f, gfPrevIsEmpty);
Exclude(f, gfCodeIsEmpty);
end;
Exclude(f, gfToken);
Exclude(f, gfTokenOnly);
if (gfAddNextLine in f) then begin
Exclude(f, gfAddNextLine);
Include(f, gfAddToPrevLine);
end;
line := '';
end;

@@ -258,35 +307,59 @@ var
end;

gtBlockBegin: begin
if (Trim(line) <> '') then
Include(f, gfAddNextLine);
Include(f, gfPrevIsEmpty);
ProgressBlock(GetOffset(cp));
ProgressBlock(GetStrOffset(line) + cp.Indent);
end;

gtBlockEnd: begin
if (Trim(line) = '') then
Include(f, gfAddToPrevLine);
IndentBlock(FirstLineIndex, aIndent);
exit;
end;

else
s := cp.GetText;
if (gfAddNextLine in f) and (Trim(s) <> '') then
Exclude(f, gfAddNextLine);
s := cp.Code;
line := line + s;
end;
end;
end;

procedure GenerateDebugCode;
var
cp: TCodePart;
s: String;
sl: TStringList;
begin
s := '';
for cp in fItems do
s := s + cp.DebugText;
sl := TStringList.Create;
try
sl.Text := s;
sl.SaveToFile('C:\Users\Erik\Desktop\tmp\debug.txt');
finally
FreeAndNil(sl);
end;
end;

begin
i := 0;
f := [gfPrevIsEmpty, gfCodeIsEmpty];
line := '';
GenerateDebugCode;
ProgressBlock(0);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.TCodeStackItem.Merge(const aItem: TCodeStackItem; aIndex: Integer);
begin
if (aIndex < 0) then
aIndex := 0;
if (aIndex > fItems.Count) then
aIndex := fItems.Count;
while (aItem.Items.Count > 0) do
fItems.Insert(aIndex, aItem.Items.PopLast(false));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderGeneratorArgs.TCodeStackItem.Create;
begin
@@ -302,7 +375,126 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderGeneratorArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderGeneratorArgs///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderGeneratorArgs.GetFlags: TengGenerateFlags;
begin
result := fFlagStack.Last;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderGeneratorArgs.GetProcParams: TStrings;
begin
result := fProcParams.Last;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.GenerateParameterCode(const aTypes: CengShaderPartArr);
var
m: TParameterMap;
p: TengShaderPart;
begin
PushCode;
PushFlags(Flags + [gfGenerateParameterCode] - [gfAddParameterItem]);
m := TParameterMap.Create(false);
try
fMaxParameterLength := 0;
for p in fParameters do begin
if CheckType(p, aTypes) then with (p as TengShaderPartParameter) do begin
fMaxParameterLength := Max(fMaxParameterLength, Length(Typ));
m.Add(Typ+Name, p);
end;
end;
for p in m do begin
(p as TengShaderPartParameter).GenerateCodeIntern(self);
AddLineBreak;
end;
finally
FreeAndNil(m);
PopFlags;
PopCode([pcfPrepend, pcfAddEmptyLine]);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.GenerateProcedureCode;
var
i: Integer;
begin
i := 0;
while (i < fProcedures.Count) do begin
PushCode;
PushFlags([gfGenerateProcedureCode, gfAddParameterItem]);
try
(fProcedures[i] as TengShaderPartProc).GenerateCodeIntern(self);
finally
PopFlags;
PopCode([pcfPrepend, pcfAddEmptyLine]);
end;
inc(i);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.GenerateMetaCode;
var
layouts: TStringList;
m: TengMetaData;
vCompat: Boolean;
vMax, i: Integer;
s: String;
begin
PushCode;
vMax := 0;
vCompat := false;
layouts := TStringList.Create;
try
for m in fMetaDataList do begin
case m.MetaType of
metaVersion: begin
if (m.Values[0] = VERSION_EXTRA_COMPAT) then
vCompat := true
else if TryStrToInt(m.Values[0], i) then
vMax := max(vMax, i);
if (m.Count > 1) and (m.Values[1] = VERSION_EXTRA_COMPAT) then
vCompat := true;
end;

metaExtension: begin
AddText(format('#extension %s : %s', [m.Values[0], m.Values[1]]));
AddLineBreak;
end;

metaLayout: begin
layouts.Add('layout' + m.Values[0] + ';');
end;
end;
end;

if (vMax >= LAYOUT_MIN_VERSION) then begin
for s in layouts do begin
AddText(s);
AddLineBreak;
end;
end;

if (vMax > 0) then begin
PushCode;
try
AddText('#version ' + IntToStr(vMax));
if vCompat then
AddText(' ' + VERSION_EXTRA_COMPAT);
AddLineBreak;
finally
PopCode([pcfPrepend]);
end;
end;
finally
PopCode([pcfPrepend, pcfAddEmptyLine]);
FreeAndNil(layouts);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.PushCode;
begin
@@ -310,69 +502,269 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.PopCode;
procedure TengShaderGeneratorArgs.PushFlags(const aFlags: TengGenerateFlags);
begin
fFlagStack.PushLast(aFlags);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.PushProcParams(const aParams: TStrings);
begin
fProcParams.PushLast(aParams);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.PopCode(const aFlags: TengPopCodeFlags);
var
csi: TCodeStackItem;
begin
csi := fCode.PopLast(false);
try
// TODO merge
if csi.IsEmpty then
exit;
if (pcfPrepend in aFlags) then begin
if (pcfAddEmptyLine in aFlags) then
csi.Items.Add(TCodePart.Create(gtLineBreak, ''));
fCode.Last.Merge(csi, 1);
end else if (pcfAppend in aFlags) then begin
if (pcfAddEmptyLine in aFlags) then
fCode.Last.Items.Add(TCodePart.Create(gtLineBreak, ''));
fCode.Last.Merge(csi, fCode.Last.Items.Count);
end;
finally
FreeAndNil(csi);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddText(const aText: String);
procedure TengShaderGeneratorArgs.PopFlags;
begin
fFlagStack.PopLast(true);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.PopProcParams;
begin
fProcParams.PopLast;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderGeneratorArgs.AddText(const aText: String): TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtNormal, aText));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddToken(const aToken: String);
function TengShaderGeneratorArgs.AddToken(const aToken: String): TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtToken, aToken));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddCommandEnd(const aToken: String);
function TengShaderGeneratorArgs.AddCommandEnd(const aToken: String): TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtCommandEnd, aToken));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddLineBreak;
function TengShaderGeneratorArgs.AddLineBreak: TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtLineBreak, ''));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.BeginBlock;
function TengShaderGeneratorArgs.BeginBlock(const aIndent: Integer): TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtBlockBegin, ''));
fCode.Last.Items.Add(TCodePart.Create(gtBlockBegin, '', aIndent));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.EndBlock;
function TengShaderGeneratorArgs.EndBlock: TengShaderGeneratorArgs;
begin
fCode.Last.Items.Add(TCodePart.Create(gtBlockEnd, ''));
result := self;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengShaderPart);
procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengMetaData);
begin
// TODO
fMetaDataList.Add(aMeta);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddParam(const aParam: TengShaderPart);
procedure TengShaderGeneratorArgs.AddParameter(const aParam: TengShaderPart);
var
p: TengShaderPart;
s: String;
begin
if not (aParam is TengShaderPartParameter) then
raise EengShaderPartInternal.Create('parameter (' + aParam.ClassName + ') is not a ' + TengShaderPartParameter.ClassName, aParam);
with (aParam as TengShaderPartParameter) do begin
p := fParameters[Name];
if Assigned(p) then begin
s := Format('use of duplicate identifier: %s (%s %d:%d)', [Name, Filename, Line + 1, Col]) + sLineBreak +
'previously declared here:' + sLineBreak +
Format(' %s %d:%d', [p.Filename, p.Line + 1, p.Col]) + sLineBreak;
fRoot.LogMsg(llWarning, s);
fParameters[Name] := aParam;
end else
fParameters.Add(Name, aParam);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.AddProcedure(const aProc: TengShaderPart);
begin
if not (aProc is TengShaderPartProc) then
raise EengShaderPartInternal.Create('parameter (' + aProc.ClassName + ') is not a ' + TengShaderPartProc.ClassName, aProc);
fProcedures.Add(aProc);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderGeneratorArgs.ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer;
var
csi: TCodeStackItem;
i, len: Integer;
s: String;
begin
csi := fCode.Last;
if not Assigned(aCommand) then
exit;

// find last command end token
while (csi.Items.Last.Token <> gtCommandEnd) do
aCommand.Items.PushFirst(csi.Items.PopLast(false));

// move forward to first code part with text
while (aCommand.Items.First.Token <> gtNormal) or (Trim(aCommand.Items.First.Text) = '') do
csi.Items.PushLast(aCommand.Items.PopFirst(false));

// extract leading whitespaces
i := 1;
s := aCommand.Items.First.Text;
len := Length(s);
while (s[i] in WHITESPACES) and (i <= len) do
inc(i);
csi.Items.PushLast(TCodePart.Create(gtNormal, Copy(s, 1, i-1)));
aCommand.Items.First.Text := copy(s, i, len-i+1);
result := i - 1;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.ReplaceIdents(const aOld, aNew: TStrings);
var
rx: TRegExpr;
i: Integer;
cp: TCodePart;
begin
// TODO
if (aOld.Count <> aNew.Count) then
raise EengShaderPartInternal.Create('old and new ident must have the same size');
rx := TRegExpr.Create;
try
for i := 0 to aOld.Count-1 do begin
rx.Expression := '([^A-z0-9_]+|^)' + aOld[i] + '([^A-z0-9_]+|$)';
for cp in fCode.Last.Items do
cp.Text := rx.Replace(cp.Text, '$1' + aNew[i] + '$2', true);
end;
finally
FreeAndNil(rx);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String);
var
rx: TRegExpr;
RetCount, i, j: Integer;
csi: TCodeStackItem;
cp: TCodePart;
s: String;
begin
rx := TRegExpr.Create;
try
rx.Expression := '([^A-z0-9_]+|^)return([^A-z0-9_]+|$)';
csi := fCode.Last;

// find number of "return" in code
RetCount := 0;
for cp in csi.Items do begin
s := cp.Code;
if rx.Exec(s) then
inc(RetCount);
end;

// no "return" found
if (RetCount = 0) then begin
raise EengShaderPartInternal.Create('expected "return" token in function');

// more than one "return"
end else if (RetCount > 1) then begin
// find block begin
i := 0;
while (csi.Items[i].Token <> gtBlockBegin) and (i < csi.Items.Count) do
inc(i);
if (i < csi.Items.Count)
then inc(i)
else i := 0;

// insert temp variable
s := Format('%s_ret%.4d', [aName, fInlineReturnCounter]);
inc(fInlineReturnCounter);
csi.Items.Insert(i, TCodePart.Create(gtLineBreak, ''));
csi.Items.Insert(i+1, TCodePart.Create(gtNormal, aRetType + ' ' + s));
csi.Items.Insert(i+2, TCodePart.Create(gtCommandEnd, ';'));
csi.Items.Insert(i+3, TCodePart.Create(gtLineBreak, ''));

// replace "return" with temp variable
for cp in csi.Items do
cp.Text := rx.Replace(cp.Text, '$1' + s + ' =$2', true);

// merge code
csi.Merge(aCommand, csi.Items.Count);
AddText(s);

// exact one "return"
end else begin
i := csi.Items.Count-1;
while (i > 0) do begin
cp := csi.Items[i];
if rx.Exec(cp.Text) then begin
csi.Items.Insert(i, TCodePart.Create(gtNormal, rx.Match[1]));
cp.Text := rx.Replace(cp.Text, '(', true);

// replace last gtCommandEnd with ')' and delete everything behind
j := csi.Items.Count-1;
while (j > i) and not (csi.Items[j].Token = gtCommandEnd) do
dec(j);
if (j > i) then
csi.Items[j] := TCodePart.Create(gtNormal, ')');
while (csi.Items.Count-1 > j) do
csi.Items.PopLast(true);

// merge
csi.Merge(aCommand, i+1);
end;
dec(i);
end;
end;
finally
FreeAndNil(rx);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderGeneratorArgs.GenerateCode(const aCode: TengShaderCode);
begin
GenerateProcedureCode;
GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVar));
GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVarying));
GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartUniform));
GenerateMetaCode;
fCode.Last.GenerateCode(aCode);
end;

@@ -380,14 +772,26 @@ end;
constructor TengShaderGeneratorArgs.Create(const aRoot: TengShaderPart);
begin
inherited Create;
fCode := TCodeStack.Create(true);
fRoot := aRoot;
fCode := TCodeStack.Create(true);
fFlagStack := TengGenerateFlagsStack.Create();
fMetaDataList := TengMetaDataList.Create(false);
fParameters := TParameterMap.Create(false);
fProcedures := TProcedureList.Create(false);
fProcParams := TProcParamStack.Create(false);
fRoot := aRoot;
fInlineReturnCounter := 0;
PushCode;
PushFlags([ gfAddParameterItem, gfAddProcedureItem ]);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengShaderGeneratorArgs.Destroy;
begin
FreeAndNil(fProcParams);
FreeAndNil(fProcedures);
FreeAndNil(fParameters);
FreeAndNil(fMetaDataList);
FreeAndNil(fFlagStack);
FreeAndNil(fCode);
inherited Destroy;
end;


+ 1
- 1
uengShaderPart.pas Bestand weergeven

@@ -226,7 +226,7 @@ end;
function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
begin
if not GetParent(aType, result) then
raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self);
raise EengShaderPartInternal.Create(GetTokenName + ' has no parent of type ' + aType.GetTokenName, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 97
- 2
uengShaderPartCall.pas Bestand weergeven

@@ -44,6 +44,12 @@ type
{ Class Methods }
protected
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ Code Generation }
public
procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;

{ Class Methods }
public
class function GetTokenName: String; override;
class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
@@ -52,7 +58,8 @@ type
implementation

uses
uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper;
uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes,
uengShaderFileHelper, uengShaderGenerator, uengShaderFile;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartCall////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -95,9 +102,34 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartCall.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
var
sr: TengSearchResults;
walker: TengProcSearchWalker;
proc: TengShaderPartProc;
begin
inherited GenerateCodeIntern(aArgs);
// TODO
sr := TengSearchResults.Create;
walker := TengProcSearchWalker.Create(sr);
try
walker.Name := Name;
walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited];
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
walker.Run(aArgs.Root);
proc := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc);

aArgs.PushProcParams(fParameters);
aArgs.PushFlags(aArgs.Flags - [gfGenerateProcedureCode, gfGenerateInlineCode] + [gfGenerateProcedureCall]);
try
proc.GenerateCodeIntern(aArgs);
finally
aArgs.PopFlags;
aArgs.PopProcParams;
end;
finally
FreeAndNil(walker);
FreeAndNil(sr);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,6 +181,69 @@ begin
result := '';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);

function FindProc: TengShaderPartProc;
var
sr: TengSearchResults;
walker: TengProcSearchWalker;
ParentProc: TengShaderPartProc;
begin
sr := TengSearchResults.Create;
walker := TengProcSearchWalker.Create(sr);
try
ParentProc := (GetParent(TengShaderPartProc) as TengShaderPartProc);
walker.Name := Name;
if (walker.Name = '') then
walker.Name := ParentProc.Name;
walker.Owner := ParentProc;
walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited, sfSearchParents];
walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass);
walker.Run(ParentProc);
result := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc);
finally
FreeAndNil(walker);
FreeAndNil(sr);
end;
end;

procedure GenCode(const aProc: TengShaderPartProc; const aParams: TStrings);
begin
aArgs.PushFlags(aArgs.Flags + [gfGenerateInlineCode]);
aArgs.PushProcParams(aParams);
try
aProc.GenerateCodeIntern(aArgs);
finally
aArgs.PopProcParams;
aArgs.PopFlags;
end;
end;

var
proc: TengShaderPartProc;
i: Integer;
params: TStringList;
begin
aArgs.AddToken(GetTokenName);
proc := FindProc;
if (fParameters.Count > 0) then begin
if (fParameters.Count <> proc.ParameterCount) then
raise EengInvalidParamterCount.Create(proc.name + ' expexts ' + IntToStr(proc.ParameterCount) + ' parameters', self);
GenCode(proc, fParameters);
end else begin
params := TStringList.Create;
try
for i := 0 to proc.ParameterCount-1 do
params.Add(proc.Parameters[i].Name);
GenCode(proc, params);
finally
FreeAndNil(params);
end;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TengShaderPartInherited.GetTokenName: String;
begin


+ 24
- 4
uengShaderPartClass.pas Bestand weergeven

@@ -18,7 +18,7 @@ type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartClass = class;
TengShaderPartClassList = specialize TutlSimpleList<TengShaderPartClass>;
TengShaderPartClass = class(TengShaderCodeGenerator)
TengShaderPartClass = class(TengShaderGenerator)
{ Code Loading & Storage }
private { member }
fName: String;
@@ -54,7 +54,8 @@ type
implementation

uses
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair, uengShaderPartScope, uengShaderFile;
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair,
uengShaderPartScope, uengShaderFile, uengShaderPartProc;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartClass///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -173,7 +174,7 @@ begin
walker := TengSearchWalker.Create(sr);
try
walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator);
walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
walker.Run(self);
for p in sr.GetReverseEnumerator do
@@ -188,6 +189,9 @@ end;
procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
var
c: TengShaderPartClass;
sr: TengSearchResults;
walker: TengSearchWalker;
main: TengShaderPartMain;
begin
if (aArgs.Root <> self) then
exit;
@@ -195,7 +199,23 @@ begin
c.GenerateCodeIntern(aArgs);
inherited GenerateCodeIntern(aArgs);

// TODO generate main routine
sr := TengSearchResults.Create;
walker := TengSearchWalker.Create(sr);
try
walker.SearchFlags := [sfSearchChildren, sfEvaluateIf];
walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain);
walker.Run(self);
main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain);
aArgs.PushFlags([gfGenerateProcedureCode]);
try
main.GenerateCodeIntern(aArgs);
finally
aArgs.PopFlags;
end;
finally
FreeAndNil(walker);
FreeAndNil(sr);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 5
- 1
uengShaderPartCntr.pas Bestand weergeven

@@ -154,8 +154,12 @@ end;
procedure TengShaderPartCntr.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
var
p: TengShaderCodePart;
s: String;
begin
aArgs.AddToken(GetTokenName);
s := GetTokenName;
if (s = '') then
s := ClassName;
aArgs.AddToken(s);
try
for p in fChildren do
p.GenerateCodeIntern(aArgs);


+ 3
- 60
uengShaderPartMeta.pas Bestand weergeven

@@ -7,33 +7,9 @@ interface

uses
Classes, SysUtils,
uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs;
uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs, uengShaderFileTypes;

type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengMetaType = (
metaUnknown,
metaNormal,
metaVersion,
metaExtension,
metaLayout);
TengMetaData = class(TObject)
private
fMetaType: TengMetaType;
fName: String;
fValues: TStringList;
function GetValues: TStrings;
public
property MetaType: TengMetaType read fMetaType;
property Name: String read fName;
property Values: TStrings read GetValues;

procedure Assign(const aValues: TengMetaData);

constructor Create(const aName: String; const aType: TengMetaType);
destructor Destroy; override;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TengShaderPartMeta = class(TengShaderCodePart)
{ Code Loading & Storage }
@@ -61,40 +37,7 @@ type
implementation

uses
uengShaderFileConstants, uengShaderFileTypes;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengMetaData//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengMetaData.GetValues: TStrings;
begin
result := fValues;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengMetaData.Assign(const aValues: TengMetaData);
begin
fName := aValues.Name;
fMetaType := aValues.MetaType;
fValues.Clear;
fValues.AddStrings(aValues.Values);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengMetaData.Create(const aName: String; const aType: TengMetaType);
begin
inherited Create;
fName := aName;
fMetaType := aType;
fValues := TStringList.Create;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TengMetaData.Destroy;
begin
FreeAndNil(fValues);
inherited Destroy;
end;
uengShaderFileConstants;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartMeta////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -170,7 +113,7 @@ end;
procedure TengShaderPartMeta.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
begin
inherited GenerateCodeIntern(aArgs);
aArgs.AddMeta(self);
aArgs.AddMeta(fData);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 12
- 12
uengShaderPartParameter.pas Bestand weergeven

@@ -129,7 +129,7 @@ procedure TengShaderPartParameter.GenerateCodeIntern(const aArgs: TengShaderGene
begin
if (gfAddParameterItem in aArgs.Flags) then begin
inherited GenerateCodeIntern(aArgs);
aArgs.AddParam(self);
aArgs.AddParameter(self);
end;
end;

@@ -167,8 +167,11 @@ end;
procedure TengShaderPartVar.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
begin
inherited GenerateCodeIntern(aArgs);
if (gfGenerateParameterItemCode in aArgs.Flags) then begin
// TODO
if (gfGenerateParameterCode in aArgs.Flags) then begin
aArgs.AddText(format('%*s %s', [aArgs.MaxParameterLength, fType, fName]));
if (fDefaultValue <> '') then
aArgs.AddText(' = ' + fDefaultValue);
aArgs.AddCommandEnd(';');
end;
end;

@@ -184,9 +187,8 @@ end;
procedure TengShaderPartVarying.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
begin
inherited GenerateCodeIntern(aArgs);
if (gfGenerateParameterItemCode in aArgs.Flags) then begin
// TODO
end;
if (gfGenerateParameterCode in aArgs.Flags) then
aArgs.AddText(Format('varying %*s %s;', [aArgs.MaxParameterLength, fType, fName]));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -201,9 +203,8 @@ end;
procedure TengShaderPartUniform.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
begin
inherited GenerateCodeIntern(aArgs);
if (gfGenerateParameterItemCode in aArgs.Flags) then begin
// TODO
end;
if (gfGenerateParameterCode in aArgs.Flags) then
aArgs.AddText(Format('uniform %*s %s;', [aArgs.MaxParameterLength, fType, fName]));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -242,9 +243,8 @@ end;
procedure TengShaderPartConst.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
begin
inherited GenerateCodeIntern(aArgs);
if (gfGenerateParameterItemCode in aArgs.Flags) then begin
// TODO
end;
if (gfGenerateParameterCode in aArgs.Flags) then
aArgs.AddText(Format('const %*s %s;', [aArgs.MaxParameterLength, fType, fName]));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 178
- 3
uengShaderPartProc.pas Bestand weergeven

@@ -7,7 +7,7 @@ interface

uses
Classes, SysUtils,
uengShaderPart, uengShaderPartScope, uengShaderFileParser
uengShaderPart, uengShaderPartScope, uengShaderFileParser, uengShaderGeneratorArgs

{$IFDEF USE_BITSPACE_UTILS}
, uutlGenerics;
@@ -30,15 +30,26 @@ type
fName: String;
fIsInline: Boolean;
fParameters: TengShaderPartProcParamList;
function GetParameter(const aIndex: Integer): TengShaderPartProcParam;
function GetParameterCount: Integer;
protected
function GetHeaderText: String; virtual;
function GetText: String; override;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ Code Generation }
protected
function GenerateHeaderCode: String; virtual;
procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); virtual;
public
procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;

{ General }
public
property Name: String read fName;
property IsInline: Boolean read fIsInline;
property Name: String read fName;
property IsInline: Boolean read fIsInline;
property ParameterCount: Integer read GetParameterCount;
property Parameters[const aIndex: Integer]: TengShaderPartProcParam read GetParameter;

constructor Create(const aParent: TengShaderPart); override;
destructor Destroy; override;
@@ -55,6 +66,10 @@ type
function GetHeaderText: String; override;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ Code Generation }
protected
function GenerateHeaderCode: String; override;

{ General }
public
class function GetTokenName: String; override;
@@ -69,6 +84,11 @@ type
function GetHeaderText: String; override;
function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;

{ Code Generation }
protected
function GenerateHeaderCode: String; override;
procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); override;

{ Class Methods }
public
class function GetTokenName: String; override;
@@ -77,10 +97,23 @@ type
implementation

uses
RegExpr,
uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TengShaderPartProc////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartProc.GetParameter(const aIndex: Integer): TengShaderPartProcParam;
begin
result := fParameters[aIndex];
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartProc.GetParameterCount: Integer;
begin
result := fParameters.Count;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartProc.GetHeaderText: String;
var
@@ -150,6 +183,102 @@ begin
result := CheckEndToken(aArgs, self);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartProc.GenerateHeaderCode: String;
var
p: TengShaderPartProcParam;
begin
result := '';
for p in fParameters do begin
if (result <> '') then
result := result + ', ';
result := result + p.Typ + ' ' + p.Name;
end;
if (result = '') then
result := 'void';
result := 'void ' + fName + '(' + result + ')';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartProc.GenerateInlineCode(const aArgs: TengShaderGeneratorArgs);
var
p: TengShaderPartProcParam;
old, new: TStringList;
rx: TRegExpr;
s: String;
begin
aArgs.PushCode;
rx := TRegExpr.Create;
old := TStringList.Create;
new := TStringList.Create;
try
inherited GenerateCodeIntern(aArgs);

// prepare old parameters
for p in fParameters do
old.Add(p.Name);

// prepate new paramaters
rx.Expression := '[^A-z0-9_]+';
for s in aArgs.ProcParams do begin
if rx.Exec(s)
then new.Add('(' + s + ')')
else new.Add(s);
end;

// replace parameters
aArgs.ReplaceIdents(old, new);
finally
FreeAndNil(rx);
FreeAndNil(old);
FreeAndNil(new);
aArgs.PopCode([pcfAppend]);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartProc.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
var
s, params: String;
begin
// generate inline code
if (aArgs.Flags * [gfGenerateProcedureCall, gfGenerateProcedureCode] <> []) and
((gfGenerateInlineCode in aArgs.Flags) or fIsInline) then
begin
GenerateInlineCode(aArgs);
// TODO: ignore next command end?!

// generate code
end else if (gfGenerateProcedureCode in aArgs.Flags) then begin
aArgs
.AddLineBreak
.AddText(GenerateHeaderCode)
.AddLineBreak
.AddCommandEnd('{')
.AddLineBreak
.BeginBlock(4);
try
inherited GenerateCodeIntern(aArgs);
finally
aArgs
.EndBlock
.AddCommandEnd('}')
.AddLineBreak;
end;

// generate call
end else if (gfGenerateProcedureCall in aArgs.Flags) then begin
params := '';
for s in aArgs.ProcParams do begin
if (params <> '') then
params := params + ', ';
params := params + s;
end;
aArgs.AddText(fName + '(' + params + ')');
aArgs.AddProcedure(self);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TengShaderPartProc.Create(const aParent: TengShaderPart);
begin
@@ -197,6 +326,12 @@ begin
inherited ParseIntern(aArgs, aParams);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartMain.GenerateHeaderCode: String;
begin
result := 'void main(void)';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TengShaderPartMain.GetTokenName: String;
begin
@@ -232,6 +367,46 @@ begin
result := inherited ParseIntern(aArgs, aParams);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TengShaderPartFunc.GenerateHeaderCode: String;
var
p: TengShaderPartProcParam;
begin
result := '';
for p in fParameters do begin
if (result <> '') then
result := result + ', ';
result := result + p.Typ + ' ' + p.Name;
end;
if (result = '') then
result := 'void';
result := fReturnType + ' ' + fName + '(' + result + ')';
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TengShaderPartFunc.GenerateInlineCode(const aArgs: TengShaderGeneratorArgs);
var
csi: TengShaderGeneratorArgs.TCodeStackItem;
indent: Integer;
begin
csi := TengShaderGeneratorArgs.TCodeStackItem.Create;
try
indent := aArgs.ExtractCurrentCommand(csi);
aArgs.PushCode;
aArgs.BeginBlock;
try
inherited GenerateInlineCode(aArgs);
finally
aArgs.EndBlock;
aArgs.AddText(StringOfChar(' ', indent));
aArgs.ReplaceReturns(csi, fReturnType, fName);
aArgs.PopCode([pcfAppend]);
end;
finally
FreeAndNil(csi);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class function TengShaderPartFunc.GetTokenName: String;
begin


Laden…
Annuleren
Opslaan