Refactor: Compatible compute and graphics VerifyIO
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmInstructionTests.cpp
index fa647dd..77b677b 100644 (file)
@@ -50,6 +50,7 @@
 #include "tcuStringTemplate.hpp"
 
 #include "vktSpvAsmCrossStageInterfaceTests.hpp"
+#include "vktSpvAsm8bitStorageTests.hpp"
 #include "vktSpvAsm16bitStorageTests.hpp"
 #include "vktSpvAsmUboMatrixPaddingTests.hpp"
 #include "vktSpvAsmConditionalBranchTests.hpp"
@@ -60,6 +61,7 @@
 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
 #include "vktSpvAsmVariablePointersTests.hpp"
 #include "vktSpvAsmVariableInitTests.hpp"
+#include "vktSpvAsmPointerParameterTests.hpp"
 #include "vktSpvAsmSpirvVersionTests.hpp"
 #include "vktTestCaseUtil.hpp"
 #include "vktSpvAsmLoopDepLenTests.hpp"
@@ -367,7 +369,7 @@ tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-bool compareFUnord (const std::vector<BufferSp>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog& log)
+bool compareFUnord (const std::vector<Resource>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog& log)
 {
        if (outputAllocs.size() != 1)
                return false;
@@ -376,14 +378,14 @@ bool compareFUnord (const std::vector<BufferSp>& inputs, const vector<Allocation
        vector<deUint8> input2Bytes;
        vector<deUint8> expectedBytes;
 
-       inputs[0]->getBytes(input1Bytes);
-       inputs[1]->getBytes(input2Bytes);
-       expectedOutputs[0]->getBytes(expectedBytes);
+       inputs[0].getBytes(input1Bytes);
+       inputs[1].getBytes(input2Bytes);
+       expectedOutputs[0].getBytes(expectedBytes);
 
-       const deInt32* const    expectedOutputAsInt             = reinterpret_cast<const deInt32* const>(&expectedBytes.front());
-       const deInt32* const    outputAsInt                             = static_cast<const deInt32* const>(outputAllocs[0]->getHostPtr());
-       const float* const              input1AsFloat                   = reinterpret_cast<const float* const>(&input1Bytes.front());
-       const float* const              input2AsFloat                   = reinterpret_cast<const float* const>(&input2Bytes.front());
+       const deInt32* const    expectedOutputAsInt             = reinterpret_cast<const deInt32*>(&expectedBytes.front());
+       const deInt32* const    outputAsInt                             = static_cast<const deInt32*>(outputAllocs[0]->getHostPtr());
+       const float* const              input1AsFloat                   = reinterpret_cast<const float*>(&input1Bytes.front());
+       const float* const              input2AsFloat                   = reinterpret_cast<const float*>(&input2Bytes.front());
        bool returnValue                                                                = true;
 
        for (size_t idx = 0; idx < expectedBytes.size() / sizeof(deInt32); ++idx)
@@ -530,22 +532,26 @@ struct OpAtomicCase
 {
        const char*             name;
        const char*             assembly;
+       const char*             retValAssembly;
        OpAtomicType    opAtomic;
        deInt32                 numOutputElements;
 
-                                       OpAtomicCase                    (const char* _name, const char* _assembly, OpAtomicType _opAtomic, deInt32 _numOutputElements)
+                                       OpAtomicCase(const char* _name, const char* _assembly, const char* _retValAssembly, OpAtomicType _opAtomic, deInt32 _numOutputElements)
                                                : name                          (_name)
                                                , assembly                      (_assembly)
+                                               , retValAssembly        (_retValAssembly)
                                                , opAtomic                      (_opAtomic)
                                                , numOutputElements     (_numOutputElements) {}
 };
 
-tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStorageBuffer)
+tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStorageBuffer, int numElements = 65535, bool verifyReturnValues = false)
 {
-       de::MovePtr<tcu::TestCaseGroup> group                           (new tcu::TestCaseGroup(testCtx,
-                                                                                                                                                               useStorageBuffer ? "opatomic_storage_buffer" : "opatomic",
-                                                                                                                                                               "Test the OpAtomic* opcodes"));
-       const int                                               numElements                     = 65535;
+       std::string                                             groupName                       ("opatomic");
+       if (useStorageBuffer)
+               groupName += "_storage_buffer";
+       if (verifyReturnValues)
+               groupName += "_return_values";
+       de::MovePtr<tcu::TestCaseGroup> group                           (new tcu::TestCaseGroup(testCtx, groupName.c_str(), "Test the OpAtomic* opcodes"));
        vector<OpAtomicCase>                    cases;
 
        const StringTemplate                    shaderTemplate  (
@@ -574,6 +580,8 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStor
                "OpMemberDecorate %sumbuf 0 Coherent\n"
                "OpMemberDecorate %sumbuf 0 Offset 0\n"
 
+               "${RETVAL_BUF_DECORATE}"
+
                + getComputeAsmCommonTypes("${BLOCK_POINTER_TYPE}") +
 
                "%buf       = OpTypeStruct %i32arr\n"
@@ -584,6 +592,8 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStor
                "%sumbufptr = OpTypePointer ${BLOCK_POINTER_TYPE} %sumbuf\n"
                "%sum       = OpVariable %sumbufptr ${BLOCK_POINTER_TYPE}\n"
 
+               "${RETVAL_BUF_DECL}"
+
                "%id        = OpVariable %uvec3ptr Input\n"
                "%minusone  = OpConstant %i32 -1\n"
                "%zero      = OpConstant %i32 0\n"
@@ -600,28 +610,39 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStor
 
                "%outloc    = OpAccessChain %i32ptr %sum %zero ${INDEX}\n"
                "${INSTRUCTION}"
+               "${RETVAL_ASSEMBLY}"
 
                "             OpReturn\n"
                "             OpFunctionEnd\n");
 
-       #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, OPATOMIC, NUM_OUTPUT_ELEMENTS) \
+       #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC, NUM_OUTPUT_ELEMENTS) \
        do { \
-               DE_STATIC_ASSERT((NUM_OUTPUT_ELEMENTS) == 1 || (NUM_OUTPUT_ELEMENTS) == numElements); \
-               cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, OPATOMIC, NUM_OUTPUT_ELEMENTS)); \
+               DE_ASSERT((NUM_OUTPUT_ELEMENTS) == 1 || (NUM_OUTPUT_ELEMENTS) == numElements); \
+               cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC, NUM_OUTPUT_ELEMENTS)); \
        } while (deGetFalse())
-       #define ADD_OPATOMIC_CASE_1(NAME, ASSEMBLY, OPATOMIC) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, OPATOMIC, 1)
-       #define ADD_OPATOMIC_CASE_N(NAME, ASSEMBLY, OPATOMIC) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, OPATOMIC, numElements)
-
-       ADD_OPATOMIC_CASE_1(iadd,       "%unused    = OpAtomicIAdd %i32 %outloc %one %zero %inval\n", OPATOMIC_IADD );
-       ADD_OPATOMIC_CASE_1(isub,       "%unused    = OpAtomicISub %i32 %outloc %one %zero %inval\n", OPATOMIC_ISUB );
-       ADD_OPATOMIC_CASE_1(iinc,       "%unused    = OpAtomicIIncrement %i32 %outloc %one %zero\n",  OPATOMIC_IINC );
-       ADD_OPATOMIC_CASE_1(idec,       "%unused    = OpAtomicIDecrement %i32 %outloc %one %zero\n",  OPATOMIC_IDEC );
-       ADD_OPATOMIC_CASE_N(load,       "%inval2    = OpAtomicLoad %i32 %inloc %one %zero\n"
-                                                               "             OpStore %outloc %inval2\n",  OPATOMIC_LOAD );
-       ADD_OPATOMIC_CASE_N(store,      "             OpAtomicStore %outloc %one %zero %inval\n",  OPATOMIC_STORE );
+       #define ADD_OPATOMIC_CASE_1(NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC, 1)
+       #define ADD_OPATOMIC_CASE_N(NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, RETVAL_ASSEMBLY, OPATOMIC, numElements)
+
+       ADD_OPATOMIC_CASE_1(iadd,       "%retv      = OpAtomicIAdd %i32 %outloc %one %zero %inval\n",
+                                                               "             OpStore %retloc %retv\n", OPATOMIC_IADD );
+       ADD_OPATOMIC_CASE_1(isub,       "%retv      = OpAtomicISub %i32 %outloc %one %zero %inval\n",
+                                                               "             OpStore %retloc %retv\n", OPATOMIC_ISUB );
+       ADD_OPATOMIC_CASE_1(iinc,       "%retv      = OpAtomicIIncrement %i32 %outloc %one %zero\n",
+                                                               "             OpStore %retloc %retv\n", OPATOMIC_IINC );
+       ADD_OPATOMIC_CASE_1(idec,       "%retv      = OpAtomicIDecrement %i32 %outloc %one %zero\n",
+                                                               "             OpStore %retloc %retv\n", OPATOMIC_IDEC );
+       if (!verifyReturnValues)
+       {
+               ADD_OPATOMIC_CASE_N(load,       "%inval2    = OpAtomicLoad %i32 %inloc %one %zero\n"
+                                                                       "             OpStore %outloc %inval2\n", "", OPATOMIC_LOAD );
+               ADD_OPATOMIC_CASE_N(store,      "             OpAtomicStore %outloc %one %zero %inval\n", "", OPATOMIC_STORE );
+       }
+
        ADD_OPATOMIC_CASE_N(compex, "%even      = OpSMod %i32 %inval %two\n"
                                                                "             OpStore %outloc %even\n"
-                                                               "%unused    = OpAtomicCompareExchange %i32 %outloc %one %zero %zero %minusone %zero\n",  OPATOMIC_COMPEX );
+                                                               "%retv      = OpAtomicCompareExchange %i32 %outloc %one %zero %zero %minusone %zero\n",
+                                                               "                         OpStore %retloc %retv\n", OPATOMIC_COMPEX );
+
 
        #undef ADD_OPATOMIC_CASE
        #undef ADD_OPATOMIC_CASE_1
@@ -638,6 +659,36 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStor
                specializations["INSTRUCTION"]                  = cases[caseNdx].assembly;
                specializations["BLOCK_DECORATION"]             = useStorageBuffer ? "Block" : "BufferBlock";
                specializations["BLOCK_POINTER_TYPE"]   = useStorageBuffer ? "StorageBuffer" : "Uniform";
+
+               if (verifyReturnValues)
+               {
+                       const StringTemplate blockDecoration    (
+                               "\n"
+                               "OpDecorate %retbuf ${BLOCK_DECORATION}\n"
+                               "OpDecorate %ret DescriptorSet 0\n"
+                               "OpDecorate %ret Binding 2\n"
+                               "OpMemberDecorate %retbuf 0 Offset 0\n\n");
+
+                       const StringTemplate blockDeclaration   (
+                               "\n"
+                               "%retbuf    = OpTypeStruct %i32arr\n"
+                               "%retbufptr = OpTypePointer ${BLOCK_POINTER_TYPE} %retbuf\n"
+                               "%ret       = OpVariable %retbufptr ${BLOCK_POINTER_TYPE}\n\n");
+
+                       specializations["RETVAL_ASSEMBLY"] =
+                               "%retloc    = OpAccessChain %i32ptr %ret %zero %x\n"
+                               + std::string(cases[caseNdx].retValAssembly);
+
+                       specializations["RETVAL_BUF_DECORATE"]  = blockDecoration.specialize(specializations);
+                       specializations["RETVAL_BUF_DECL"]              = blockDeclaration.specialize(specializations);
+               }
+               else
+               {
+                       specializations["RETVAL_ASSEMBLY"]              = "";
+                       specializations["RETVAL_BUF_DECORATE"]  = "";
+                       specializations["RETVAL_BUF_DECL"]              = "";
+               }
+
                spec.assembly                                                   = shaderTemplate.specialize(specializations);
 
                if (useStorageBuffer)
@@ -645,7 +696,33 @@ tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStor
 
                spec.inputs.push_back(BufferSp(new OpAtomicBuffer(numElements, cases[caseNdx].numOutputElements, cases[caseNdx].opAtomic, BUFFERTYPE_INPUT)));
                spec.outputs.push_back(BufferSp(new OpAtomicBuffer(numElements, cases[caseNdx].numOutputElements, cases[caseNdx].opAtomic, BUFFERTYPE_EXPECTED)));
+               if (verifyReturnValues)
+                       spec.outputs.push_back(BufferSp(new OpAtomicBuffer(numElements, cases[caseNdx].numOutputElements, cases[caseNdx].opAtomic, BUFFERTYPE_ATOMIC_RET)));
                spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+               if (verifyReturnValues)
+               {
+                       switch (cases[caseNdx].opAtomic)
+                       {
+                               case OPATOMIC_IADD:
+                                       spec.verifyIO = OpAtomicBuffer::compareWithRetvals<OPATOMIC_IADD>;
+                                       break;
+                               case OPATOMIC_ISUB:
+                                       spec.verifyIO = OpAtomicBuffer::compareWithRetvals<OPATOMIC_ISUB>;
+                                       break;
+                               case OPATOMIC_IINC:
+                                       spec.verifyIO = OpAtomicBuffer::compareWithRetvals<OPATOMIC_IINC>;
+                                       break;
+                               case OPATOMIC_IDEC:
+                                       spec.verifyIO = OpAtomicBuffer::compareWithRetvals<OPATOMIC_IDEC>;
+                                       break;
+                               case OPATOMIC_COMPEX:
+                                       spec.verifyIO = OpAtomicBuffer::compareWithRetvals<OPATOMIC_COMPEX>;
+                                       break;
+                               default:
+                                       DE_FATAL("Unsupported OpAtomic type for return value verification");
+                       }
+               }
                group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
        }
 
@@ -881,13 +958,13 @@ tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
 
 // Compare instruction for the contraction compute case.
 // Returns true if the output is what is expected from the test case.
