Commit d8fe2ca8 by John Kessenich

HLSL: Handle flattened I/O structs passed to function *out* parameters.

parent c86d38bb
...@@ -3,6 +3,12 @@ struct OutParam { ...@@ -3,6 +3,12 @@ struct OutParam {
int2 i; int2 i;
}; };
void fun(out OutParam op)
{
op.v = float2(0.4);
op.i = int2(7);
}
float4 PixelShaderFunction(float4 input, out float4 out1, out OutParam out2, out OutParam out3) : COLOR0 float4 PixelShaderFunction(float4 input, out float4 out1, out OutParam out2, out OutParam out3) : COLOR0
{ {
out1 = input; out1 = input;
...@@ -11,7 +17,7 @@ float4 PixelShaderFunction(float4 input, out float4 out1, out OutParam out2, out ...@@ -11,7 +17,7 @@ float4 PixelShaderFunction(float4 input, out float4 out1, out OutParam out2, out
OutParam local; OutParam local;
local.v = 12.0; local.v = 12.0;
local.i = 13; local.i = 13;
out3 = local; fun(out3);
return out1; return out1;
} }
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits. // For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run). // For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1543" #define GLSLANG_REVISION "Overload400-PrecQual.1544"
#define GLSLANG_DATE "01-Oct-2016" #define GLSLANG_DATE "01-Oct-2016"
...@@ -2246,21 +2246,9 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct ...@@ -2246,21 +2246,9 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
if (builtIn && fnCandidate->getNumExtensions()) if (builtIn && fnCandidate->getNumExtensions())
requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
if (arguments) { // Convert 'in' arguments
// Make sure qualifications work for these arguments. if (arguments)
//TIntermAggregate* aggregate = arguments->getAsAggregate(); addInputArgumentConversions(*fnCandidate, arguments);
//for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
// // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
// // is the single argument itself or its children are the arguments. Only one argument
// // means take 'arguments' itself as the one argument.
// TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments);
// TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier();
// TQualifier& argQualifier = arg->getAsTyped()->getQualifier();
//}
// Convert 'in' arguments
addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node
}
op = fnCandidate->getBuiltInOp(); op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) { if (builtIn && op != EOpNull) {
...@@ -2390,7 +2378,9 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI ...@@ -2390,7 +2378,9 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
// At this early point there is a slight ambiguity between whether an aggregate 'arguments' // At this early point there is a slight ambiguity between whether an aggregate 'arguments'
// is the single argument itself or its children are the arguments. Only one argument // is the single argument itself or its children are the arguments. Only one argument
// means take 'arguments' itself as the one argument. // means take 'arguments' itself as the one argument.
TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); TIntermTyped* arg = function.getParamCount() == 1
? arguments->getAsTyped()
: (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
if (*function[i].type != arg->getType()) { if (*function[i].type != arg->getType()) {
// In-qualified arguments just need an extra node added above the argument to // In-qualified arguments just need an extra node added above the argument to
// convert to the correct type. // convert to the correct type.
...@@ -2401,9 +2391,9 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI ...@@ -2401,9 +2391,9 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
if (shouldFlatten(arg->getType())) { if (shouldFlatten(arg->getType())) {
// Will make a two-level subtree. // Will make a two-level subtree.
// The deepest will copy member-by-member to build the structure to pass. // The deepest will copy member-by-member to build the structure to pass.
// The level above that will be an two-operand EOpComma sequence that follows the copy by the // The level above that will be a two-operand EOpComma sequence that follows the copy by the
// object itself. // object itself.
TSourceLoc dummyLoc; TSourceLoc dummyLoc; // ?? fix these everywhere to be arguments[i]->getLoc()?
dummyLoc.init(); dummyLoc.init();
TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[i].type); TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[i].type);
internalAggregate->getWritableType().getQualifier().makeTemporary(); internalAggregate->getWritableType().getQualifier().makeTemporary();
...@@ -2433,11 +2423,16 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI ...@@ -2433,11 +2423,16 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const
{ {
TIntermSequence& arguments = intermNode.getSequence(); TIntermSequence& arguments = intermNode.getSequence();
const auto needsConversion = [&](int argNum) {
return function[argNum].type->getQualifier().isParamOutput() &&
(*function[argNum].type != arguments[argNum]->getAsTyped()->getType() ||
shouldFlatten(arguments[argNum]->getAsTyped()->getType()));
};
// Will there be any output conversions? // Will there be any output conversions?
bool outputConversions = false; bool outputConversions = false;
for (int i = 0; i < function.getParamCount(); ++i) { for (int i = 0; i < function.getParamCount(); ++i) {
if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) { if (needsConversion(i)) {
outputConversions = true; outputConversions = true;
break; break;
} }
...@@ -2468,18 +2463,21 @@ TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& fu ...@@ -2468,18 +2463,21 @@ TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& fu
// Process each argument's conversion // Process each argument's conversion
for (int i = 0; i < function.getParamCount(); ++i) { for (int i = 0; i < function.getParamCount(); ++i) {
if (*function[i].type != arguments[i]->getAsTyped()->getType()) { if (needsConversion(i)) {
if (function[i].type->getQualifier().isParamOutput()) { // Out-qualified arguments needing conversion need to use the topology setup above.
// Out-qualified arguments need to use the topology set up above. // Do the " ...(tempArg, ...), arg = tempArg" bit from above.
// do the " ...(tempArg, ...), arg = tempArg" bit from above
TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); // Make a temporary for what the function expects the argument to look like.
tempArg->getWritableType().getQualifier().makeTemporary(); TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type);
TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc()); tempArg->getWritableType().getQualifier().makeTemporary();
TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc()); TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
// replace the argument with another node for the same tempArg variable // This makes the deepest level, the member-wise copy
arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc()); TIntermTyped* tempAssign = handleAssign(arguments[i]->getLoc(), EOpAssign, arguments[i]->getAsTyped(), tempArgNode)->getAsAggregate();
} conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
// replace the argument with another node for the same tempArg variable
arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc());
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment