Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
glslang
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
glslang
Commits
94eb0cd5
Commit
94eb0cd5
authored
May 02, 2020
by
John Kessenich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement swizzles containing 0 and 1 to represent numbers not indexes.
parent
b5f003d7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
155 additions
and
10 deletions
+155
-10
ParseContextBase.cpp
glslang/MachineIndependent/ParseContextBase.cpp
+57
-7
ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.cpp
+92
-1
ParseHelper.h
glslang/MachineIndependent/ParseHelper.h
+4
-1
hlslParseHelper.cpp
hlsl/hlslParseHelper.cpp
+2
-1
No files found.
glslang/MachineIndependent/ParseContextBase.cpp
View file @
94eb0cd5
...
@@ -481,13 +481,32 @@ const TFunction* TParseContextBase::selectFunction(
...
@@ -481,13 +481,32 @@ const TFunction* TParseContextBase::selectFunction(
// Look at a '.' field selector string and change it into numerical selectors
// Look at a '.' field selector string and change it into numerical selectors
// for a vector or scalar.
// for a vector or scalar.
//
//
// These are returned as indexes in selector.
// E.g. ".zy" will become selector = {2, 1}.
//
// Always return some form of swizzle, so the result is always usable.
// Always return some form of swizzle, so the result is always usable.
//
//
// '0' and '1' in the field will mean to use the numeric values of 0 and 1
// rather than the result of an index into the vector.
// These are represented by:
// '0': MaxSwizzleSelectors
// '1': MaxSwizzleSelectors + 1
// E.g., ".z01" will become selector = {2, 4, 5} (if MasSwizzleSelectors == 4).
//
// A leading underscore (prefix) will get ignored.
//
void
TParseContextBase
::
parseSwizzleSelector
(
const
TSourceLoc
&
loc
,
const
TString
&
compString
,
int
vecSize
,
void
TParseContextBase
::
parseSwizzleSelector
(
const
TSourceLoc
&
loc
,
const
TString
&
compString
,
int
vecSize
,
TSwizzleSelectors
<
TVectorSelector
>&
selector
)
TSwizzleSelectors
<
TVectorSelector
>&
selector
,
bool
&
numeric
)
{
{
// a swizzle does not contain numerics unless there are actually numbers
// in it, independent of whether there is a prefix
numeric
=
false
;
// If the field uses prefix syntax, normalize it.
const
int
firstChar
=
compString
[
0
]
==
'_'
;
// Too long?
// Too long?
if
(
compString
.
size
()
>
MaxSwizzleSelectors
)
if
(
compString
.
size
()
-
firstChar
>
MaxSwizzleSelectors
)
error
(
loc
,
"vector swizzle too long"
,
compString
.
c_str
(),
""
);
error
(
loc
,
"vector swizzle too long"
,
compString
.
c_str
(),
""
);
// Use this to test that all swizzle characters are from the same swizzle-namespace-set
// Use this to test that all swizzle characters are from the same swizzle-namespace-set
...
@@ -495,12 +514,13 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
...
@@ -495,12 +514,13 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
exyzw
,
exyzw
,
ergba
,
ergba
,
estpq
,
estpq
,
}
fieldSet
[
MaxSwizzleSelectors
];
enumeric
,
}
fieldSet
[
MaxSwizzleSelectors
+
1
];
// Decode the swizzle string.
// Decode the swizzle string.
int
size
=
std
::
min
(
MaxSwizzleSelectors
,
(
int
)
compString
.
size
()
);
const
int
size
=
std
::
min
(
MaxSwizzleSelectors
,
(
int
)
compString
.
size
()
-
firstChar
);
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
switch
(
compString
[
i
])
{
switch
(
compString
[
i
+
firstChar
])
{
case
'x'
:
case
'x'
:
selector
.
push_back
(
0
);
selector
.
push_back
(
0
);
fieldSet
[
i
]
=
exyzw
;
fieldSet
[
i
]
=
exyzw
;
...
@@ -553,6 +573,17 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
...
@@ -553,6 +573,17 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
fieldSet
[
i
]
=
estpq
;
fieldSet
[
i
]
=
estpq
;
break
;
break
;
case
'0'
:
selector
.
push_back
(
MaxSwizzleSelectors
);
fieldSet
[
i
]
=
enumeric
;
numeric
=
true
;
break
;
case
'1'
:
selector
.
push_back
(
MaxSwizzleSelectors
+
1
);
fieldSet
[
i
]
=
enumeric
;
numeric
=
true
;
break
;
default
:
default
:
error
(
loc
,
"unknown swizzle selection"
,
compString
.
c_str
(),
""
);
error
(
loc
,
"unknown swizzle selection"
,
compString
.
c_str
(),
""
);
break
;
break
;
...
@@ -561,13 +592,14 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
...
@@ -561,13 +592,14 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
// Additional error checking.
// Additional error checking.
for
(
int
i
=
0
;
i
<
selector
.
size
();
++
i
)
{
for
(
int
i
=
0
;
i
<
selector
.
size
();
++
i
)
{
if
(
selector
[
i
]
>=
vecSize
)
{
if
(
selector
[
i
]
<
MaxSwizzleSelectors
&&
selector
[
i
]
>=
vecSize
)
{
error
(
loc
,
"vector swizzle selection out of range"
,
compString
.
c_str
(),
""
);
error
(
loc
,
"vector swizzle selection out of range"
,
compString
.
c_str
(),
""
);
selector
.
resize
(
i
);
selector
.
resize
(
i
);
break
;
break
;
}
}
if
(
i
>
0
&&
fieldSet
[
i
]
!=
fieldSet
[
i
-
1
])
{
if
(
i
>
0
&&
fieldSet
[
i
]
!=
enumeric
&&
fieldSet
[
i
-
1
]
!=
enumeric
&&
fieldSet
[
i
]
!=
fieldSet
[
i
-
1
])
{
error
(
loc
,
"vector swizzle selectors not from the same set"
,
compString
.
c_str
(),
""
);
error
(
loc
,
"vector swizzle selectors not from the same set"
,
compString
.
c_str
(),
""
);
selector
.
resize
(
i
);
selector
.
resize
(
i
);
break
;
break
;
...
@@ -579,6 +611,24 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
...
@@ -579,6 +611,24 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
selector
.
push_back
(
0
);
selector
.
push_back
(
0
);
}
}
void
TParseContextBase
::
replicateRValue
(
TIntermTyped
*
node
,
int
num
,
TVector
<
TIntermTyped
*>&
replicates
)
{
if
(
num
==
0
)
return
;
if
(
num
==
1
)
{
replicates
.
push_back
(
node
);
return
;
}
if
(
node
->
getAsSymbolNode
())
{
replicates
.
push_back
(
node
);
for
(
int
i
=
1
;
i
<
num
;
++
i
)
replicates
.
push_back
(
intermediate
.
addSymbol
(
*
node
->
getAsSymbolNode
()));
}
// WIP: a complex expression needs to be evaluated exactly once, and then
// copies of the result put into the replicates.
}
#ifdef ENABLE_HLSL
#ifdef ENABLE_HLSL
//
//
// Make the passed-in variable information become a member of the
// Make the passed-in variable information become a member of the
...
...
glslang/MachineIndependent/ParseHelper.cpp
View file @
94eb0cd5
...
@@ -886,7 +886,8 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
...
@@ -886,7 +886,8 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
}
}
TSwizzleSelectors
<
TVectorSelector
>
selectors
;
TSwizzleSelectors
<
TVectorSelector
>
selectors
;
parseSwizzleSelector
(
loc
,
field
,
base
->
getVectorSize
(),
selectors
);
bool
numeric
=
false
;
parseSwizzleSelector
(
loc
,
field
,
base
->
getVectorSize
(),
selectors
,
numeric
);
if
(
base
->
isVector
()
&&
selectors
.
size
()
!=
1
&&
base
->
getType
().
contains16BitFloat
())
if
(
base
->
isVector
()
&&
selectors
.
size
()
!=
1
&&
base
->
getType
().
contains16BitFloat
())
requireFloat16Arithmetic
(
loc
,
"."
,
"can't swizzle types containing float16"
);
requireFloat16Arithmetic
(
loc
,
"."
,
"can't swizzle types containing float16"
);
...
@@ -895,6 +896,9 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
...
@@ -895,6 +896,9 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
if
(
base
->
isVector
()
&&
selectors
.
size
()
!=
1
&&
base
->
getType
().
contains8BitInt
())
if
(
base
->
isVector
()
&&
selectors
.
size
()
!=
1
&&
base
->
getType
().
contains8BitInt
())
requireInt8Arithmetic
(
loc
,
"."
,
"can't swizzle types containing (u)int8"
);
requireInt8Arithmetic
(
loc
,
"."
,
"can't swizzle types containing (u)int8"
);
if
(
numeric
)
return
handleNumericDotSwizzle
(
loc
,
base
,
selectors
);
if
(
base
->
isScalar
())
{
if
(
base
->
isScalar
())
{
if
(
selectors
.
size
()
==
1
)
if
(
selectors
.
size
()
==
1
)
return
result
;
return
result
;
...
@@ -927,6 +931,93 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
...
@@ -927,6 +931,93 @@ TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermType
return
result
;
return
result
;
}
}
// Handle a swizzle operation where at least one selector is numeric.
//
// Can return
// - a scalar constant (e.g. for ._1), but converted to the right type
// and constant folded
// - a vector constructor
// - a sequence containing
// 1. evaluation of 'base'
// 2. a scalar constant, converted, folded
// - a sequence containing
// 1. evaluation of 'base'
// 2. a vector constructor
//
// Note that none of the above include swizzle operations.
//
// Note: A vector constructor might require copies of the rvalue being swizzled,
// to avoid the tree accidentally becoming a DAG when there are multiple
// letter swizzles present needing multiple operations to get the
// components. This is quite unlike how swizzles are handled, or any
// other native GLSL operation.
//
TIntermTyped
*
TParseContext
::
handleNumericDotSwizzle
(
const
TSourceLoc
&
loc
,
TIntermTyped
*
base
,
const
TSwizzleSelectors
<
TVectorSelector
>&
selectors
)
{
const
auto
isLetter
=
[](
int
selector
)
{
return
selector
<
MaxSwizzleSelectors
;
};
const
auto
isNumber
=
[
isLetter
](
int
selector
)
{
return
!
isLetter
(
selector
);
};
const
auto
getNumber
=
[](
int
selector
)
{
return
selector
-
MaxSwizzleSelectors
;
};
// The type of the result has the 'base' component type,
// but the component-count of 'selectors'.
TType
type
(
base
->
getBasicType
(),
EvqTemporary
,
selectors
.
size
());
// If only one selector, the result is a scalar.
// But, its type might be changing, so add a constructor.
// This will always result in an already folded scalar front-end constant.
if
(
selectors
.
size
()
==
1
)
{
assert
(
isNumber
(
selectors
[
0
]));
return
addConstructor
(
loc
,
intermediate
.
addConstantUnion
(
getNumber
(
selectors
[
0
]),
loc
),
type
);
// WIP: this is incorrect if 'base' had side effects, it still needs to
// be evaluated as part of a sequence operation, unless the
// specification for this operation says those side effects are ignored.
}
// Otherwise, the result is like making a vector constructor,
// where we know we have more than one argument.
// Collect the arguments.
// This is complicated by the presence of more than one letter selector,
// because we need to reuse the r-value for each one, so it is a rare
// situation of needing to replicate the r-value.
// count the letter selectors (unless the base is a constant))
int
letterCount
=
0
;
if
(
!
base
->
getType
().
getQualifier
().
isFrontEndConstant
())
{
for
(
int
s
=
0
;
s
<
selectors
.
size
();
++
s
)
letterCount
+=
isLetter
(
selectors
[
s
])
?
1
:
0
;
}
// get the replicates
TVector
<
TIntermTyped
*>
replicates
;
replicateRValue
(
base
,
letterCount
,
replicates
);
// process all the selectors to make the vector
TIntermAggregate
*
args
=
nullptr
;
for
(
int
s
=
0
;
s
<
(
int
)
selectors
.
size
();
++
s
)
{
if
(
isNumber
(
selectors
[
s
]))
{
args
=
intermediate
.
growAggregate
(
args
,
intermediate
.
addConstantUnion
(
getNumber
(
selectors
[
s
]),
loc
));
}
else
{
// traditional swizzle selector, which needs to consume the replicates
// (unless base is a constant)
TIntermTyped
*
arg
;
if
(
base
->
getType
().
getQualifier
().
isFrontEndConstant
())
{
arg
=
intermediate
.
foldDereference
(
base
,
selectors
[
s
],
loc
);
}
else
{
TIntermTyped
*
rep
=
replicates
.
back
();
replicates
.
pop_back
();
TIntermTyped
*
index
=
intermediate
.
addConstantUnion
(
selectors
[
s
],
loc
);
arg
=
intermediate
.
addIndex
(
EOpIndexDirect
,
rep
,
index
,
loc
);
}
args
=
intermediate
.
growAggregate
(
args
,
arg
);
}
}
// form the constructor
return
addConstructor
(
loc
,
args
,
type
)
->
getAsAggregate
();
}
void
TParseContext
::
blockMemberExtensionCheck
(
const
TSourceLoc
&
loc
,
const
TIntermTyped
*
base
,
int
member
,
const
TString
&
memberName
)
void
TParseContext
::
blockMemberExtensionCheck
(
const
TSourceLoc
&
loc
,
const
TIntermTyped
*
base
,
int
member
,
const
TString
&
memberName
)
{
{
// a block that needs extension checking is either 'base', or if arrayed,
// a block that needs extension checking is either 'base', or if arrayed,
...
...
glslang/MachineIndependent/ParseHelper.h
View file @
94eb0cd5
...
@@ -217,7 +217,8 @@ protected:
...
@@ -217,7 +217,8 @@ protected:
/* output */
bool
&
tie
);
/* output */
bool
&
tie
);
virtual
void
parseSwizzleSelector
(
const
TSourceLoc
&
,
const
TString
&
,
int
size
,
virtual
void
parseSwizzleSelector
(
const
TSourceLoc
&
,
const
TString
&
,
int
size
,
TSwizzleSelectors
<
TVectorSelector
>&
);
TSwizzleSelectors
<
TVectorSelector
>&
,
bool
&
numeric
);
virtual
void
replicateRValue
(
TIntermTyped
*
node
,
int
n
,
TVector
<
TIntermTyped
*>&
replicates
);
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
TVariable
*
globalUniformBlock
;
// the actual block, inserted into the symbol table
TVariable
*
globalUniformBlock
;
// the actual block, inserted into the symbol table
...
@@ -316,6 +317,8 @@ public:
...
@@ -316,6 +317,8 @@ public:
TIntermTyped
*
handleUnaryMath
(
const
TSourceLoc
&
,
const
char
*
str
,
TOperator
op
,
TIntermTyped
*
childNode
);
TIntermTyped
*
handleUnaryMath
(
const
TSourceLoc
&
,
const
char
*
str
,
TOperator
op
,
TIntermTyped
*
childNode
);
TIntermTyped
*
handleDotDereference
(
const
TSourceLoc
&
,
TIntermTyped
*
base
,
const
TString
&
field
);
TIntermTyped
*
handleDotDereference
(
const
TSourceLoc
&
,
TIntermTyped
*
base
,
const
TString
&
field
);
TIntermTyped
*
handleDotSwizzle
(
const
TSourceLoc
&
,
TIntermTyped
*
base
,
const
TString
&
field
);
TIntermTyped
*
handleDotSwizzle
(
const
TSourceLoc
&
,
TIntermTyped
*
base
,
const
TString
&
field
);
TIntermTyped
*
handleNumericDotSwizzle
(
const
TSourceLoc
&
,
TIntermTyped
*
base
,
const
TSwizzleSelectors
<
TVectorSelector
>&
);
void
blockMemberExtensionCheck
(
const
TSourceLoc
&
,
const
TIntermTyped
*
base
,
int
member
,
const
TString
&
memberName
);
void
blockMemberExtensionCheck
(
const
TSourceLoc
&
,
const
TIntermTyped
*
base
,
int
member
,
const
TString
&
memberName
);
TFunction
*
handleFunctionDeclarator
(
const
TSourceLoc
&
,
TFunction
&
function
,
bool
prototype
);
TFunction
*
handleFunctionDeclarator
(
const
TSourceLoc
&
,
TFunction
&
function
,
bool
prototype
);
TIntermAggregate
*
handleFunctionDefinition
(
const
TSourceLoc
&
,
TFunction
&
);
TIntermAggregate
*
handleFunctionDefinition
(
const
TSourceLoc
&
,
TFunction
&
);
...
...
hlsl/hlslParseHelper.cpp
View file @
94eb0cd5
...
@@ -952,7 +952,8 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
...
@@ -952,7 +952,8 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
}
}
}
else
if
(
base
->
isVector
()
||
base
->
isScalar
())
{
}
else
if
(
base
->
isVector
()
||
base
->
isScalar
())
{
TSwizzleSelectors
<
TVectorSelector
>
selectors
;
TSwizzleSelectors
<
TVectorSelector
>
selectors
;
parseSwizzleSelector
(
loc
,
field
,
base
->
getVectorSize
(),
selectors
);
bool
numeric
=
false
;
parseSwizzleSelector
(
loc
,
field
,
base
->
getVectorSize
(),
selectors
,
numeric
);
if
(
base
->
isScalar
())
{
if
(
base
->
isScalar
())
{
if
(
selectors
.
size
()
==
1
)
if
(
selectors
.
size
()
==
1
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment