@@ -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 | |||