| @@ -9,7 +9,7 @@ uses | |||
| Classes, SysUtils, | |||
| uengShaderPart, uengShaderFileParser, uengShaderGeneratorArgs | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} | |||
| , uutlGenerics | |||
| {$ENDIF} | |||
| ; | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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); | |||
| @@ -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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -9,7 +9,7 @@ uses | |||
| Classes, SysUtils, | |||
| uengShaderFileTypes | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} | |||
| , uutlGenerics | |||
| {$ELSE} | |||
| , fgl | |||
| @@ -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; | |||
| @@ -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); | |||
| @@ -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; | |||
| @@ -10,7 +10,7 @@ uses | |||
| uengShaderFileParser, uengShaderFileTypes | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS} | |||
| , uutlGenerics | |||
| {$ELSE} | |||
| , fgl | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -169,7 +169,8 @@ begin | |||
| if Assigned(p) then begin | |||
| p.GenerateCodeIntern(aArgs); | |||
| aArgs.AppendToPrevLine; | |||
| end; | |||
| end else | |||
| aArgs.AddToken(GetTokenName); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -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<TengShaderPartProperty>) | |||
| TengShaderPartPropertyList = class(specialize TutlList<TengShaderPartProperty>) | |||
| 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//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -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 | |||