-bool compareNoContractCase(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareNoContractCase(const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
        // Only size is needed because we are not comparing the exact values.
-       size_t byteSize = expectedOutputs[0]->getByteSize();
+       size_t byteSize = expectedOutputs[0].getByteSize();
 
        const float*    outputAsFloat   = static_cast<const float*>(outputAllocs[0]->getHostPtr());
 
@@ -991,13 +1068,13 @@ tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-bool compareFRem(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareFRem(const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
        vector<deUint8> expectedBytes;
-       expectedOutputs[0]->getBytes(expectedBytes);
+       expectedOutputs[0].getBytes(expectedBytes);
 
        const float*    expectedOutputAsFloat   = reinterpret_cast<const float*>(&expectedBytes.front());
        const float*    outputAsFloat                   = static_cast<const float*>(outputAllocs[0]->getHostPtr());
@@ -1092,12 +1169,12 @@ tcu::TestCaseGroup* createOpFRemGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-bool compareNMin (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareNMin (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
-       const BufferSp&                 expectedOutput                  (expectedOutputs[0]);
+       const BufferSp&                 expectedOutput                  (expectedOutputs[0].getBuffer());
        std::vector<deUint8>    data;
        expectedOutput->getBytes(data);
 
@@ -1216,12 +1293,12 @@ tcu::TestCaseGroup* createOpNMinGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-bool compareNMax (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareNMax (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
-       const BufferSp&                 expectedOutput                  = expectedOutputs[0];
+       const BufferSp&                 expectedOutput                  = expectedOutputs[0].getBuffer();
        std::vector<deUint8>    data;
        expectedOutput->getBytes(data);
 
@@ -1339,12 +1416,12 @@ tcu::TestCaseGroup* createOpNMaxGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-bool compareNClamp (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareNClamp (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
-       const BufferSp&                 expectedOutput                  = expectedOutputs[0];
+       const BufferSp&                 expectedOutput                  = expectedOutputs[0].getBuffer();
        std::vector<deUint8>    data;
        expectedOutput->getBytes(data);
 
@@ -2657,6 +2734,7 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
        cases.push_back(SpecConstantTwoIntCase("sgreaterthanequal",             " %i32 0",              " %i32 0",              "%bool",        "SGreaterThanEqual    %sc_0 %sc_1",                     -1000,  50,             selectFalseUsingSc,     outputInts2));
        cases.push_back(SpecConstantTwoIntCase("ugreaterthanequal",             " %i32 0",              " %i32 0",              "%bool",        "UGreaterThanEqual    %sc_0 %sc_1",                     10,             10,             selectTrueUsingSc,      outputInts2));
        cases.push_back(SpecConstantTwoIntCase("iequal",                                " %i32 0",              " %i32 0",              "%bool",        "IEqual               %sc_0 %sc_1",                     42,             24,             selectFalseUsingSc,     outputInts2));
+       cases.push_back(SpecConstantTwoIntCase("inotequal",                             " %i32 0",              " %i32 0",              "%bool",        "INotEqual            %sc_0 %sc_1",                     42,             24,             selectTrueUsingSc,      outputInts2));
        cases.push_back(SpecConstantTwoIntCase("logicaland",                    "True %bool",   "True %bool",   "%bool",        "LogicalAnd           %sc_0 %sc_1",                     0,              1,              selectFalseUsingSc,     outputInts2));
        cases.push_back(SpecConstantTwoIntCase("logicalor",                             "False %bool",  "False %bool",  "%bool",        "LogicalOr            %sc_0 %sc_1",                     1,              0,              selectTrueUsingSc,      outputInts2));
        cases.push_back(SpecConstantTwoIntCase("logicalequal",                  "True %bool",   "True %bool",   "%bool",        "LogicalEqual         %sc_0 %sc_1",                     0,              1,              selectFalseUsingSc,     outputInts2));
@@ -2703,8 +2781,8 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
                spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
                spec.outputs.push_back(BufferSp(new Int32Buffer(cases[caseNdx].expectedOutput)));
                spec.numWorkGroups = IVec3(numElements, 1, 1);
-               spec.specConstants.push_back(cases[caseNdx].scActualValue0);
-               spec.specConstants.push_back(cases[caseNdx].scActualValue1);
+               spec.specConstants.append(cases[caseNdx].scActualValue0);
+               spec.specConstants.append(cases[caseNdx].scActualValue1);
 
                group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].caseName, cases[caseNdx].caseName, spec, features));
        }
@@ -2767,9 +2845,9 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
        spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
        spec.outputs.push_back(BufferSp(new Int32Buffer(outputInts3)));
        spec.numWorkGroups = IVec3(numElements, 1, 1);
-       spec.specConstants.push_back(123);
-       spec.specConstants.push_back(56);
-       spec.specConstants.push_back(-77);
+       spec.specConstants.append<deInt32>(123);
+       spec.specConstants.append<deInt32>(56);
+       spec.specConstants.append<deInt32>(-77);
 
        group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector_related", "VectorShuffle, CompositeExtract, & CompositeInsert", spec));
 
@@ -4303,13 +4381,13 @@ float constructNormalizedFloat (deInt32 exponent, deUint32 significand)
 
 // Compare instruction for the OpQuantizeF16 compute exact case.
 // Returns true if the output is what is expected from the test case.
-bool compareOpQuantizeF16ComputeExactCase (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareOpQuantizeF16ComputeExactCase (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
        // Only size is needed because we cannot compare Nans.
-       size_t byteSize = expectedOutputs[0]->getByteSize();
+       size_t byteSize = expectedOutputs[0].getByteSize();
 
        const float*    outputAsFloat   = static_cast<const float*>(outputAllocs[0]->getHostPtr());
 
@@ -4344,15 +4422,15 @@ bool compareOpQuantizeF16ComputeExactCase (const std::vector<BufferSp>&, const v
 }
 
 // Checks that every output from a test-case is a float NaN.
-bool compareNan (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool compareNan (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        if (outputAllocs.size() != 1)
                return false;
 
        // Only size is needed because we cannot compare Nans.
-       size_t byteSize = expectedOutputs[0]->getByteSize();
+       size_t byteSize = expectedOutputs[0].getByteSize();
 
-       const float* const      output_as_float = static_cast<const float* const>(outputAllocs[0]->getHostPtr());
+       const float* const      output_as_float = static_cast<const float*>(outputAllocs[0]->getHostPtr());
 
        for (size_t idx = 0; idx < byteSize / sizeof(float); ++idx)
        {
@@ -4643,10 +4721,10 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te
                spec.assembly           = shader;
                spec.numWorkGroups      = IVec3(numCases, 1, 1);
 
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::numeric_limits<float>::infinity()));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(-std::numeric_limits<float>::infinity()));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, 16)));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, 32)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::numeric_limits<float>::infinity()));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(-std::numeric_limits<float>::infinity()));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::ldexp(1.0f, 16)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::ldexp(-1.0f, 32)));
 
                outputs.push_back(std::numeric_limits<float>::infinity());
                outputs.push_back(-std::numeric_limits<float>::infinity());
@@ -4674,7 +4752,7 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te
                outputs.push_back(-std::numeric_limits<float>::quiet_NaN());
 
                for (deUint8 idx = 0; idx < numCases; ++idx)
-                       spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
+                       spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(outputs[idx]));
 
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
                spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
@@ -4692,12 +4770,12 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te
                spec.assembly           = shader;
                spec.numWorkGroups      = IVec3(numCases, 1, 1);
 
-               spec.specConstants.push_back(bitwiseCast<deUint32>(0.f));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(-0.f));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -16)));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, -32)));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -127)));
-               spec.specConstants.push_back(bitwiseCast<deUint32>(-std::ldexp(1.0f, -128)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(0.f));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(-0.f));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::ldexp(1.0f, -16)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::ldexp(-1.0f, -32)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(std::ldexp(1.0f, -127)));
+               spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(-std::ldexp(1.0f, -128)));
 
                outputs.push_back(0.f);
                outputs.push_back(-0.f);
@@ -4725,7 +4803,7 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te
                for (deUint8 idx = 0; idx < 6; ++idx)
                {
                        const float f = static_cast<float>(idx * 10 - 30) / 4.f;
-                       spec.specConstants.push_back(bitwiseCast<deUint32>(f));
+                       spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(f));
                        outputs.push_back(f);
                }
 
@@ -4752,7 +4830,7 @@ tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& te
                outputs.push_back(constructNormalizedFloat(1, 0xFFE000));
 
                for (deUint8 idx = 0; idx < numCases; ++idx)
-                       spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
+                       spec.specConstants.append<deInt32>(bitwiseCast<deUint32>(outputs[idx]));
 
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
                spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
@@ -5494,7 +5572,7 @@ tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
                "OpNoLine\n"
                "OpLine %name 1 1\n"
                "OpLine %name 1 1\n"
-               "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+               "%second_function = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "OpNoLine\n"
                "OpLine %name 1 1\n"
                "OpNoLine\n"
