From fc7e3feaa896c2691ec1ef78f2103f228a6e717d Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 12 Sep 2015 19:02:00 +0200 Subject: [PATCH] * fixed some small issues (while testing old shader code) --- uengShaderCodePart.pas | 2 +- uengShaderFile.inc | 6 +- uengShaderFile.pas | 47 +----- uengShaderFileExpression.pas | 10 +- uengShaderFileHelper.pas | 13 ++ uengShaderFileParser.pas | 2 +- uengShaderFileTypes.pas | 4 +- uengShaderGenerator.pas | 58 ++++++- uengShaderGeneratorArgs.pas | 292 ++++++++++++++++++--------------- uengShaderPart.pas | 2 +- uengShaderPartClass.pas | 31 +--- uengShaderPartCntr.pas | 28 ++-- uengShaderPartIf.pas | 3 +- uengShaderPartKeyValuePair.pas | 20 ++- uengShaderPartProc.pas | 5 +- 15 files changed, 282 insertions(+), 241 deletions(-) diff --git a/uengShaderCodePart.pas b/uengShaderCodePart.pas index 7111617..45d06f2 100644 --- a/uengShaderCodePart.pas +++ b/uengShaderCodePart.pas @@ -9,7 +9,7 @@ uses Classes, SysUtils, uengShaderPart, uengShaderFileParser, uengShaderGeneratorArgs -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ENDIF} ; diff --git a/uengShaderFile.inc b/uengShaderFile.inc index a380c2e..780ae75 100644 --- a/uengShaderFile.inc +++ b/uengShaderFile.inc @@ -1,3 +1,3 @@ -{.$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions -{$DEFINE USE_BITSPACE_UTILS} // use bitSpace Utils -{.$DEFINE DEBUG} // enable debug output +{.$DEFINE DEBUGEXPRESSION_ADD_BRACKET} // add brackets to expressions +{$DEFINE SHADER_FILE_USE_BITSPACE_UTILS} // use bitSpace Utils +{.$DEFINE SHADER_FILE_DEBUG} // enable debug output diff --git a/uengShaderFile.pas b/uengShaderFile.pas index 636373e..97c4e8e 100644 --- a/uengShaderFile.pas +++ b/uengShaderFile.pas @@ -13,9 +13,9 @@ interface uses Classes, sysutils, uengShaderPart, uengShaderPartClass, uengShaderFileParser, uengShaderFileTypes, - uengShaderGenerator, uengShaderGeneratorArgs + uengShaderGenerator -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlSerialization {$ENDIF} ; @@ -44,10 +44,6 @@ type procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); - { Code Generation } - public - procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; - { General } private fOnLog: TengShaderFileLogEvent; @@ -68,7 +64,7 @@ type implementation uses - uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper, uengShaderPartProc; + uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -105,13 +101,13 @@ procedure TengShaderFile.UpdateClasses; s: String; begin c := fClasses[aClass.Name]; - if Assigned(c) then begin + if Assigned(c) and (c <> aClass) then begin s := Format('use of duplicate identifier: %s (%s %d:%d)', [aClass.Name, aClass.Filename, aClass.Line + 1, aClass.Col]) + sLineBreak + 'previously declared here:' + sLineBreak + Format(' %s %d:%d', [c.Filename, c.Line + 1, c.Col]) + sLineBreak; LogMsg(llWarning, s); fClasses[aClass.Name] := aClass; - end else + end else if (c <> aClass) then fClasses.Add(aClass.Name, aClass); end; @@ -260,39 +256,6 @@ begin end; end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderFile.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); -var - sr: TengSearchResults; - walker: TengSearchWalker; - main: TengShaderPartMain; -begin - inherited GenerateCodeIntern(aArgs); - if (aArgs.Root = self) then begin - 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; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); var diff --git a/uengShaderFileExpression.pas b/uengShaderFileExpression.pas index 62a706d..167bd7b 100644 --- a/uengShaderFileExpression.pas +++ b/uengShaderFileExpression.pas @@ -343,9 +343,9 @@ begin if not Assigned(fChild) then EengExpression.Create('no child assigned', self); result := - {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF} + {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN+{$ENDIF} EXPRESSION_UNARY_OPERATIONS[fUnaryOp] + ' ' + fChild.GetText - {$IFDEF EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF}; + {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}+TOKEN_OP_GROUP_END{$ENDIF}; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -439,9 +439,9 @@ begin if not Assigned(fFirst) or not Assigned(fSecond) then raise EengExpression.Create('first or second item not assigned'); result := - {$IFDEF EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF} + {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET}TOKEN_OP_GROUP_BEGIN +{$ENDIF} fFirst.GetText + ' ' + EXPRESSION_BINARY_OPERATIONS[fBinaryOp] + ' ' + fSecond.GetText - {$IFDEF EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF}; + {$IFDEF SHADER_FILE_EXPRESSION_ADD_BRACKET} + TOKEN_OP_GROUP_END{$ENDIF}; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -693,7 +693,7 @@ begin walker := TengKeyValuePairSearchWalker.Create(sr); try walker.Name := param.Name; - walker.SearchFlags := [sfSearchChildren, sfSearchParents]; + walker.SearchFlags := [sfSearchChildren, sfSearchParents, sfSearchInherited]; walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); diff --git a/uengShaderFileHelper.pas b/uengShaderFileHelper.pas index d49af75..6351f2b 100644 --- a/uengShaderFileHelper.pas +++ b/uengShaderFileHelper.pas @@ -41,6 +41,7 @@ type TengSearchResults = class(TengShaderPartList) public + function Add(const aItem: TengShaderPart): Integer; reintroduce; constructor Create; end; @@ -193,6 +194,18 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengSearchResults.Add(const aItem: TengShaderPart): Integer; +var + i: Integer; +begin + result := -1; + for i := 0 to Count-1 do + if (Items[i] = aItem) then + exit; + result := inherited Add(aItem); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderFileParser.pas b/uengShaderFileParser.pas index 2e5ac5a..0429080 100644 --- a/uengShaderFileParser.pas +++ b/uengShaderFileParser.pas @@ -9,7 +9,7 @@ uses Classes, SysUtils, uengShaderFileTypes -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ELSE} , fgl diff --git a/uengShaderFileTypes.pas b/uengShaderFileTypes.pas index 44c1f8b..f8f3db4 100644 --- a/uengShaderFileTypes.pas +++ b/uengShaderFileTypes.pas @@ -8,14 +8,14 @@ interface uses Classes, SysUtils -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlSerialization, uutlCommon, uutlGenerics {$ENDIF} ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} IengShaderFileWriter = uutlSerialization.IutlFileWriter; IengShaderFileReader = uutlSerialization.IutlFileReader; TengShaderFileReader = uutlSerialization.TutlSimpleFileReader; diff --git a/uengShaderGenerator.pas b/uengShaderGenerator.pas index b796914..4a1498a 100644 --- a/uengShaderGenerator.pas +++ b/uengShaderGenerator.pas @@ -47,6 +47,9 @@ type implementation +uses + uengShaderFile, uengShaderFileHelper, uengShaderPartProc, uengShaderPartParameter; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -98,13 +101,16 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); var + i: Integer; l: TengShaderPartPropertyList; p: TengShaderPartProperty; s: String; begin + i := -1; l := fPropertyMap[aProp.Name]; if Assigned(l) then begin - if aShowWarning then begin + i := l.IndexOf(aProp); + if aShowWarning and (i >= 0) then begin p := l.Last; s := Format('use of duplicate identifier: %s (%s %d:%d)', [aProp.Name, aProp.Filename, aProp.Line + 1, aProp.Col]) + sLineBreak + 'previously declared here:' + sLineBreak + @@ -115,9 +121,11 @@ begin l := TengShaderPartPropertyList.Create; fPropertyMap.Add(aProp.Name, l); end; - l.Add(aProp); - if (aProp.Value <> Unassigned) then - l.Value := aProp.Value; + if (i < 0) then begin + l.Add(aProp); + if (aProp.Value <> Unassigned) then + l.Value := aProp.Value; + end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -148,11 +156,53 @@ end; procedure TengShaderGenerator.GenerateCode(const aCode: TengShaderCode); var args: TengShaderGeneratorArgs; + sr: TengSearchResults; + walker: TengSearchWalker; + main: TengShaderPartMain; begin args := TengShaderGeneratorArgs.Create(self); try fPropertyMap.ApplyValues; GenerateCodeIntern(args); + + args.PushCode; + 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); + if (self is TengShaderFile) + then main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr, []) as TengShaderPartMain) + else main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain); + if Assigned(main) then begin + args.PushFlags((args.Flags * [gfAddProcedureItem, gfAddParameterItem]) + [gfGenerateProcedureCode, gfGenerateProcedureMain]); + try + main.GenerateCodeIntern(args); + finally + args.PopFlags; + end; + end; + + args.GenerateProcedureCode; + args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVar)); + args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVarying)); + args.GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartUniform)); + finally + FreeAndNil(walker); + FreeAndNil(sr); + args.PopCode([pcfAppend, pcfAddEmptyLine]); + end; + + args.PushCode; + try + args.GenerateMetaCode; + finally + args.PopCode([pcfPrepend, pcfAddEmptyLine]); + end; + args.GenerateCode(aCode); finally FreeAndNil(args); diff --git a/uengShaderGeneratorArgs.pas b/uengShaderGeneratorArgs.pas index dc285a2..22f862f 100644 --- a/uengShaderGeneratorArgs.pas +++ b/uengShaderGeneratorArgs.pas @@ -9,7 +9,7 @@ uses Classes, SysUtils, uengShaderFileTypes, uengShaderPart -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ENDIF} ; @@ -38,13 +38,14 @@ type TengShaderGeneratorArgs = class(TObject) private type TengGeneratorToken = ( - 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) - gtAppendToPrev = 5, // append current line to prev line - gtToken = 6 // 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) + gtAppendToPrev = 5, // append current line to prev line + gtIgnoreNextCommandEnd = 6, // ignore next command end + gtToken = 7 // code token (like '$INCLUDE' or '$IF') ); TCodePart = class(TObject) @@ -100,10 +101,6 @@ type 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 GetFlags; @@ -125,6 +122,7 @@ type function BeginBlock(const aIndent: Integer = High(Integer)): TengShaderGeneratorArgs; function EndBlock(const aCanAppend: Boolean = false): TengShaderGeneratorArgs; function AppendToPrevLine: TengShaderGeneratorArgs; + function IgnoreNextCommandEnd: TengShaderGeneratorArgs; procedure AddMeta(const aMeta: TengMetaData); procedure AddParameter(const aParam: TengShaderPart); @@ -134,6 +132,10 @@ type function ReplaceIdents(const aOld, aNew: TStrings): TengShaderGeneratorArgs; function ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String): TengShaderGeneratorArgs; + procedure GenerateParameterCode(const aTypes: CengShaderPartArr); + procedure GenerateProcedureCode; + procedure GenerateMetaCode; + procedure GenerateCode(const aCode: TengShaderCode); constructor Create(const aRoot: TengShaderPart); @@ -267,10 +269,11 @@ end; procedure TengShaderGeneratorArgs.TCodeStackItem.GenerateCode(const aCode: TengShaderCode); type TGenFlag = ( - 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) - gfAddToPrev // add current line to previouse line + 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) + gfAddToPrev, // add current line to previouse line + gfIgnoreNextCommandEnd ); TGenFlags = set of TGenFlag; @@ -279,7 +282,7 @@ var f: TGenFlags; cb: TCodeBlock; -{$IFDEF DEBUG} +{$IFDEF SHADER_FILE_DEBUG} procedure GenerateDebugCode; var cp: TCodePart; @@ -359,6 +362,7 @@ var var cp: TCodePart; tmp: Integer; + s: String; begin while (i < fItems.Count) do begin cp := fItems[i]; @@ -406,22 +410,36 @@ var end; gtBlockEnd: begin - {$IFDEF DEBUG} + {$IFDEF SHADER_FILE_DEBUG} GenerateCurrentCode(Format('------====== DEBUG STEP BEFORE INDENT (%d) ======------', [aCurrentBlockIndent])); {$ENDIF} IndentBlock(aDepth, aCurrentBlockIndent); - {$IFDEF DEBUG} + {$IFDEF SHADER_FILE_DEBUG} GenerateCurrentCode(Format('------====== DEBUG STEP AFTER INDENT (%d) ======------', [aCurrentBlockIndent])); {$ENDIF} exit; end; + gtIgnoreNextCommandEnd: begin + include(f, gfIgnoreNextCommandEnd); + end; + gtAppendToPrev: begin if (Trim(cb.Last) = '') and not (gfPrevIsEmpty in f) then include(f, gfAddToPrev); end; + + gtCommandEnd: begin + if (gfIgnoreNextCommandEnd in f) + then exclude(f, gfIgnoreNextCommandEnd) + else cb.Last := cb.Last + cp.Code; + end; + else - cb.Last := cb.Last + cp.Code; + s := cp.Code; + if (Trim(s) <> '') then + exclude(f, gfIgnoreNextCommandEnd); + cb.Last := cb.Last + s; end; end; end; @@ -429,7 +447,7 @@ var var s, e: Integer; begin -{$IFDEF DEBUG} +{$IFDEF SHADER_FILE_DEBUG} GenerateDebugCode; {$ENDIF} @@ -446,7 +464,7 @@ begin dec(e); for i := s to e do aCode.Add( - {$IFDEF DEBUG} + {$IFDEF SHADER_FILE_DEBUG} Format('[%02d]%s|', [cb.Depth[i], cb[i]]) {$ELSE} cb[i] @@ -496,113 +514,6 @@ 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; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderGeneratorArgs.PushCode: TengShaderGeneratorArgs; begin @@ -711,6 +622,13 @@ begin result := self; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderGeneratorArgs.IgnoreNextCommandEnd: TengShaderGeneratorArgs; +begin + fCode.Last.Items.Add(TCodePart.Create(gtIgnoreNextCommandEnd, '')); + result := self; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengMetaData); begin @@ -727,13 +645,13 @@ begin 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 + if Assigned(p) and (p <> aParam) 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 + end else if (p <> aParam) then fParameters.Add(Name, aParam); end; end; @@ -883,14 +801,116 @@ begin result := self; 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.GenerateCode(const aCode: TengShaderCode); begin - GenerateProcedureCode; - GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVar)); - GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVarying)); - GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartUniform)); - GenerateMetaCode; fCode.Last.GenerateCode(aCode); end; diff --git a/uengShaderPart.pas b/uengShaderPart.pas index 3900135..f1ce70c 100644 --- a/uengShaderPart.pas +++ b/uengShaderPart.pas @@ -10,7 +10,7 @@ uses uengShaderFileParser, uengShaderFileTypes -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ELSE} , fgl diff --git a/uengShaderPartClass.pas b/uengShaderPartClass.pas index 3cf5db6..8d7158b 100644 --- a/uengShaderPartClass.pas +++ b/uengShaderPartClass.pas @@ -9,7 +9,7 @@ uses Classes, SysUtils, uengShaderPart, uengShaderGenerator, uengShaderGeneratorArgs, uengShaderFileParser -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ENDIF} ; @@ -56,7 +56,7 @@ implementation uses uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair, - uengShaderPartScope, uengShaderFile, uengShaderPartProc; + uengShaderPartScope, uengShaderFile; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -174,9 +174,9 @@ begin sr := TengSearchResults.Create; walker := TengSearchWalker.Create(sr); try + walker.SearchFlags := [sfSearchChildren]; walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty); - walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); - walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); walker.Run(self); for p in sr.GetReverseEnumerator do AddProperty(p as TengShaderPartProperty); @@ -190,32 +190,15 @@ end; procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); var c: TengShaderPartClass; - sr: TengSearchResults; - walker: TengSearchWalker; - main: TengShaderPartMain; begin - if (aArgs.Root <> self) then - exit; for c in fInherited do c.GenerateCodeIntern(aArgs); - inherited GenerateCodeIntern(aArgs); - sr := TengSearchResults.Create; - walker := TengSearchWalker.Create(sr); + aArgs.BeginBlock; try - walker.SearchFlags := [sfSearchChildren, sfEvaluateIf]; - walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain); - walker.Run(self); - main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain); - aArgs.PushFlags([gfGenerateProcedureCode, gfGenerateProcedureMain]); - try - main.GenerateCodeIntern(aArgs); - finally - aArgs.PopFlags; - end; + inherited GenerateCodeIntern(aArgs); finally - FreeAndNil(walker); - FreeAndNil(sr); + aArgs.EndBlock; end; end; diff --git a/uengShaderPartCntr.pas b/uengShaderPartCntr.pas index 2924597..11c528d 100644 --- a/uengShaderPartCntr.pas +++ b/uengShaderPartCntr.pas @@ -15,13 +15,14 @@ type { Code Loading & Storage } private fChildren: TengShaderCodePartList; - procedure AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean = false); function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; protected { virtual getter } function GetCount: Integer; override; function GetChild(const aIndex: Integer): TengShaderPart; override; function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + public + procedure AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean = false); { Code Generation } public @@ -40,13 +41,13 @@ uses uengShaderPartKeyValuePair, uengShaderPartClass, uengShaderPartMessage, uengShaderPartMeta, uengShaderPartCall, uengShaderPartProc, uengShaderPartText, uengShaderPartEcho, uengShaderPartIf, uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment, uengShaderFileConstants -{$IFDEF DEBUG} +{$IFDEF SHADER_FILE_DEBUG} , uengShaderFileTypes {$ENDIF} ; const - TOKEN_CLASSES: array[0..21] of CengShaderCodePart = ( + TOKEN_CLASSES: array[0..22] of CengShaderCodePart = ( TengShaderPartCall, TengShaderPartClass, TengShaderPartConst, @@ -65,6 +66,7 @@ const TengShaderPartMeta, TengShaderPartProc, TengShaderPartProperty, + TengShaderPartThrow, TengShaderPartUniform, TengShaderPartVar, TengShaderPartVarying, @@ -73,14 +75,6 @@ const //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartCntr//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPartCntr.AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean); -begin - if aPrepend - then fChildren.PushFirst(aChild) - else fChildren.PushLast(aChild); -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartCntr.HandleToken(const aToken: String; const aArgs: TengParseArgs): String; var @@ -96,10 +90,6 @@ begin break; end; end; -{$IFDEF DEBUG} - if Assigned(p) then - LogMsg(llDebug, 'ParseText: ' + p.ClassName); -{$ENDIF} if Assigned(p) then result := p.ParseText(aArgs) else result := aToken; @@ -150,6 +140,14 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartCntr.AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean); +begin + if aPrepend + then fChildren.PushFirst(aChild) + else fChildren.PushLast(aChild); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPartCntr.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); var diff --git a/uengShaderPartIf.pas b/uengShaderPartIf.pas index 0bcfeea..d2f2c37 100644 --- a/uengShaderPartIf.pas +++ b/uengShaderPartIf.pas @@ -169,7 +169,8 @@ begin if Assigned(p) then begin p.GenerateCodeIntern(aArgs); aArgs.AppendToPrevLine; - end; + end else + aArgs.AddToken(GetTokenName); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartKeyValuePair.pas b/uengShaderPartKeyValuePair.pas index 6c09614..af9e4ee 100644 --- a/uengShaderPartKeyValuePair.pas +++ b/uengShaderPartKeyValuePair.pas @@ -7,9 +7,9 @@ interface uses Classes, SysUtils, variants, - uengShaderCodePart, uengShaderFileParser + uengShaderPart, uengShaderCodePart, uengShaderFileParser -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics {$ENDIF} ; @@ -34,6 +34,8 @@ type property ValueName: String read fValueName; property Value: Variant read fValue; property DefaultValue: Variant read fDefaultValue; + + constructor Create(const aParent: TengShaderPart; const aName: String; const aValue: Variant); overload; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -48,7 +50,7 @@ type end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartPropertyList = class(specialize TutlSimpleList) + TengShaderPartPropertyList = class(specialize TutlList) private fValue: Variant; public @@ -72,7 +74,7 @@ type implementation uses - uengShaderPart, uengShaderFile, uengShaderPartScope, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + uengShaderFile, uengShaderPartScope, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartPropertyList///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -163,6 +165,16 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartKeyValuePair.Create(const aParent: TengShaderPart; const aName: String; const aValue: Variant); +begin + inherited Create(aParent); + fName := aName; + fValueName := ''; + fValue := aValue; + fDefaultValue := aValue; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartProperty//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartProc.pas b/uengShaderPartProc.pas index c8184c4..ac130db 100644 --- a/uengShaderPartProc.pas +++ b/uengShaderPartProc.pas @@ -9,7 +9,7 @@ uses Classes, SysUtils, uengShaderPart, uengShaderPartScope, uengShaderFileParser, uengShaderGeneratorArgs -{$IFDEF USE_BITSPACE_UTILS} +{$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} , uutlGenerics; {$ELSE} , fgl; @@ -250,7 +250,8 @@ begin ((gfGenerateInlineCode in aArgs.Flags) or fIsInline) then begin GenerateInlineCode(aArgs); - // TODO: ignore next command end?! + if (GetTokenName = TOKEN_PROC) then + aArgs.IgnoreNextCommandEnd; // generate code end else if (gfGenerateProcedureCode in aArgs.Flags) then begin