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
82ae8c31
Commit
82ae8c31
authored
Jun 13, 2017
by
John Kessenich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
HLSL: Fix #924: Convert between two different arrays with cast.
parent
0320d090
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
122 additions
and
7 deletions
+122
-7
hlsl.constructArray.vert.out
Test/baseResults/hlsl.constructArray.vert.out
+0
-0
hlsl.constructArray.vert
Test/hlsl.constructArray.vert
+10
-0
ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.cpp
+3
-0
Hlsl.FromFile.cpp
gtests/Hlsl.FromFile.cpp
+1
-0
hlslGrammar.cpp
hlsl/hlslGrammar.cpp
+11
-1
hlslParseHelper.cpp
hlsl/hlslParseHelper.cpp
+96
-6
hlslParseHelper.h
hlsl/hlslParseHelper.h
+1
-0
No files found.
Test/baseResults/hlsl.constructArray.vert.out
0 → 100755
View file @
82ae8c31
This diff is collapsed.
Click to expand it.
Test/hlsl.constructArray.vert
0 → 100644
View file @
82ae8c31
float4
main
()
:
SV_POSITION
{
int4
int4_array
[
3
];
float4
float4_array_times
[
2
]
=
(
float4
[
2
])
int4_array
;
float2
float2_array_times2
[
4
]
=
(
float2
[
4
])
int4_array
;
int4
int4_array2
[
2
]
=
(
int4
[
2
])
int4_array
;
int
int1_array
[
2
]
=
(
int
[
2
])
int4_array
;
return
(
float4
)
0
.
0
;
}
glslang/MachineIndependent/ParseHelper.cpp
View file @
82ae8c31
...
@@ -5425,6 +5425,9 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
...
@@ -5425,6 +5425,9 @@ TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const
// Test for the correctness of the parameters passed to various constructor functions
// Test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right data type, if allowed and required.
// and also convert them to the right data type, if allowed and required.
//
//
// 'node' is what to construct from.
// 'type' is what type to construct.
//
// Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
// Returns nullptr for an error or the constructed node (aggregate or typed) for no error.
//
//
TIntermTyped
*
TParseContext
::
addConstructor
(
const
TSourceLoc
&
loc
,
TIntermNode
*
node
,
const
TType
&
type
)
TIntermTyped
*
TParseContext
::
addConstructor
(
const
TSourceLoc
&
loc
,
TIntermNode
*
node
,
const
TType
&
type
)
...
...
gtests/Hlsl.FromFile.cpp
View file @
82ae8c31
...
@@ -100,6 +100,7 @@ INSTANTIATE_TEST_CASE_P(
...
@@ -100,6 +100,7 @@ INSTANTIATE_TEST_CASE_P(
{
"hlsl.comparison.vec.frag"
,
"main"
},
{
"hlsl.comparison.vec.frag"
,
"main"
},
{
"hlsl.conditional.frag"
,
"PixelShaderFunction"
},
{
"hlsl.conditional.frag"
,
"PixelShaderFunction"
},
{
"hlsl.constantbuffer.frag"
,
"main"
},
{
"hlsl.constantbuffer.frag"
,
"main"
},
{
"hlsl.constructArray.vert"
,
"main"
},
{
"hlsl.constructexpr.frag"
,
"main"
},
{
"hlsl.constructexpr.frag"
,
"main"
},
{
"hlsl.constructimat.frag"
,
"main"
},
{
"hlsl.constructimat.frag"
,
"main"
},
{
"hlsl.depthGreater.frag"
,
"PixelShaderFunction"
},
{
"hlsl.depthGreater.frag"
,
"PixelShaderFunction"
},
...
...
hlsl/hlslGrammar.cpp
View file @
82ae8c31
...
@@ -2732,9 +2732,14 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
...
@@ -2732,9 +2732,14 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
if
(
acceptTokenClass
(
EHTokLeftParen
))
{
if
(
acceptTokenClass
(
EHTokLeftParen
))
{
TType
castType
;
TType
castType
;
if
(
acceptType
(
castType
))
{
if
(
acceptType
(
castType
))
{
// recognize any array_specifier as part of the type
TArraySizes
*
arraySizes
=
nullptr
;
acceptArraySpecifier
(
arraySizes
);
if
(
arraySizes
!=
nullptr
)
castType
.
newArraySizes
(
*
arraySizes
);
TSourceLoc
loc
=
token
.
loc
;
if
(
acceptTokenClass
(
EHTokRightParen
))
{
if
(
acceptTokenClass
(
EHTokRightParen
))
{
// We've matched "(type)" now, get the expression to cast
// We've matched "(type)" now, get the expression to cast
TSourceLoc
loc
=
token
.
loc
;
if
(
!
acceptUnaryExpression
(
node
))
if
(
!
acceptUnaryExpression
(
node
))
return
false
;
return
false
;
...
@@ -2754,6 +2759,11 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
...
@@ -2754,6 +2759,11 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
// the '(int' part. We must back up twice.
// the '(int' part. We must back up twice.
recedeToken
();
recedeToken
();
recedeToken
();
recedeToken
();
// Note, there are no array constructors like
// (float[2](...))
if
(
arraySizes
!=
nullptr
)
parseContext
.
error
(
loc
,
"parenthesized array constructor not allowed"
,
"([]())"
,
""
,
""
);
}
}
}
else
{
}
else
{
// This isn't a type cast, but it still started "(", so if it is a
// This isn't a type cast, but it still started "(", so if it is a
...
...
hlsl/hlslParseHelper.cpp
View file @
82ae8c31
...
@@ -5401,7 +5401,8 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
...
@@ -5401,7 +5401,8 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
if
(
type
.
isImplicitlySizedArray
())
{
if
(
type
.
isImplicitlySizedArray
())
{
// auto adapt the constructor type to the number of arguments
// auto adapt the constructor type to the number of arguments
type
.
changeOuterArraySize
(
function
.
getParamCount
());
type
.
changeOuterArraySize
(
function
.
getParamCount
());
}
else
if
(
type
.
getOuterArraySize
()
!=
function
.
getParamCount
())
{
}
else
if
(
type
.
getOuterArraySize
()
!=
function
.
getParamCount
()
&&
type
.
computeNumComponents
()
>
size
)
{
error
(
loc
,
"array constructor needs one argument per array element"
,
"constructor"
,
""
);
error
(
loc
,
"array constructor needs one argument per array element"
,
"constructor"
,
""
);
return
true
;
return
true
;
}
}
...
@@ -5430,6 +5431,12 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
...
@@ -5430,6 +5431,12 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
}
}
}
}
// Some array -> array type casts are okay
if
(
arrayArg
&&
function
.
getParamCount
()
==
1
&&
op
!=
EOpConstructStruct
&&
type
.
isArray
()
&&
!
type
.
isArrayOfArrays
()
&&
!
function
[
0
].
type
->
isArrayOfArrays
()
&&
type
.
getVectorSize
()
>=
1
&&
function
[
0
].
type
->
getVectorSize
()
>=
1
)
return
false
;
if
(
arrayArg
&&
op
!=
EOpConstructStruct
&&
!
type
.
isArrayOfArrays
())
{
if
(
arrayArg
&&
op
!=
EOpConstructStruct
&&
!
type
.
isArrayOfArrays
())
{
error
(
loc
,
"constructing non-array constituent from array argument"
,
"constructor"
,
""
);
error
(
loc
,
"constructing non-array constituent from array argument"
,
"constructor"
,
""
);
return
true
;
return
true
;
...
@@ -7336,17 +7343,20 @@ TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TInterm
...
@@ -7336,17 +7343,20 @@ TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TInterm
// Add a constructor, either from the grammar, or other programmatic reasons.
// Add a constructor, either from the grammar, or other programmatic reasons.
//
//
// 'node' is what to construct from.
// 'type' is what type to construct.
//
// Returns the constructed object.
// Return nullptr if it can't be done.
// Return nullptr if it can't be done.
//
//
TIntermTyped
*
HlslParseContext
::
addConstructor
(
const
TSourceLoc
&
loc
,
TIntermTyped
*
node
,
const
TType
&
type
)
TIntermTyped
*
HlslParseContext
::
addConstructor
(
const
TSourceLoc
&
loc
,
TIntermTyped
*
node
,
const
TType
&
type
)
{
{
TIntermAggregate
*
aggrNode
=
node
->
getAsAggregate
();
TOperator
op
=
intermediate
.
mapTypeToConstructorOp
(
type
);
TOperator
op
=
intermediate
.
mapTypeToConstructorOp
(
type
);
// Combined texture-sampler constructors are completely semantic checked
// Combined texture-sampler constructors are completely semantic checked
// in constructorTextureSamplerError()
// in constructorTextureSamplerError()
if
(
op
==
EOpConstructTextureSampler
)
if
(
op
==
EOpConstructTextureSampler
)
return
intermediate
.
setAggregateOperator
(
aggrNode
,
op
,
type
,
loc
);
return
intermediate
.
setAggregateOperator
(
node
->
getAsAggregate
()
,
op
,
type
,
loc
);
TTypeList
::
const_iterator
memberTypes
;
TTypeList
::
const_iterator
memberTypes
;
if
(
op
==
EOpConstructStruct
)
if
(
op
==
EOpConstructStruct
)
...
@@ -7360,7 +7370,8 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp
...
@@ -7360,7 +7370,8 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp
elementType
.
shallowCopy
(
type
);
elementType
.
shallowCopy
(
type
);
bool
singleArg
;
bool
singleArg
;
if
(
aggrNode
)
{
TIntermAggregate
*
aggrNode
=
node
->
getAsAggregate
();
if
(
aggrNode
!=
nullptr
)
{
if
(
aggrNode
->
getOp
()
!=
EOpNull
||
aggrNode
->
getSequence
().
size
()
==
1
)
if
(
aggrNode
->
getOp
()
!=
EOpNull
||
aggrNode
->
getSequence
().
size
()
==
1
)
singleArg
=
true
;
singleArg
=
true
;
else
else
...
@@ -7370,9 +7381,15 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp
...
@@ -7370,9 +7381,15 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyp
TIntermTyped
*
newNode
;
TIntermTyped
*
newNode
;
if
(
singleArg
)
{
if
(
singleArg
)
{
// Handle array -> array conversion
// Constructing an array of one type from an array of another type is allowed,
// assuming there are enough components available (semantic-checked earlier).
if
(
type
.
isArray
()
&&
node
->
isArray
())
newNode
=
convertArray
(
node
,
type
);
// If structure constructor or array constructor is being called
// If structure constructor or array constructor is being called
// for only one parameter inside the structure, we need to call constructAggregate function once.
// for only one parameter inside the structure, we need to call constructAggregate function once.
if
(
type
.
isArray
())
else
if
(
type
.
isArray
())
newNode
=
constructAggregate
(
node
,
elementType
,
1
,
node
->
getLoc
());
newNode
=
constructAggregate
(
node
,
elementType
,
1
,
node
->
getLoc
());
else
if
(
op
==
EOpConstructStruct
)
else
if
(
op
==
EOpConstructStruct
)
newNode
=
constructAggregate
(
node
,
*
(
*
memberTypes
).
type
,
1
,
node
->
getLoc
());
newNode
=
constructAggregate
(
node
,
*
(
*
memberTypes
).
type
,
1
,
node
->
getLoc
());
...
@@ -7537,13 +7554,86 @@ TIntermTyped* HlslParseContext::constructBuiltIn(const TType& type, TOperator op
...
@@ -7537,13 +7554,86 @@ TIntermTyped* HlslParseContext::constructBuiltIn(const TType& type, TOperator op
return
intermediate
.
setAggregateOperator
(
newNode
,
op
,
type
,
loc
);
return
intermediate
.
setAggregateOperator
(
newNode
,
op
,
type
,
loc
);
}
}
// Convert the array in node to the requested type, which is also an array.
// Returns nullptr on failure, otherwise returns aggregate holding the list of
// elements needed to construct the array.
TIntermTyped
*
HlslParseContext
::
convertArray
(
TIntermTyped
*
node
,
const
TType
&
type
)
{
assert
(
node
->
isArray
()
&&
type
.
isArray
());
if
(
node
->
getType
().
computeNumComponents
()
<
type
.
computeNumComponents
())
return
nullptr
;
// TODO: write an argument replicator, for the case the argument should not be
// executed multiple times, yet multiple copies are needed.
TIntermTyped
*
constructee
=
node
->
getAsTyped
();
// track where we are in consuming the argument
int
constructeeElement
=
0
;
int
constructeeComponent
=
0
;
// bump up to the next component to consume
const
auto
getNextComponent
=
[
&
]()
{
TIntermTyped
*
component
;
component
=
handleBracketDereference
(
node
->
getLoc
(),
constructee
,
intermediate
.
addConstantUnion
(
constructeeElement
,
node
->
getLoc
()));
if
(
component
->
isVector
())
component
=
handleBracketDereference
(
node
->
getLoc
(),
component
,
intermediate
.
addConstantUnion
(
constructeeComponent
,
node
->
getLoc
()));
// bump component pointer up
++
constructeeComponent
;
if
(
constructeeComponent
==
constructee
->
getVectorSize
())
{
constructeeComponent
=
0
;
++
constructeeElement
;
}
return
component
;
};
// make one subnode per constructed array element
TIntermAggregate
*
constructor
=
nullptr
;
TType
derefType
(
type
,
0
);
TType
speculativeComponentType
(
derefType
,
0
);
TType
*
componentType
=
derefType
.
isVector
()
?
&
speculativeComponentType
:
&
derefType
;
TOperator
componentOp
=
intermediate
.
mapTypeToConstructorOp
(
*
componentType
);
TType
crossType
(
node
->
getBasicType
(),
EvqTemporary
,
type
.
getVectorSize
());
for
(
int
e
=
0
;
e
<
type
.
getOuterArraySize
();
++
e
)
{
// construct an element
TIntermTyped
*
elementArg
;
if
(
type
.
getVectorSize
()
==
constructee
->
getVectorSize
())
{
// same element shape
elementArg
=
handleBracketDereference
(
node
->
getLoc
(),
constructee
,
intermediate
.
addConstantUnion
(
e
,
node
->
getLoc
()));
}
else
{
// mismatched element shapes
if
(
type
.
getVectorSize
()
==
1
)
elementArg
=
getNextComponent
();
else
{
// make a vector
TIntermAggregate
*
elementConstructee
=
nullptr
;
for
(
int
c
=
0
;
c
<
type
.
getVectorSize
();
++
c
)
elementConstructee
=
intermediate
.
growAggregate
(
elementConstructee
,
getNextComponent
());
elementArg
=
addConstructor
(
node
->
getLoc
(),
elementConstructee
,
crossType
);
}
}
// convert basic types
elementArg
=
intermediate
.
addConversion
(
componentOp
,
derefType
,
elementArg
);
if
(
elementArg
==
nullptr
)
return
nullptr
;
// combine with top-level constructor
constructor
=
intermediate
.
growAggregate
(
constructor
,
elementArg
);
}
return
constructor
;
}
// This function tests for the type of the parameters to the structure or array constructor. Raises
// This function tests for the type of the parameters to the structure or array constructor. Raises
// an error message if the expected type does not match the parameter passed to the constructor.
// an error message if the expected type does not match the parameter passed to the constructor.
//
//
// Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
// Returns nullptr for an error or the input node itself if the expected and the given parameter types match.
//
//
TIntermTyped
*
HlslParseContext
::
constructAggregate
(
TIntermNode
*
node
,
const
TType
&
type
,
int
paramCount
,
const
TSourceLoc
&
loc
)
TIntermTyped
*
HlslParseContext
::
constructAggregate
(
TIntermNode
*
node
,
const
TType
&
type
,
int
paramCount
,
const
TSourceLoc
&
loc
)
{
{
// Handle cases that map more 1:1 between constructor arguments and constructed.
TIntermTyped
*
converted
=
intermediate
.
addConversion
(
EOpConstructStruct
,
type
,
node
->
getAsTyped
());
TIntermTyped
*
converted
=
intermediate
.
addConversion
(
EOpConstructStruct
,
type
,
node
->
getAsTyped
());
if
(
!
converted
||
converted
->
getType
()
!=
type
)
{
if
(
!
converted
||
converted
->
getType
()
!=
type
)
{
error
(
loc
,
""
,
"constructor"
,
"cannot convert parameter %d from '%s' to '%s'"
,
paramCount
,
error
(
loc
,
""
,
"constructor"
,
"cannot convert parameter %d from '%s' to '%s'"
,
paramCount
,
...
...
hlsl/hlslParseHelper.h
View file @
82ae8c31
...
@@ -146,6 +146,7 @@ public:
...
@@ -146,6 +146,7 @@ public:
void
lengthenList
(
const
TSourceLoc
&
,
TIntermSequence
&
list
,
int
size
,
TIntermTyped
*
scalarInit
);
void
lengthenList
(
const
TSourceLoc
&
,
TIntermSequence
&
list
,
int
size
,
TIntermTyped
*
scalarInit
);
TIntermTyped
*
handleConstructor
(
const
TSourceLoc
&
,
TIntermTyped
*
,
const
TType
&
);
TIntermTyped
*
handleConstructor
(
const
TSourceLoc
&
,
TIntermTyped
*
,
const
TType
&
);
TIntermTyped
*
addConstructor
(
const
TSourceLoc
&
,
TIntermTyped
*
,
const
TType
&
);
TIntermTyped
*
addConstructor
(
const
TSourceLoc
&
,
TIntermTyped
*
,
const
TType
&
);
TIntermTyped
*
convertArray
(
TIntermTyped
*
,
const
TType
&
);
TIntermTyped
*
constructAggregate
(
TIntermNode
*
,
const
TType
&
,
int
,
const
TSourceLoc
&
);
TIntermTyped
*
constructAggregate
(
TIntermNode
*
,
const
TType
&
,
int
,
const
TSourceLoc
&
);
TIntermTyped
*
constructBuiltIn
(
const
TType
&
,
TOperator
,
TIntermTyped
*
,
const
TSourceLoc
&
,
bool
subset
);
TIntermTyped
*
constructBuiltIn
(
const
TType
&
,
TOperator
,
TIntermTyped
*
,
const
TSourceLoc
&
,
bool
subset
);
void
declareBlock
(
const
TSourceLoc
&
,
TType
&
,
const
TString
*
instanceName
=
0
,
TArraySizes
*
arraySizes
=
0
);
void
declareBlock
(
const
TSourceLoc
&
,
TType
&
,
const
TString
*
instanceName
=
0
,
TArraySizes
*
arraySizes
=
0
);
...
...
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