@@ -5515,7 +5593,7 @@ tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
                "OpNoLine\n"
                "OpNoLine\n"
                "OpLine %name 1 1\n"
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "OpNoLine\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "OpNoLine\n"
@@ -5551,7 +5629,7 @@ tcu::TestCaseGroup* createOpModuleProcessedTests(tcu::TestContext& testCtx)
                "OpModuleProcessed \"Date: 2017/09/21\"\n";
 
        fragments["pre_main"]   =
-               "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+               "%second_function = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%second_param1 = OpFunctionParameter %v4f32\n"
                "%label_secondfunction = OpLabel\n"
                "OpReturnValue %second_param1\n"
@@ -5559,7 +5637,7 @@ tcu::TestCaseGroup* createOpModuleProcessedTests(tcu::TestContext& testCtx)
 
        fragments["testfun"]            =
                // A %test_code function that returns its argument unchanged.
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
@@ -5597,7 +5675,7 @@ tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
                "OpLine %other_name 4294967295 0\n"
                "OpLine %other_name 32 40\n"
                "OpLine %file_name 0 0\n"
-               "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+               "%second_function = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "OpLine %file_name 1 0\n"
                "%second_param1 = OpFunctionParameter %v4f32\n"
                "OpLine %file_name 1 3\n"
@@ -5612,7 +5690,7 @@ tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
        fragments["testfun"]            =
                // A %test_code function that returns its argument unchanged.
                "OpLine %file_name 1 0\n"
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "OpLine %file_name 16 330\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "OpLine %file_name 14 442\n"
@@ -5641,7 +5719,7 @@ tcu::TestCaseGroup* createOpConstantNullTests(tcu::TestContext& testCtx)
 
 
        const char                                              functionStart[] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%lbl    = OpLabel\n";
 
@@ -5758,7 +5836,7 @@ tcu::TestCaseGroup* createOpConstantCompositeTests(tcu::TestContext& testCtx)
 
 
        const char                                              functionStart[]  =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%lbl    = OpLabel\n";
 
@@ -5909,7 +5987,7 @@ tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx)
        //   return result;
        // }
        const char                                              function[]                      =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1    = OpFunctionParameter %v4f32\n"
                "%lbl       = OpLabel\n"
                "%iptr      = OpVariable %fp_i32 Function\n"
@@ -6001,7 +6079,7 @@ tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx)
        //   return result;
        // }
        const char                                              function[]                      =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1    = OpFunctionParameter %v4f32\n"
                "%lbl       = OpLabel\n"
                "%iptr      = OpVariable %fp_i32 Function\n"
@@ -6114,7 +6192,7 @@ tcu::TestCaseGroup* createDecorationGroupTests(tcu::TestContext& testCtx)
                "%c_struct2 = OpConstantComposite %struct2 %c_a3f32_2\n";
 
        const char                                              function[]                      =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%entry     = OpLabel\n"
                "%result    = OpVariable %fp_v4f32 Function\n"
@@ -6248,11 +6326,11 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                "%sc_op     = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n";
 
        const char      function1[]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%label     = OpLabel\n"
-               "${TYPE_CONVERT:opt}"
                "%result    = OpVariable %fp_v4f32 Function\n"
+               "${TYPE_CONVERT:opt}"
                "             OpStore %result %param\n"
                "%gen       = ${GEN_RESULT}\n"
                "%index     = OpIAdd %i32 %gen %c_i32_1\n"
@@ -6315,6 +6393,7 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
        cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthanequal",             " %i32 0",              " %i32 0",              "%bool",        "SGreaterThanEqual    %sc_0 %sc_1",                             -1000,  50,             selectFalseUsingSc,     outputColors2));
        cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthanequal",             " %i32 0",              " %i32 0",              "%bool",        "UGreaterThanEqual    %sc_0 %sc_1",                             10,             10,             selectTrueUsingSc,      outputColors2));
        cases.push_back(SpecConstantTwoIntGraphicsCase("iequal",                                " %i32 0",              " %i32 0",              "%bool",        "IEqual               %sc_0 %sc_1",                             42,             24,             selectFalseUsingSc,     outputColors2));
+       cases.push_back(SpecConstantTwoIntGraphicsCase("inotequal",                             " %i32 0",              " %i32 0",              "%bool",        "INotEqual            %sc_0 %sc_1",                             42,             24,             selectTrueUsingSc,      outputColors2));
        cases.push_back(SpecConstantTwoIntGraphicsCase("logicaland",                    "True %bool",   "True %bool",   "%bool",        "LogicalAnd           %sc_0 %sc_1",                             0,              1,              selectFalseUsingSc,     outputColors2));
        cases.push_back(SpecConstantTwoIntGraphicsCase("logicalor",                             "False %bool",  "False %bool",  "%bool",        "LogicalOr            %sc_0 %sc_1",                             1,              0,              selectTrueUsingSc,      outputColors2));
        cases.push_back(SpecConstantTwoIntGraphicsCase("logicalequal",                  "True %bool",   "True %bool",   "%bool",        "LogicalEqual         %sc_0 %sc_1",                             0,              1,              selectFalseUsingSc,     outputColors2));
