Implement atomic ops, bit conversions, fix fwidth stage mask, fix saturate dest modifier.
This commit is contained in:
@@ -771,6 +771,29 @@ void HlslParseContext::handleFunctionArgument(TFunction* function, TIntermTyped*
|
||||
arguments = newArg;
|
||||
}
|
||||
|
||||
//
|
||||
// HLSL atomic operations have slightly different arguments than
|
||||
// GLSL/AST/SPIRV. The semantics are converted below in decomposeIntrinsic.
|
||||
// This provides the post-decomposition equivalent opcode.
|
||||
//
|
||||
TOperator HlslParseContext::mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage)
|
||||
{
|
||||
switch (op) {
|
||||
case EOpInterlockedAdd: return isImage ? EOpImageAtomicAdd : EOpAtomicAdd;
|
||||
case EOpInterlockedAnd: return isImage ? EOpImageAtomicAnd : EOpAtomicAnd;
|
||||
case EOpInterlockedCompareExchange: return isImage ? EOpImageAtomicCompSwap : EOpAtomicCompSwap;
|
||||
case EOpInterlockedMax: return isImage ? EOpImageAtomicMax : EOpAtomicMax;
|
||||
case EOpInterlockedMin: return isImage ? EOpImageAtomicMin : EOpAtomicMin;
|
||||
case EOpInterlockedOr: return isImage ? EOpImageAtomicOr : EOpAtomicOr;
|
||||
case EOpInterlockedXor: return isImage ? EOpImageAtomicXor : EOpAtomicXor;
|
||||
case EOpInterlockedExchange: return isImage ? EOpImageAtomicExchange : EOpAtomicExchange;
|
||||
case EOpInterlockedCompareStore: // TODO: ...
|
||||
default:
|
||||
error(loc, "unknown atomic operation", "unknown op", "");
|
||||
return EOpNull;
|
||||
}
|
||||
}
|
||||
|
||||
// Optionally decompose intrinsics to AST opcodes.
|
||||
//
|
||||
void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments)
|
||||
@@ -825,6 +848,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
|
||||
clamp->getSequence().push_back(intermediate.addConstantUnion(1, type0, loc, true));
|
||||
clamp->setLoc(loc);
|
||||
clamp->setType(node->getType());
|
||||
clamp->getWritableType().getQualifier().makeTemporary();
|
||||
node = clamp;
|
||||
|
||||
break;
|
||||
@@ -944,6 +968,61 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
|
||||
break;
|
||||
}
|
||||
|
||||
case EOpInterlockedAdd: // optional last argument (if present) is assigned from return value
|
||||
case EOpInterlockedMin: // ...
|
||||
case EOpInterlockedMax: // ...
|
||||
case EOpInterlockedAnd: // ...
|
||||
case EOpInterlockedOr: // ...
|
||||
case EOpInterlockedXor: // ...
|
||||
case EOpInterlockedExchange: // always has output arg
|
||||
{
|
||||
TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped();
|
||||
TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped();
|
||||
|
||||
const bool isImage = arg0->getType().isImage();
|
||||
const TOperator atomicOp = mapAtomicOp(loc, op, isImage);
|
||||
|
||||
if (argAggregate->getSequence().size() > 2) {
|
||||
// optional output param is present. return value goes to arg2.
|
||||
TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped();
|
||||
|
||||
TIntermAggregate* atomic = new TIntermAggregate(atomicOp);
|
||||
atomic->getSequence().push_back(arg0);
|
||||
atomic->getSequence().push_back(arg1);
|
||||
atomic->setLoc(loc);
|
||||
atomic->setType(arg0->getType());
|
||||
atomic->getWritableType().getQualifier().makeTemporary();
|
||||
|
||||
node = intermediate.addAssign(EOpAssign, arg2, atomic, loc);
|
||||
} else {
|
||||
// Set the matching operator. Since output is absent, this is all we need to do.
|
||||
node->getAsAggregate()->setOperator(atomicOp);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EOpInterlockedCompareExchange:
|
||||
{
|
||||
TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // dest
|
||||
TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // cmp
|
||||
TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped(); // value
|
||||
TIntermTyped* arg3 = argAggregate->getSequence()[3]->getAsTyped(); // orig
|
||||
|
||||
const bool isImage = arg0->getType().isImage();
|
||||
TIntermAggregate* atomic = new TIntermAggregate(mapAtomicOp(loc, op, isImage));
|
||||
atomic->getSequence().push_back(arg0);
|
||||
atomic->getSequence().push_back(arg1);
|
||||
atomic->getSequence().push_back(arg2);
|
||||
atomic->setLoc(loc);
|
||||
atomic->setType(arg2->getType());
|
||||
atomic->getWritableType().getQualifier().makeTemporary();
|
||||
|
||||
node = intermediate.addAssign(EOpAssign, arg3, atomic, loc);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break; // most pass through unchanged
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ protected:
|
||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
|
||||
TOperator mapTypeToConstructorOp(const TType&) const;
|
||||
TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
|
||||
void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
||||
va_list args);
|
||||
|
||||
@@ -296,20 +296,26 @@ void TBuiltInParseablesHlsl::initialize(int version, EProfile profile, int spv,
|
||||
{ "fmod", nullptr, nullptr, "SVM,", "F,", EShLangAll },
|
||||
{ "frac", nullptr, nullptr, "SVM", "F", EShLangAll },
|
||||
{ "frexp", nullptr, nullptr, "SVM,", "F,", EShLangAll },
|
||||
{ "fwidth", nullptr, nullptr, "SVM", "F", EShLangAll },
|
||||
{ "fwidth", nullptr, nullptr, "SVM", "F", EShLangFragmentMask },
|
||||
{ "GetRenderTargetSampleCount", "S", "U", "-", "-", EShLangAll },
|
||||
{ "GetRenderTargetSamplePosition", "V2", "F", "V1", "I", EShLangAll },
|
||||
{ "GroupMemoryBarrier", nullptr, nullptr, "-", "-", EShLangComputeMask },
|
||||
{ "GroupMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangComputeMask },
|
||||
{ "InterlockedAdd", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedAdd", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedAnd", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedAnd", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedCompareExchange", "-", "-", "SVM,,,>", "UI,,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedCompareStore", "-", "-", "SVM,,", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedExchange", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedMax", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedMax", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedMin", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedMin", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedOr", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedOr", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedXor", "-", "-", "SVM,,>", "UI,,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "InterlockedXor", "-", "-", "SVM,", "UI,", EShLangFragmentMask | EShLangComputeMask },
|
||||
{ "isfinite", nullptr, "B" , "SVM", "F", EShLangAll },
|
||||
{ "isinf", nullptr, "B" , "SVM", "F", EShLangAll },
|
||||
{ "isnan", nullptr, "B" , "SVM", "F", EShLangAll },
|
||||
@@ -516,11 +522,11 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int version, EProfile profile, int
|
||||
// symbolTable.relateToOperator("AllMemoryBarrier");
|
||||
// symbolTable.relateToOperator("AllMemoryBarrierWithGroupSync");
|
||||
symbolTable.relateToOperator("any", EOpAny);
|
||||
// symbolTable.relateToOperator("asdouble");
|
||||
// symbolTable.relateToOperator("asfloat");
|
||||
symbolTable.relateToOperator("asdouble", EOpUint64BitsToDouble);
|
||||
symbolTable.relateToOperator("asfloat", EOpIntBitsToFloat);
|
||||
symbolTable.relateToOperator("asin", EOpAsin);
|
||||
// symbolTable.relateToOperator("asint");
|
||||
// symbolTable.relateToOperator("asuint");
|
||||
symbolTable.relateToOperator("asint", EOpFloatBitsToInt);
|
||||
symbolTable.relateToOperator("asuint", EOpFloatBitsToUint);
|
||||
symbolTable.relateToOperator("atan", EOpAtan);
|
||||
symbolTable.relateToOperator("atan2", EOpAtan);
|
||||
symbolTable.relateToOperator("ceil", EOpCeil);
|
||||
@@ -566,15 +572,15 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int version, EProfile profile, int
|
||||
// symbolTable.relateToOperator("GetRenderTargetSamplePosition");
|
||||
// symbolTable.relateToOperator("GroupMemoryBarrier");
|
||||
// symbolTable.relateToOperator("GroupMemoryBarrierWithGroupSync");
|
||||
// symbolTable.relateToOperator("InterlockedAdd");
|
||||
// symbolTable.relateToOperator("InterlockedAnd");
|
||||
// symbolTable.relateToOperator("InterlockedCompareExchange");
|
||||
// symbolTable.relateToOperator("InterlockedCompareStore");
|
||||
// symbolTable.relateToOperator("InterlockedExchange");
|
||||
// symbolTable.relateToOperator("InterlockedMax");
|
||||
// symbolTable.relateToOperator("InterlockedMin");
|
||||
// symbolTable.relateToOperator("InterlockedOr");
|
||||
// symbolTable.relateToOperator("InterlockedXor");
|
||||
symbolTable.relateToOperator("InterlockedAdd", EOpInterlockedAdd);
|
||||
symbolTable.relateToOperator("InterlockedAnd", EOpInterlockedAnd);
|
||||
symbolTable.relateToOperator("InterlockedCompareExchange", EOpInterlockedCompareExchange);
|
||||
symbolTable.relateToOperator("InterlockedCompareStore", EOpInterlockedCompareStore);
|
||||
symbolTable.relateToOperator("InterlockedExchange", EOpInterlockedExchange);
|
||||
symbolTable.relateToOperator("InterlockedMax", EOpInterlockedMax);
|
||||
symbolTable.relateToOperator("InterlockedMin", EOpInterlockedMin);
|
||||
symbolTable.relateToOperator("InterlockedOr", EOpInterlockedOr);
|
||||
symbolTable.relateToOperator("InterlockedXor", EOpInterlockedXor);
|
||||
symbolTable.relateToOperator("isfinite", EOpIsFinite);
|
||||
symbolTable.relateToOperator("isinf", EOpIsInf);
|
||||
symbolTable.relateToOperator("isnan", EOpIsNan);
|
||||
|
||||
Reference in New Issue
Block a user