@@ -6332,7 +6411,7 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
        {
                map<string, string>                     specializations;
                map<string, string>                     fragments;
-               vector<deInt32>                         specConstants;
+               SpecConstants                           specConstants;
                vector<string>                          features;
                PushConstants                           noPushConstants;
                GraphicsResources                       noResources;
@@ -6367,8 +6446,8 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                fragments["pre_main"]                           = tcu::StringTemplate(typesAndConstants1).specialize(specializations);
                fragments["testfun"]                            = tcu::StringTemplate(function1).specialize(specializations);
 
-               specConstants.push_back(cases[caseNdx].scActualValue0);
-               specConstants.push_back(cases[caseNdx].scActualValue1);
+               specConstants.append(cases[caseNdx].scActualValue0);
+               specConstants.append(cases[caseNdx].scActualValue1);
 
                createTestsForAllStages(
                        cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants,
@@ -6402,7 +6481,7 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                "%sc_final    = OpSpecConstantOp %i32   IMul             %sc_sub      %sc_ext_2\n";                                                             // (sc_2 - sc_0) * sc_1
 
        const char      function2[]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%label     = OpLabel\n"
                "%result    = OpVariable %fp_v4f32 Function\n"
@@ -6416,15 +6495,15 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                "             OpFunctionEnd\n";
 
        map<string, string>     fragments;
-       vector<deInt32>         specConstants;
+       SpecConstants           specConstants;
 
        fragments["decoration"] = decorations2;
        fragments["pre_main"]   = typesAndConstants2;
        fragments["testfun"]    = function2;
 
-       specConstants.push_back(56789);
-       specConstants.push_back(-2);
-       specConstants.push_back(56788);
+       specConstants.append<deInt32>(56789);
+       specConstants.append<deInt32>(-2);
+       specConstants.append<deInt32>(56788);
 
        createTestsForAllStages("vector_related", inputColors, outputColors2, fragments, specConstants, group.get());
 
@@ -6464,7 +6543,7 @@ tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
        //   return result;
        // }
        const char      function1[]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1    = OpFunctionParameter %v4f32\n"
                "%lbl       = OpLabel\n"
                "%iptr      = OpVariable %fp_i32 Function\n"
@@ -6528,7 +6607,7 @@ tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
 
        // Add .4 to the second element of the given parameter.
        const char      function2[]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%entry     = OpLabel\n"
                "%result    = OpVariable %fp_v4f32 Function\n"
@@ -6570,7 +6649,7 @@ tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
 
        // Swap the second and the third element of the given parameter.
        const char      function3[]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%entry     = OpLabel\n"
                "%result    = OpVariable %fp_v4f32 Function\n"
@@ -6627,7 +6706,7 @@ tcu::TestCaseGroup* createNoContractionTests(tcu::TestContext& testCtx)
                "%c_f32_n1pn24   = OpConstant %f32 -0x1p-24\n";
 
        const char                                              function[]       =
-               "%test_code      = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code      = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param          = OpFunctionParameter %v4f32\n"
                "%label          = OpLabel\n"
                "%var1           = OpVariable %fp_f32 Function %c_f32_1pl2_23\n"
@@ -6694,7 +6773,7 @@ tcu::TestCaseGroup* createMemoryAccessTests(tcu::TestContext& testCtx)
                "%fp_stype          = OpTypePointer Function %stype\n";
 
        const char                                              function[]       =
-               "%test_code         = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code         = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1            = OpFunctionParameter %v4f32\n"
                "%lbl               = OpLabel\n"
                "%v1                = OpVariable %fp_v4f32 Function\n"
@@ -6787,7 +6866,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        {
                fragments["undef_type"] = tests[testNdx].type;
                fragments["testfun"] = StringTemplate(
-                       "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+                       "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                        "%param1 = OpFunctionParameter %v4f32\n"
                        "%label_testfun = OpLabel\n"
                        "%undef = OpUndef ${undef_type}\n"
@@ -6799,7 +6878,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        fragments.clear();
 
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%undef = OpUndef %f32\n"
@@ -6815,7 +6894,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%undef = OpUndef %i32\n"
@@ -6828,7 +6907,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%undef = OpUndef %u32\n"
@@ -6841,7 +6920,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%undef = OpUndef %v4f32\n"
@@ -6855,9 +6934,9 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%is_nan_2 = OpIsNan %bool %zero_2\n"
                "%is_nan_3 = OpIsNan %bool %zero_3\n"
                "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n"
-               "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n"
-               "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n"
-               "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n"
+               "%actually_zero_1 = OpSelect %f32 %is_nan_1 %c_f32_0 %zero_1\n"
+               "%actually_zero_2 = OpSelect %f32 %is_nan_2 %c_f32_0 %zero_2\n"
+               "%actually_zero_3 = OpSelect %f32 %is_nan_3 %c_f32_0 %zero_3\n"
                "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
                "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
                "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
@@ -6878,7 +6957,7 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
        fragments["pre_main"] =
                "%m2x2f32 = OpTypeMatrix %v2f32 2\n";
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%undef = OpUndef %m2x2f32\n"
@@ -6892,9 +6971,9 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%is_nan_2 = OpIsNan %bool %zero_2\n"
                "%is_nan_3 = OpIsNan %bool %zero_3\n"
                "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n"
-               "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n"
-               "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n"
-               "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n"
+               "%actually_zero_1 = OpSelect %f32 %is_nan_1 %c_f32_0 %zero_1\n"
+               "%actually_zero_2 = OpSelect %f32 %is_nan_2 %c_f32_0 %zero_2\n"
+               "%actually_zero_3 = OpSelect %f32 %is_nan_3 %c_f32_0 %zero_3\n"
                "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
                "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
                "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
@@ -7038,7 +7117,7 @@ void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
                "%test_constant = OpConstant %f32 ";  // The value will be test.constant.
 
        StringTemplate  function                        (
-               "%test_code     = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code     = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1        = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%a             = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
@@ -7057,7 +7136,7 @@ void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
                        "%c             = OpSpecConstantOp %f32 QuantizeToF16 %test_constant\n";
 
        StringTemplate  specConstantFunction(
-               "%test_code     = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code     = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1        = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "${condition}\n"
@@ -7081,7 +7160,7 @@ void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
        {
                map<string, string>                                                             codeSpecialization;
                map<string, string>                                                             fragments;
-               vector<deInt32>                                                                 passConstants;
+               SpecConstants                                                                   passConstants;
                deInt32                                                                                 specConstant;
 
                codeSpecialization["condition"]                                 = tests[idx].condition;
@@ -7090,7 +7169,7 @@ void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
                fragments["pre_main"]                                                   = specConstants;
 
                memcpy(&specConstant, &tests[idx].valueAsFloat, sizeof(float));
-               passConstants.push_back(specConstant);
+               passConstants.append(specConstant);
 
                createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx);
        }
@@ -7165,7 +7244,7 @@ void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx)
        const char* specDecorations = "OpDecorate %input_const  SpecId 0\n";
 
        const char* function  =
-               "%test_code     = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code     = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1        = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%a             = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
@@ -7196,7 +7275,7 @@ void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx)
        for(size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) {
                map<string, string>                                                                     fragments;
                map<string, string>                                                                     constantSpecialization;
-               vector<deInt32>                                                                         passConstants;
+               SpecConstants                                                                           passConstants;
                deInt32                                                                                         specConstant;
 
                constantSpecialization["output1"]                                       = tests[idx].possibleOutput1;
@@ -7206,7 +7285,7 @@ void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx)
                fragments["pre_main"]                                                           = specConstants.specialize(constantSpecialization);
 
                memcpy(&specConstant, &tests[idx].inputAsFloat, sizeof(float));
-               passConstants.push_back(specConstant);
+               passConstants.append(specConstant);
 
                createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx);
        }
@@ -7312,7 +7391,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
        // itself. In SPIR-V terms, the "loop construct" contains no blocks at all
        // -- the "continue construct" forms the entire loop.
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7341,7 +7420,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
 
        // Body comprised of multiple basic blocks.
        const StringTemplate multiBlock(
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7397,7 +7476,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
 
        // A loop with continue statement.
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7437,7 +7516,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
 
        // A loop with break.
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7482,7 +7561,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
 
        // A loop with return.
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7545,7 +7624,7 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
                "%false = OpConstantFalse %bool\n";
 
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
 
                "%entry = OpLabel\n"
@@ -7605,7 +7684,7 @@ tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
                "%Workgroup = OpConstant %i32 2\n"
                "%WorkgroupAcquireRelease = OpConstant %i32 0x108\n";
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "OpControlBarrier %Workgroup %Workgroup %WorkgroupAcquireRelease\n"
@@ -7619,7 +7698,7 @@ tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
                "%WorkgroupAcquireRelease = OpConstant %i32 0x108\n"
                "%c_f32_5 = OpConstant %f32 5.\n";
        const string setupPercentZero =  // Begins %test_code function with code that sets %zero to 0u but cannot be optimized away.
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%entry = OpLabel\n"
                ";param1 components are between 0 and 1, so dot product is 4 or less\n"
@@ -7709,7 +7788,7 @@ tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
                "%WorkgroupAcquireRelease = OpConstant %i32 0x108\n"
                "%c_f32_10 = OpConstant %f32 10.\n";
        fragments["testfun"] =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%entry = OpLabel\n"
                "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
@@ -7758,7 +7837,7 @@ tcu::TestCaseGroup* createFRemTests(tcu::TestContext& testCtx)
        // vec4 result = (param1 * 8.0) - 4.0;
        // return (frem(result.x,3) + 0.75, frem(result.y, -3) + 0.75, 0, 1)
        fragments["testfun"]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%v_times_8 = OpVectorTimesScalar %v4f32 %param1 %c_f32_8\n"
@@ -7804,7 +7883,7 @@ tcu::TestCaseGroup* createOpSRemGraphicsTests(tcu::TestContext& testCtx, qpTestR
        // ivec4 result = ivec4(srem(ints.x, ints.y), srem(ints.y, ints.z), srem(ints.z, ints.x), 255);
        // return float(result + 128) / 255.0;
        fragments["testfun"]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%div255 = OpFMul %v4f32 %param1 %c_v4f32_255\n"
@@ -7887,7 +7966,7 @@ tcu::TestCaseGroup* createOpSModGraphicsTests(tcu::TestContext& testCtx, qpTestR
        // ivec4 result = ivec4(smod(ints.x, ints.y), smod(ints.y, ints.z), smod(ints.z, ints.x), 255);
        // return float(result + 128) / 255.0;
        fragments["testfun"]                             =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "%div255 = OpFMul %v4f32 %param1 %c_v4f32_255\n"
@@ -8424,7 +8503,7 @@ const map<string, string> getConvertCaseFragments (string instruction, const Con
                "     %SSBOo = OpVariable %ptr_SSBOo StorageBuffer\n");
 
        const StringTemplate testfun (
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param     = OpFunctionParameter %v4f32\n"
                "%label     = OpLabel\n"
                "%iLoc      = OpAccessChain %ptr_in %SSBOi %c_u32_0\n"
@@ -8463,8 +8542,10 @@ tcu::TestCaseGroup* createConvertComputeTests (tcu::TestContext& testCtx, const
                spec.inputs.push_back   (test->m_inputBuffer);
                spec.outputs.push_back  (test->m_outputBuffer);
 
-               if (test->m_features == COMPUTE_TEST_USES_INT16 || test->m_features == COMPUTE_TEST_USES_INT16_INT64 || usesInt16(test->m_fromType, test->m_toType))
+               if (test->m_features == COMPUTE_TEST_USES_INT16 || test->m_features == COMPUTE_TEST_USES_INT16_INT64 || usesInt16(test->m_fromType, test->m_toType)) {
                        spec.extensions.push_back("VK_KHR_16bit_storage");
+                       spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
+               }
 
                group->addChild(new SpvAsmComputeShaderCase(testCtx, test->m_name.c_str(), "", spec, test->m_features));
        }
@@ -8484,22 +8565,26 @@ tcu::TestCaseGroup* createConvertGraphicsTests (tcu::TestContext& testCtx, const
                vector<string>          features                = getFeatureStringVector(test->m_features);
                GraphicsResources       resources;
                vector<string>          extensions;
-               vector<deInt32>         noSpecConstants;
+               SpecConstants           noSpecConstants;
                PushConstants           noPushConstants;
+               VulkanFeatures          vulkanFeatures;
                GraphicsInterfaces      noInterfaces;
                tcu::RGBA                       defaultColors[4];
 
                getDefaultColors                        (defaultColors);
-               resources.inputs.push_back      (std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, test->m_inputBuffer));
-               resources.outputs.push_back     (std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, test->m_outputBuffer));
+               resources.inputs.push_back      (Resource(test->m_inputBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+               resources.outputs.push_back     (Resource(test->m_outputBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
                extensions.push_back            ("VK_KHR_storage_buffer_storage_class");
 
                if (test->m_features == COMPUTE_TEST_USES_INT16 || test->m_features == COMPUTE_TEST_USES_INT16_INT64 || usesInt16(test->m_fromType, test->m_toType))
+               {
                        extensions.push_back("VK_KHR_16bit_storage");
+                       vulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
+               }
 
                createTestsForAllStages(
                        test->m_name, defaultColors, defaultColors, fragments, noSpecConstants,
-                       noPushConstants, resources, noInterfaces, extensions, features, VulkanFeatures(), group.get());
+                       noPushConstants, resources, noInterfaces, extensions, features, vulkanFeatures, group.get());
        }
        return group.release();
 }
@@ -9119,7 +9204,7 @@ const string specializeDefaultOutputShaderTemplate (const NumberType type, const
        ).specialize(parameters);
 }
 
-bool compareFloats (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog& log)
+bool compareFloats (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog& log)
 {
        DE_ASSERT(outputAllocs.size() != 0);
        DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
@@ -9133,7 +9218,7 @@ bool compareFloats (const std::vector<BufferSp>&, const vector<AllocationSp>& ou
                float                   expected;
                float                   actual;
 
-               expectedOutputs[outputNdx]->getBytes(expectedBytes);
+               expectedOutputs[outputNdx].getBytes(expectedBytes);
                memcpy(&expected, &expectedBytes.front(), expectedBytes.size());
                memcpy(&actual, outputAllocs[outputNdx]->getHostPtr(), expectedBytes.size());
 
@@ -9149,7 +9234,7 @@ bool compareFloats (const std::vector<BufferSp>&, const vector<AllocationSp>& ou
 }
 
 // Checks if the driver crash with uninitialized cases
-bool passthruVerify (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+bool passthruVerify (const std::vector<Resource>&, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog&)
 {
        DE_ASSERT(outputAllocs.size() != 0);
        DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
@@ -9158,7 +9243,7 @@ bool passthruVerify (const std::vector<BufferSp>&, const vector<AllocationSp>& o
        for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
        {
                vector<deUint8> expectedBytes;
-               expectedOutputs[outputNdx]->getBytes(expectedBytes);
+               expectedOutputs[outputNdx].getBytes(expectedBytes);
 
                const size_t    width                   = expectedBytes.size();
                vector<char>    data                    (width);
@@ -9247,7 +9332,7 @@ tcu::TestCaseGroup* createOpNopTests (tcu::TestContext& testCtx)
        getDefaultColors(defaultColors);
 
        opNopFragments["testfun"]               =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_testfun = OpLabel\n"
                "OpNop\n"
@@ -9285,7 +9370,7 @@ tcu::TestCaseGroup* createOpNameTests (tcu::TestContext& testCtx)
                "OpName %BP_main \"not_main\"";
 
        opNameFragments["testfun"]              =
-               "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
                "%param1 = OpFunctionParameter %v4f32\n"
                "%label_func = OpLabel\n"
                "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
@@ -9313,7 +9398,8 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createOpNopGroup(testCtx));
        computeTests->addChild(createOpFUnordGroup(testCtx));
        computeTests->addChild(createOpAtomicGroup(testCtx, false));
-       computeTests->addChild(createOpAtomicGroup(testCtx, true)); // Using new StorageBuffer decoration
+       computeTests->addChild(createOpAtomicGroup(testCtx, true));                                     // Using new StorageBuffer decoration
+       computeTests->addChild(createOpAtomicGroup(testCtx, false, 1024, true));        // Return value validation
        computeTests->addChild(createOpLineGroup(testCtx));
        computeTests->addChild(createOpModuleProcessedGroup(testCtx));
        computeTests->addChild(createOpNoLineGroup(testCtx));
@@ -9359,6 +9445,8 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
 
                computeTests->addChild(computeAndroidTests.release());
        }
+
+       computeTests->addChild(create8BitStorageComputeGroup(testCtx));
        computeTests->addChild(create16BitStorageComputeGroup(testCtx));
        computeTests->addChild(createUboMatrixPaddingComputeGroup(testCtx));
        computeTests->addChild(createVariableInitComputeGroup(testCtx));
@@ -9367,6 +9455,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createVariablePointersComputeGroup(testCtx));
        computeTests->addChild(createImageSamplerComputeGroup(testCtx));
        computeTests->addChild(createOpNameGroup(testCtx));
+       computeTests->addChild(createPointerParameterComputeGroup(testCtx));
        graphicsTests->addChild(createCrossStageInterfaceTests(testCtx));
        graphicsTests->addChild(createSpivVersionCheckTests(testCtx, !testComputePipeline));
        graphicsTests->addChild(createOpNopTests(testCtx));
@@ -9404,6 +9493,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        }
        graphicsTests->addChild(createOpNameTests(testCtx));
 
+       graphicsTests->addChild(create8BitStorageGraphicsGroup(testCtx));
        graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
        graphicsTests->addChild(createUboMatrixPaddingGraphicsGroup(testCtx));
        graphicsTests->addChild(createVariableInitGraphicsGroup(testCtx));
@@ -9414,6 +9504,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpSConvert", "sconvert"));
        graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpUConvert", "uconvert"));
        graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpFConvert", "fconvert"));
+       graphicsTests->addChild(createPointerParameterGraphicsGroup(testCtx));
 
        instructionTests->addChild(computeTests.release());
        instructionTests->addChild(graphicsTests.release());