Need Float16 in some derivative tests
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmInstructionTests.cpp
index a0a6799..bfa7d9e 100644 (file)
@@ -48,6 +48,7 @@
 #include "deStringUtil.hpp"
 #include "deUniquePtr.hpp"
 #include "deMath.h"
+#include "deRandom.hpp"
 #include "tcuStringTemplate.hpp"
 
 #include "vktSpvAsmCrossStageInterfaceTests.hpp"
 #include "vktTestCaseUtil.hpp"
 #include "vktSpvAsmLoopDepLenTests.hpp"
 #include "vktSpvAsmLoopDepInfTests.hpp"
+#include "vktSpvAsmCompositeInsertTests.hpp"
+#include "vktSpvAsmVaryingNameTests.hpp"
+#include "vktSpvAsmWorkgroupMemoryTests.hpp"
+#include "vktSpvAsmSignedIntCompareTests.hpp"
+#include "vktSpvAsmPtrAccessChainTests.hpp"
 
 #include <cmath>
 #include <limits>
@@ -99,6 +105,7 @@ using de::UniquePtr;
 using tcu::StringTemplate;
 using tcu::Vec4;
 
+const bool TEST_WITH_NAN       = true;
 const bool TEST_WITHOUT_NAN    = false;
 
 template<typename T>
@@ -106,7 +113,7 @@ static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* ds
 {
        T* const typedPtr = (T*)dst;
        for (int ndx = 0; ndx < numValues; ndx++)
-               typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
+               typedPtr[offset + ndx] = de::randomScalar<T>(rnd, minValue, maxValue);
 }
 
 // Filter is a function that returns true if a value should pass, false otherwise.
@@ -118,7 +125,7 @@ static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* ds
        for (int ndx = 0; ndx < numValues; ndx++)
        {
                do
-                       value = randomScalar<T>(rnd, minValue, maxValue);
+                       value = de::randomScalar<T>(rnd, minValue, maxValue);
                while (!filter(value));
 
                typedPtr[offset + ndx] = value;
@@ -373,6 +380,129 @@ tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
+tcu::TestCaseGroup* createUnusedVariableComputeTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "unused_variables", "Compute shaders with unused variables"));
+       de::Random                                              rnd                             (deStringHash(group->getName()));
+       const int                                               numElements             = 100;
+       vector<float>                                   positiveFloats  (numElements, 0);
+       vector<float>                                   negativeFloats  (numElements, 0);
+
+       fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+       for (size_t ndx = 0; ndx < numElements; ++ndx)
+               negativeFloats[ndx] = -positiveFloats[ndx];
+
+       const VariableLocation                  testLocations[] =
+       {
+               // Set          Binding
+               { 0,            5                       },
+               { 5,            5                       },
+       };
+
+       for (size_t locationNdx = 0; locationNdx < DE_LENGTH_OF_ARRAY(testLocations); ++locationNdx)
+       {
+               const VariableLocation& location = testLocations[locationNdx];
+
+               // Unused variable.
+               {
+                       ComputeShaderSpec                               spec;
+
+                       spec.assembly =
+                               string(getComputeAsmShaderPreamble()) +
+
+                               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+                               + getUnusedDecorations(location)
+
+                               + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes())
+
+                               + getUnusedTypesAndConstants()
+
+                               + string(getComputeAsmInputOutputBuffer())
+
+                               + getUnusedBuffer() +
+
+                               "%id        = OpVariable %uvec3ptr Input\n"
+                               "%zero      = OpConstant %i32 0\n"
+
+                               "%main      = OpFunction %void None %voidf\n"
+                               "%label     = OpLabel\n"
+                               "%idval     = OpLoad %uvec3 %id\n"
+                               "%x         = OpCompositeExtract %u32 %idval 0\n"
+
+                               "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
+                               "%inval     = OpLoad %f32 %inloc\n"
+                               "%neg       = OpFNegate %f32 %inval\n"
+                               "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
+                               "             OpStore %outloc %neg\n"
+                               "             OpReturn\n"
+                               "             OpFunctionEnd\n";
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+                       spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+                       std::string testName            = "variable_" + location.toString();
+                       std::string testDescription     = "Unused variable test with " + location.toDescription();
+
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testDescription.c_str(), spec));
+               }
+
+               // Unused function.
+               {
+                       ComputeShaderSpec                               spec;
+
+                       spec.assembly =
+                               string(getComputeAsmShaderPreamble("", "", "", getUnusedEntryPoint())) +
+
+                               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+                               + getUnusedDecorations(location)
+
+                               + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes())
+
+                               + getUnusedTypesAndConstants() +
+
+                               "%c_i32_0 = OpConstant %i32 0\n"
+                               "%c_i32_1 = OpConstant %i32 1\n"
+
+                               + string(getComputeAsmInputOutputBuffer())
+
+                               + getUnusedBuffer() +
+
+                               "%id        = OpVariable %uvec3ptr Input\n"
+                               "%zero      = OpConstant %i32 0\n"
+
+                               "%main      = OpFunction %void None %voidf\n"
+                               "%label     = OpLabel\n"
+                               "%idval     = OpLoad %uvec3 %id\n"
+                               "%x         = OpCompositeExtract %u32 %idval 0\n"
+
+                               "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
+                               "%inval     = OpLoad %f32 %inloc\n"
+                               "%neg       = OpFNegate %f32 %inval\n"
+                               "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
+                               "             OpStore %outloc %neg\n"
+                               "             OpReturn\n"
+                               "             OpFunctionEnd\n"
+
+                               + getUnusedFunctionBody();
+
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+                       spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+                       std::string testName            = "function_" + location.toString();
+                       std::string testDescription     = "Unused function test with " + location.toDescription();
+
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testDescription.c_str(), spec));
+               }
+       }
+
+       return group.release();
+}
+
+template<bool nanSupported>
 bool compareFUnord (const std::vector<Resource>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog& log)
 {
        if (outputAllocs.size() != 1)
@@ -394,6 +524,9 @@ bool compareFUnord (const std::vector<Resource>& inputs, const vector<Allocation
 
        for (size_t idx = 0; idx < expectedBytes.size() / sizeof(deInt32); ++idx)
        {
+               if (!nanSupported && (tcu::Float32(input1AsFloat[idx]).isNaN() || tcu::Float32(input2AsFloat[idx]).isNaN()))
+                       continue;
+
                if (outputAsInt[idx] != expectedOutputAsInt[idx])
                {
                        log << TestLog::Message << "ERROR: Sub-case failed. inputs: " << input1AsFloat[idx] << "," << input2AsFloat[idx] << " output: " << outputAsInt[idx]<< " expected output: " << expectedOutputAsInt[idx] << TestLog::EndMessage;
@@ -423,17 +556,19 @@ do { \
        cases.push_back(OpFUnordCase(#NAME, OPCODE, compare_##NAME::compare)); \
 } while (deGetFalse())
 
-tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
+tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx, const bool testWithNan)
 {
-       de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opfunord", "Test the OpFUnord* opcodes"));
+       const string                                    nan                             = testWithNan ? "_nan" : "";
+       const string                                    groupName               = "opfunord" + nan;
+       de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, groupName.c_str(), "Test the OpFUnord* opcodes"));
        de::Random                                              rnd                             (deStringHash(group->getName()));
        const int                                               numElements             = 100;
        vector<OpFUnordCase>                    cases;
-
+       string                                                  extensions              = testWithNan ? "OpExtension \"SPV_KHR_float_controls\"\n" : "";
+       string                                                  capabilities    = testWithNan ? "OpCapability SignedZeroInfNanPreserve\n" : "";
+       string                                                  exeModes                = testWithNan ? "OpExecutionMode %main SignedZeroInfNanPreserve 32\n" : "";
        const StringTemplate                    shaderTemplate  (
-
-               string(getComputeAsmShaderPreamble()) +
-
+               string(getComputeAsmShaderPreamble(capabilities, extensions, exeModes)) +
                "OpSource GLSL 430\n"
                "OpName %main           \"main\"\n"
                "OpName %id             \"gl_GlobalInvocationID\"\n"
@@ -524,8 +659,15 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
                spec.outputs.push_back(BufferSp(new Int32Buffer(expectedInts)));
-               spec.numWorkGroups = IVec3(numElements, 1, 1);
-               spec.verifyIO = &compareFUnord;
+               spec.numWorkGroups      = IVec3(numElements, 1, 1);
+               spec.verifyIO           = testWithNan ? &compareFUnord<true> : &compareFUnord<false>;
+
+               if (testWithNan)
+               {
+                       spec.extensions.push_back("VK_KHR_shader_float_controls");
+                       spec.requestedVulkanFeatures.floatControlsProperties.shaderSignedZeroInfNanPreserveFloat32 = DE_TRUE;
+               }
+
                group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
        }
 
@@ -2999,9 +3141,9 @@ void createOpPhiVartypeTests (de::MovePtr<tcu::TestCaseGroup>& group, tcu::TestC
 
                "%id       = OpVariable %uvec3ptr Input\n"
                "%zero     = OpConstant %i32 0\n"
-               "%float_0  = OpConstant %f16 0.0\n"
-               "%float_1  = OpConstant %f16 1.0\n"
-               "%float_n1 = OpConstant %f16 -1.0\n"
+               "%float_0  = OpConstant %f32 0.0\n"
+               "%float_1  = OpConstant %f32 1.0\n"
+               "%float_n1 = OpConstant %f32 -1.0\n"
 
                "%main     = OpFunction %void None %voidf\n"
                "%entry    = OpLabel\n"
@@ -3009,8 +3151,9 @@ void createOpPhiVartypeTests (de::MovePtr<tcu::TestCaseGroup>& group, tcu::TestC
                "%x        = OpCompositeExtract %u32 %idval 0\n"
                "%inloc    = OpAccessChain %f16ptr %indata %zero %x\n"
                "%inval    = OpLoad %f16 %inloc\n"
+               "%f32_inval = OpFConvert %f32 %inval\n"
 
-               "%comp     = OpFOrdGreaterThan %bool %inval %float_0\n"
+               "%comp     = OpFOrdGreaterThan %bool %f32_inval %float_0\n"
                "            OpSelectionMerge %cm None\n"
                "            OpBranchConditional %comp %tb %fb\n"
                "%tb       = OpLabel\n"
@@ -3018,10 +3161,11 @@ void createOpPhiVartypeTests (de::MovePtr<tcu::TestCaseGroup>& group, tcu::TestC
                "%fb       = OpLabel\n"
                "            OpBranch %cm\n"
                "%cm       = OpLabel\n"
-               "%res      = OpPhi %f16 %float_1 %tb %float_n1 %fb\n"
+               "%res      = OpPhi %f32 %float_1 %tb %float_n1 %fb\n"
+               "%f16_res  = OpFConvert %f16 %res\n"
 
                "%outloc   = OpAccessChain %f16ptr %outdata %zero %x\n"
-               "            OpStore %outloc %res\n"
+               "            OpStore %outloc %f16_res\n"
                "            OpReturn\n"
 
                "            OpFunctionEnd\n";
@@ -5107,7 +5251,6 @@ tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
        cases.push_back(CaseParameter("none",                           "None"));
        cases.push_back(CaseParameter("unroll",                         "Unroll"));
        cases.push_back(CaseParameter("dont_unroll",            "DontUnroll"));
-       cases.push_back(CaseParameter("unroll_dont_unroll",     "Unroll|DontUnroll"));
 
        fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
 
@@ -5229,37 +5372,112 @@ tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
-tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
+void getOpNameAbuseCases (vector<CaseParameter> &abuseCases)
+{
+       // Generate a long name.
+       std::string longname;
+       longname.resize(65535, 'k'); // max string literal, spir-v 2.17
+
+       // Some bad names, abusing utf-8 encoding. This may also cause problems
+       // with the logs.
+       // 1. Various illegal code points in utf-8
+       std::string utf8illegal =
+               "Illegal bytes in UTF-8: "
+               "\xc0 \xc1 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff"
+               "illegal surrogates: \xed\xad\xbf \xed\xbe\x80";
+
+       // 2. Zero encoded as overlong, not exactly legal but often supported to differentiate from terminating zero
+       std::string utf8nul = "UTF-8 encoded nul \xC0\x80 (should not end name)";
+
+       // 3. Some overlong encodings
+       std::string utf8overlong =
+               "UTF-8 overlong \xF0\x82\x82\xAC \xfc\x83\xbf\xbf\xbf\xbf \xf8\x87\xbf\xbf\xbf "
+               "\xf0\x8f\xbf\xbf";
+
+       // 4. Internet "zalgo" meme "bleeding text"
+       std::string utf8zalgo =
+               "\x56\xcc\xb5\xcc\x85\xcc\x94\xcc\x88\xcd\x8a\xcc\x91\xcc\x88\xcd\x91\xcc\x83\xcd\x82"
+               "\xcc\x83\xcd\x90\xcc\x8a\xcc\x92\xcc\x92\xcd\x8b\xcc\x94\xcd\x9d\xcc\x98\xcc\xab\xcc"
+               "\xae\xcc\xa9\xcc\xad\xcc\x97\xcc\xb0\x75\xcc\xb6\xcc\xbe\xcc\x80\xcc\x82\xcc\x84\xcd"
+               "\x84\xcc\x90\xcd\x86\xcc\x9a\xcd\x84\xcc\x9b\xcd\x86\xcd\x92\xcc\x9a\xcd\x99\xcd\x99"
+               "\xcc\xbb\xcc\x98\xcd\x8e\xcd\x88\xcd\x9a\xcc\xa6\xcc\x9c\xcc\xab\xcc\x99\xcd\x94\xcd"
+               "\x99\xcd\x95\xcc\xa5\xcc\xab\xcd\x89\x6c\xcc\xb8\xcc\x8e\xcc\x8b\xcc\x8b\xcc\x9a\xcc"
+               "\x8e\xcd\x9d\xcc\x80\xcc\xa1\xcc\xad\xcd\x9c\xcc\xba\xcc\x96\xcc\xb3\xcc\xa2\xcd\x8e"
+               "\xcc\xa2\xcd\x96\x6b\xcc\xb8\xcc\x84\xcd\x81\xcc\xbf\xcc\x8d\xcc\x89\xcc\x85\xcc\x92"
+               "\xcc\x84\xcc\x90\xcd\x81\xcc\x93\xcd\x90\xcd\x92\xcd\x9d\xcc\x84\xcd\x98\xcd\x9d\xcd"
+               "\xa0\xcd\x91\xcc\x94\xcc\xb9\xcd\x93\xcc\xa5\xcd\x87\xcc\xad\xcc\xa7\xcd\x96\xcd\x99"
+               "\xcc\x9d\xcc\xbc\xcd\x96\xcd\x93\xcc\x9d\xcc\x99\xcc\xa8\xcc\xb1\xcd\x85\xcc\xba\xcc"
+               "\xa7\x61\xcc\xb8\xcc\x8e\xcc\x81\xcd\x90\xcd\x84\xcd\x8c\xcc\x8c\xcc\x85\xcd\x86\xcc"
+               "\x84\xcd\x84\xcc\x90\xcc\x84\xcc\x8d\xcd\x99\xcd\x8d\xcc\xb0\xcc\xa3\xcc\xa6\xcd\x89"
+               "\xcd\x8d\xcd\x87\xcc\x98\xcd\x8d\xcc\xa4\xcd\x9a\xcd\x8e\xcc\xab\xcc\xb9\xcc\xac\xcc"
+               "\xa2\xcd\x87\xcc\xa0\xcc\xb3\xcd\x89\xcc\xb9\xcc\xa7\xcc\xa6\xcd\x89\xcd\x95\x6e\xcc"
+               "\xb8\xcd\x8a\xcc\x8a\xcd\x82\xcc\x9b\xcd\x81\xcd\x90\xcc\x85\xcc\x9b\xcd\x80\xcd\x91"
+               "\xcd\x9b\xcc\x81\xcd\x81\xcc\x9a\xcc\xb3\xcd\x9c\xcc\x9e\xcc\x9d\xcd\x99\xcc\xa2\xcd"
+               "\x93\xcd\x96\xcc\x97\xff";
+
+       // General name abuses
+       abuseCases.push_back(CaseParameter("_has_very_long_name", longname));
+       abuseCases.push_back(CaseParameter("_utf8_illegal", utf8illegal));
+       abuseCases.push_back(CaseParameter("_utf8_nul", utf8nul));
+       abuseCases.push_back(CaseParameter("_utf8_overlong", utf8overlong));
+       abuseCases.push_back(CaseParameter("_utf8_zalgo", utf8zalgo));
+
+       // GL keywords
+       abuseCases.push_back(CaseParameter("_is_gl_Position", "gl_Position"));
+       abuseCases.push_back(CaseParameter("_is_gl_InstanceID", "gl_InstanceID"));
+       abuseCases.push_back(CaseParameter("_is_gl_PrimitiveID", "gl_PrimitiveID"));
+       abuseCases.push_back(CaseParameter("_is_gl_TessCoord", "gl_TessCoord"));
+       abuseCases.push_back(CaseParameter("_is_gl_PerVertex", "gl_PerVertex"));
+       abuseCases.push_back(CaseParameter("_is_gl_InvocationID", "gl_InvocationID"));
+       abuseCases.push_back(CaseParameter("_is_gl_PointSize", "gl_PointSize"));
+       abuseCases.push_back(CaseParameter("_is_gl_PointCoord", "gl_PointCoord"));
+       abuseCases.push_back(CaseParameter("_is_gl_Layer", "gl_Layer"));
+       abuseCases.push_back(CaseParameter("_is_gl_FragDepth", "gl_FragDepth"));
+       abuseCases.push_back(CaseParameter("_is_gl_NumWorkGroups", "gl_NumWorkGroups"));
+       abuseCases.push_back(CaseParameter("_is_gl_WorkGroupID", "gl_WorkGroupID"));
+       abuseCases.push_back(CaseParameter("_is_gl_LocalInvocationID", "gl_LocalInvocationID"));
+       abuseCases.push_back(CaseParameter("_is_gl_GlobalInvocationID", "gl_GlobalInvocationID"));
+       abuseCases.push_back(CaseParameter("_is_gl_MaxVertexAttribs", "gl_MaxVertexAttribs"));
+       abuseCases.push_back(CaseParameter("_is_gl_MaxViewports", "gl_MaxViewports"));
+       abuseCases.push_back(CaseParameter("_is_gl_MaxComputeWorkGroupCount", "gl_MaxComputeWorkGroupCount"));
+       abuseCases.push_back(CaseParameter("_is_mat3", "mat3"));
+       abuseCases.push_back(CaseParameter("_is_volatile", "volatile"));
+       abuseCases.push_back(CaseParameter("_is_inout", "inout"));
+       abuseCases.push_back(CaseParameter("_is_isampler3d", "isampler3d"));
+}
+
+tcu::TestCaseGroup* createOpNameGroup (tcu::TestContext& testCtx)
 {
        de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opname", "Tests OpName cases"));
        de::MovePtr<tcu::TestCaseGroup> entryMainGroup  (new tcu::TestCaseGroup(testCtx, "entry_main", "OpName tests with entry main"));
        de::MovePtr<tcu::TestCaseGroup> entryNotGroup   (new tcu::TestCaseGroup(testCtx, "entry_rdc", "OpName tests with entry rdc"));
+       de::MovePtr<tcu::TestCaseGroup> abuseGroup              (new tcu::TestCaseGroup(testCtx, "abuse", "OpName abuse tests"));
        vector<CaseParameter>                   cases;
+       vector<CaseParameter>                   abuseCases;
        vector<string>                                  testFunc;
        de::Random                                              rnd                             (deStringHash(group->getName()));
-       const int                                               numElements             = 100;
+       const int                                               numElements             = 128;
        vector<float>                                   inputFloats             (numElements, 0);
        vector<float>                                   outputFloats    (numElements, 0);
 
+       getOpNameAbuseCases(abuseCases);
+
        fillRandomScalars(rnd, -100.0f, 100.0f, &inputFloats[0], numElements);
 
        for(size_t ndx = 0; ndx < numElements; ++ndx)
                outputFloats[ndx] = -inputFloats[ndx];
 
-       const StringTemplate shaderTemplate (
+       const string commonShaderHeader =
                "OpCapability Shader\n"
                "OpMemoryModel Logical GLSL450\n"
-               "OpEntryPoint GLCompute %main \"${ENTRY}\" %id\n"
-               "OpExecutionMode %main LocalSize 1 1 1\n"
-
-               "OpName %${FUNC_ID} \"${NAME}\"\n"
+               "OpEntryPoint GLCompute %main \"main\" %id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n";
 
+       const string commonShaderFooter =
                "OpDecorate %id BuiltIn GlobalInvocationId\n"
 
                + string(getComputeAsmInputOutputBufferTraits())
-
                + string(getComputeAsmCommonTypes())
-
                + string(getComputeAsmInputOutputBuffer()) +
 
                "%id        = OpVariable %uvec3ptr Input\n"
@@ -5283,13 +5501,126 @@ tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
                "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
                "             OpStore %outloc %neg\n"
 
-
                "             OpReturn\n"
-               "             OpFunctionEnd\n");
+               "             OpFunctionEnd\n";
+
+       const StringTemplate shaderTemplate (
+               "OpCapability Shader\n"
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"${ENTRY}\" %id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n"
+               "OpName %${ID} \"${NAME}\"\n" +
+               commonShaderFooter);
+
+       const std::string multipleNames =
+               commonShaderHeader +
+               "OpName %main \"to_be\"\n"
+               "OpName %id   \"or_not\"\n"
+               "OpName %main \"to_be\"\n"
+               "OpName %main \"makes_no\"\n"
+               "OpName %func \"difference\"\n"
+               "OpName %5    \"to_me\"\n" +
+               commonShaderFooter;
+
+       {
+               ComputeShaderSpec       spec;
+
+               spec.assembly           = multipleNames;
+               spec.numWorkGroups      = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "main_has_multiple_names", "multiple_names", spec));
+       }
+
+       const std::string everythingNamed =
+               commonShaderHeader +
+               "OpName %main   \"name1\"\n"
+               "OpName %id     \"name2\"\n"
+               "OpName %zero   \"name3\"\n"
+               "OpName %entry  \"name4\"\n"
+               "OpName %func   \"name5\"\n"
+               "OpName %5      \"name6\"\n"
+               "OpName %7      \"name7\"\n"
+               "OpName %idval  \"name8\"\n"
+               "OpName %inloc  \"name9\"\n"
+               "OpName %inval  \"name10\"\n"
+               "OpName %neg    \"name11\"\n"
+               "OpName %outloc \"name12\"\n"+
+               commonShaderFooter;
+       {
+               ComputeShaderSpec       spec;
+
+               spec.assembly           = everythingNamed;
+               spec.numWorkGroups      = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named", "everything_named", spec));
+       }
+
+       const std::string everythingNamedTheSame =
+               commonShaderHeader +
+               "OpName %main   \"the_same\"\n"
+               "OpName %id     \"the_same\"\n"
+               "OpName %zero   \"the_same\"\n"
+               "OpName %entry  \"the_same\"\n"
+               "OpName %func   \"the_same\"\n"
+               "OpName %5      \"the_same\"\n"
+               "OpName %7      \"the_same\"\n"
+               "OpName %idval  \"the_same\"\n"
+               "OpName %inloc  \"the_same\"\n"
+               "OpName %inval  \"the_same\"\n"
+               "OpName %neg    \"the_same\"\n"
+               "OpName %outloc \"the_same\"\n"+
+               commonShaderFooter;
+       {
+               ComputeShaderSpec       spec;
+
+               spec.assembly           = everythingNamedTheSame;
+               spec.numWorkGroups      = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named_the_same", "everything_named_the_same", spec));
+       }
+
+       // main_is_...
+       for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+       {
+               map<string, string>     specializations;
+               ComputeShaderSpec       spec;
+
+               specializations["ENTRY"]        = "main";
+               specializations["ID"]           = "main";
+               specializations["NAME"]         = abuseCases[ndx].param;
+               spec.assembly                           = shaderTemplate.specialize(specializations);
+               spec.numWorkGroups                      = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("main") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+       }
+
+       // x_is_....
+       for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+       {
+               map<string, string>     specializations;
+               ComputeShaderSpec       spec;
+
+               specializations["ENTRY"]        = "main";
+               specializations["ID"]           = "x";
+               specializations["NAME"]         = abuseCases[ndx].param;
+               spec.assembly                           = shaderTemplate.specialize(specializations);
+               spec.numWorkGroups                      = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("x") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+       }
 
        cases.push_back(CaseParameter("_is_main", "main"));
        cases.push_back(CaseParameter("_is_not_main", "not_main"));
-
        testFunc.push_back("main");
        testFunc.push_back("func");
 
@@ -5297,14 +5628,14 @@ tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
        {
                for(size_t ndx = 0; ndx < cases.size(); ++ndx)
                {
-                       map<string, string>     specializations;
-                       ComputeShaderSpec       spec;
+                       map<string, string>     specializations;
+                       ComputeShaderSpec       spec;
 
-                       specializations["ENTRY"] = "main";
-                       specializations["FUNC_ID"] = testFunc[fNdx];
-                       specializations["NAME"] = cases[ndx].param;
-                       spec.assembly = shaderTemplate.specialize(specializations);
-                       spec.numWorkGroups = IVec3(numElements, 1, 1);
+                       specializations["ENTRY"]        = "main";
+                       specializations["ID"]           = testFunc[fNdx];
+                       specializations["NAME"]         = cases[ndx].param;
+                       spec.assembly                           = shaderTemplate.specialize(specializations);
+                       spec.numWorkGroups                      = IVec3(numElements, 1, 1);
                        spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
                        spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
 
@@ -5321,14 +5652,14 @@ tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
                        map<string, string>     specializations;
                        ComputeShaderSpec       spec;
 
-                       specializations["ENTRY"] = "rdc";
-                       specializations["FUNC_ID"] = testFunc[fNdx];
-                       specializations["NAME"] = cases[ndx].param;
-                       spec.assembly = shaderTemplate.specialize(specializations);
-                       spec.numWorkGroups = IVec3(numElements, 1, 1);
+                       specializations["ENTRY"]        = "rdc";
+                       specializations["ID"]           = testFunc[fNdx];
+                       specializations["NAME"]         = cases[ndx].param;
+                       spec.assembly                           = shaderTemplate.specialize(specializations);
+                       spec.numWorkGroups                      = IVec3(numElements, 1, 1);
+                       spec.entryPoint                         = "rdc";
                        spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
                        spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
-                       spec.entryPoint = "rdc";
 
                        entryNotGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (testFunc[fNdx] + cases[ndx].name).c_str(), cases[ndx].name, spec));
                }
@@ -5336,6 +5667,124 @@ tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
 
        group->addChild(entryMainGroup.release());
        group->addChild(entryNotGroup.release());
+       group->addChild(abuseGroup.release());
+
+       return group.release();
+}
+
+tcu::TestCaseGroup* createOpMemberNameGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "opmembername", "Tests OpMemberName cases"));
+       de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "abuse", "OpMemberName abuse tests"));
+       vector<CaseParameter>                   abuseCases;
+       vector<string>                                  testFunc;
+       de::Random                                              rnd(deStringHash(group->getName()));
+       const int                                               numElements = 128;
+       vector<float>                                   inputFloats(numElements, 0);
+       vector<float>                                   outputFloats(numElements, 0);
+
+       getOpNameAbuseCases(abuseCases);
+
+       fillRandomScalars(rnd, -100.0f, 100.0f, &inputFloats[0], numElements);
+
+       for (size_t ndx = 0; ndx < numElements; ++ndx)
+               outputFloats[ndx] = -inputFloats[ndx];
+
+       const string commonShaderHeader =
+               "OpCapability Shader\n"
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"main\" %id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n";
+
+       const string commonShaderFooter =
+               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+               + string(getComputeAsmInputOutputBufferTraits())
+               + string(getComputeAsmCommonTypes())
+               + string(getComputeAsmInputOutputBuffer()) +
+
+               "%u3str     = OpTypeStruct %u32 %u32 %u32\n"
+
+               "%id        = OpVariable %uvec3ptr Input\n"
+               "%zero      = OpConstant %i32 0\n"
+
+               "%main      = OpFunction %void None %voidf\n"
+               "%entry     = OpLabel\n"
+
+               "%idval     = OpLoad %uvec3 %id\n"
+               "%x0        = OpCompositeExtract %u32 %idval 0\n"
+
+               "%idstr     = OpCompositeConstruct %u3str %x0 %x0 %x0\n"
+               "%x         = OpCompositeExtract %u32 %idstr 0\n"
+
+               "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
+               "%inval     = OpLoad %f32 %inloc\n"
+               "%neg       = OpFNegate %f32 %inval\n"
+               "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
+               "             OpStore %outloc %neg\n"
+
+               "             OpReturn\n"
+               "             OpFunctionEnd\n";
+
+       const StringTemplate shaderTemplate(
+               commonShaderHeader +
+               "OpMemberName %u3str 0 \"${NAME}\"\n" +
+               commonShaderFooter);
+
+       const std::string multipleNames =
+               commonShaderHeader +
+               "OpMemberName %u3str 0 \"to_be\"\n"
+               "OpMemberName %u3str 1 \"or_not\"\n"
+               "OpMemberName %u3str 0 \"to_be\"\n"
+               "OpMemberName %u3str 2 \"makes_no\"\n"
+               "OpMemberName %u3str 0 \"difference\"\n"
+               "OpMemberName %u3str 0 \"to_me\"\n" +
+               commonShaderFooter;
+       {
+               ComputeShaderSpec       spec;
+
+               spec.assembly = multipleNames;
+               spec.numWorkGroups = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "u3str_x_has_multiple_names", "multiple_names", spec));
+       }
+
+       const std::string everythingNamedTheSame =
+               commonShaderHeader +
+               "OpMemberName %u3str 0 \"the_same\"\n"
+               "OpMemberName %u3str 1 \"the_same\"\n"
+               "OpMemberName %u3str 2 \"the_same\"\n" +
+               commonShaderFooter;
+
+       {
+               ComputeShaderSpec       spec;
+
+               spec.assembly = everythingNamedTheSame;
+               spec.numWorkGroups = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named_the_same", "everything_named_the_same", spec));
+       }
+
+       // u3str_x_is_....
+       for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+       {
+               map<string, string>     specializations;
+               ComputeShaderSpec       spec;
+
+               specializations["NAME"] = abuseCases[ndx].param;
+               spec.assembly = shaderTemplate.specialize(specializations);
+               spec.numWorkGroups = IVec3(numElements, 1, 1);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+               abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("u3str_x") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+       }
+
+       group->addChild(abuseGroup.release());
 
        return group.release();
 }
@@ -5671,7 +6120,12 @@ tcu::TestCaseGroup* createFloat16OpConstantCompositeGroup (tcu::TestContext& tes
                spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
                spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
                spec.numWorkGroups = IVec3(numElements, 1, 1);
+
                spec.extensions.push_back("VK_KHR_16bit_storage");
+               spec.extensions.push_back("VK_KHR_shader_float16_int8");
+
+               spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
+               spec.requestedVulkanFeatures.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
 
                group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
        }
@@ -5679,84 +6133,18 @@ tcu::TestCaseGroup* createFloat16OpConstantCompositeGroup (tcu::TestContext& tes
        return group.release();
 }
 
-// IEEE-754 floating point numbers:
-// +--------+------+----------+-------------+
-// | binary | sign | exponent | significand |
-// +--------+------+----------+-------------+
-// | 16-bit |  1   |    5     |     10      |
-// +--------+------+----------+-------------+
-// | 32-bit |  1   |    8     |     23      |
-// +--------+------+----------+-------------+
-//
-// 16-bit floats:
-//
-// 0   000 00   00 0000 0001 (0x0001: 2e-24:         minimum positive denormalized)
-// 0   000 00   11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
-// 0   000 01   00 0000 0000 (0x0400: 2e-14:         minimum positive normalized)
-//
-// 0   000 00   00 0000 0000 (0x0000: +0)
-// 0   111 11   00 0000 0000 (0x7c00: +Inf)
-// 0   000 00   11 1111 0000 (0x03f0: +Denorm)
-// 0   000 01   00 0000 0001 (0x0401: +Norm)
-// 0   111 11   00 0000 1111 (0x7c0f: +SNaN)
-// 0   111 11   11 1111 0000 (0x7ff0: +QNaN)
-
-// Generate and return 16-bit floats and their corresponding 32-bit values.
-//
-// The first 14 number pairs are manually picked, while the rest are randomly generated.
-// Expected count to be at least 14 (numPicks).
-vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count)
+const vector<deFloat16> squarize(const vector<deFloat16>& inData, const deUint32 argNo)
 {
-       vector<deFloat16>       float16;
+       const size_t            inDataLength    = inData.size();
+       vector<deFloat16>       result;
 
-       float16.reserve(count);
+       result.reserve(inDataLength * inDataLength);
 
-       // Zero
-       float16.push_back(deUint16(0x0000));
-       float16.push_back(deUint16(0x8000));
-       // Infinity
-       float16.push_back(deUint16(0x7c00));
-       float16.push_back(deUint16(0xfc00));
-       // SNaN
-       float16.push_back(deUint16(0x7c0f));
-       float16.push_back(deUint16(0xfc0f));
-       // QNaN
-       float16.push_back(deUint16(0x7ff0));
-       float16.push_back(deUint16(0xfff0));
-
-       // Denormalized
-       float16.push_back(deUint16(0x03f0));
-       float16.push_back(deUint16(0x83f0));
-       // Normalized
-       float16.push_back(deUint16(0x0401));
-       float16.push_back(deUint16(0x8401));
-       // Some normal number
-       float16.push_back(deUint16(0x14cb));
-       float16.push_back(deUint16(0x94cb));
-
-       const deUint32          numPicks        = static_cast<deUint32>(float16.size());
-
-       DE_ASSERT(count >= numPicks);
-       count -= numPicks;
-
-       for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
-               float16.push_back(rnd.getUint16());
-
-       return float16;
-}
-
-const vector<deFloat16> squarize(const vector<deFloat16>& inData, const deUint32 argNo)
-{
-       const size_t            inDataLength    = inData.size();
-       vector<deFloat16>       result;
-
-       result.reserve(inDataLength * inDataLength);
-
-       if (argNo == 0)
-       {
-               for (size_t numIdx = 0; numIdx < inDataLength; ++numIdx)
-                       result.insert(result.end(), inData.begin(), inData.end());
-       }
+       if (argNo == 0)
+       {
+               for (size_t numIdx = 0; numIdx < inDataLength; ++numIdx)
+                       result.insert(result.end(), inData.begin(), inData.end());
+       }
 
        if (argNo == 1)
        {
@@ -6851,16 +7239,16 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                map<string, string>                     specializations;
                map<string, string>                     fragments;
                SpecConstants                           specConstants;
-               vector<string>                          features;
                PushConstants                           noPushConstants;
                GraphicsResources                       noResources;
                GraphicsInterfaces                      noInterfaces;
-               std::vector<std::string>        noExtensions;
+               vector<string>                          extensions;
+               VulkanFeatures                          requiredFeatures;
 
                // Special SPIR-V code for SConvert-case
                if (strcmp(cases[caseNdx].caseName, "sconvert") == 0)
                {
-                       features.push_back("shaderInt16");
+                       requiredFeatures.coreFeatures.shaderInt16 = VK_TRUE;
                        fragments["capability"]                                 = "OpCapability Int16\n";                                       // Adds 16-bit integer capability
                        specializations["OPTYPE_DEFINITIONS"]   = "%i16 = OpTypeInt 16 1\n";                            // Adds 16-bit integer type
                        specializations["TYPE_CONVERT"]                 = "%sc_op32 = OpSConvert %i32 %sc_op\n";        // Converts 16-bit integer to 32-bit integer
@@ -6869,7 +7257,7 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                // Special SPIR-V code for FConvert-case
                if (strcmp(cases[caseNdx].caseName, "fconvert") == 0)
                {
-                       features.push_back("shaderFloat64");
+                       requiredFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
                        fragments["capability"]                                 = "OpCapability Float64\n";                                     // Adds 64-bit float capability
                        specializations["OPTYPE_DEFINITIONS"]   = "%f64 = OpTypeFloat 64\n";                            // Adds 64-bit float type
                        specializations["TYPE_CONVERT"]                 = "%sc_op32 = OpConvertFToS %i32 %sc_op\n";     // Converts 64-bit float to 32-bit integer
@@ -6878,6 +7266,8 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
                // Special SPIR-V code for FConvert-case for 16-bit floats
                if (strcmp(cases[caseNdx].caseName, "fconvert16") == 0)
                {
+                       extensions.push_back("VK_KHR_shader_float16_int8");
+                       requiredFeatures.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
                        fragments["capability"]                                 = "OpCapability Float16\n";                                     // Adds 16-bit float capability
                        specializations["OPTYPE_DEFINITIONS"]   = "%f16 = OpTypeFloat 16\n";                            // Adds 16-bit float type
                        specializations["TYPE_CONVERT"]                 = "%sc_op32 = OpConvertFToS %i32 %sc_op\n";     // Converts 16-bit float to 32-bit integer
@@ -6898,7 +7288,7 @@ tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
 
                createTestsForAllStages(
                        cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants,
-                       noPushConstants, noResources, noInterfaces, noExtensions, features, VulkanFeatures(), group.get());
+                       noPushConstants, noResources, noInterfaces, extensions, requiredFeatures, group.get());
        }
 
        const char      decorations2[]                  =
@@ -7832,20 +8222,69 @@ tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx)
        RGBA                                                            invertedColors[4];
        de::MovePtr<tcu::TestCaseGroup>         moduleTests                     (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders"));
 
-       const ShaderElement                                     combinedPipeline[]      =
-       {
-               ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
-               ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
-               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
-               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
-               ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
-       };
-
        getDefaultColors(defaultColors);
        getInvertedDefaultColors(invertedColors);
-       addFunctionCaseWithPrograms<InstanceContext>(
-                       moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
-                       createInstanceContext(combinedPipeline, map<string, string>()));
+
+       // Combined module tests
+       {
+               // Shader stages: vertex and fragment
+               {
+                       const ShaderElement combinedPipeline[]  =
+                       {
+                               ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+                       };
+
+                       addFunctionCaseWithPrograms<InstanceContext>(
+                               moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
+                               createInstanceContext(combinedPipeline, map<string, string>()));
+               }
+
+               // Shader stages: vertex, geometry and fragment
+               {
+                       const ShaderElement combinedPipeline[]  =
+                       {
+                               ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+                       };
+
+                       addFunctionCaseWithPrograms<InstanceContext>(
+                               moduleTests.get(), "same_module_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+                               createInstanceContext(combinedPipeline, map<string, string>()));
+               }
+
+               // Shader stages: vertex, tessellation control, tessellation evaluation and fragment
+               {
+                       const ShaderElement combinedPipeline[]  =
+                       {
+                               ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+                       };
+
+                       addFunctionCaseWithPrograms<InstanceContext>(
+                               moduleTests.get(), "same_module_tessc_tesse", "", createCombinedModule, runAndVerifyDefaultPipeline,
+                               createInstanceContext(combinedPipeline, map<string, string>()));
+               }
+
+               // Shader stages: vertex, tessellation control, tessellation evaluation, geometry and fragment
+               {
+                       const ShaderElement combinedPipeline[]  =
+                       {
+                               ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+                               ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+                       };
+
+                       addFunctionCaseWithPrograms<InstanceContext>(
+                               moduleTests.get(), "same_module_tessc_tesse_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+                               createInstanceContext(combinedPipeline, map<string, string>()));
+               }
+       }
 
        const char* numbers[] =
        {
@@ -7883,6 +8322,93 @@ tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx)
        return moduleTests.release();
 }
 
+std::string getUnusedVarTestNamePiece(const std::string& prefix, ShaderTask task)
+{
+       switch (task)
+       {
+               case SHADER_TASK_NONE:                  return "";
+               case SHADER_TASK_NORMAL:                return prefix + "_normal";
+               case SHADER_TASK_UNUSED_VAR:    return prefix + "_unused_var";
+               case SHADER_TASK_UNUSED_FUNC:   return prefix + "_unused_func";
+               default:                                                DE_ASSERT(DE_FALSE);
+       }
+       // unreachable
+       return "";
+}
+
+std::string getShaderTaskIndexName(ShaderTaskIndex index)
+{
+       switch (index)
+       {
+       case SHADER_TASK_INDEX_VERTEX:                  return "vertex";
+       case SHADER_TASK_INDEX_GEOMETRY:                return "geom";
+       case SHADER_TASK_INDEX_TESS_CONTROL:    return "tessc";
+       case SHADER_TASK_INDEX_TESS_EVAL:               return "tesse";
+       case SHADER_TASK_INDEX_FRAGMENT:                return "frag";
+       default:                                                                DE_ASSERT(DE_FALSE);
+       }
+       // unreachable
+       return "";
+}
+
+std::string getUnusedVarTestName(const ShaderTaskArray& shaderTasks, const VariableLocation& location)
+{
+       std::string testName = location.toString();
+
+       for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(shaderTasks); ++i)
+       {
+               if (shaderTasks[i] != SHADER_TASK_NONE)
+               {
+                       testName += "_" + getUnusedVarTestNamePiece(getShaderTaskIndexName((ShaderTaskIndex)i), shaderTasks[i]);
+               }
+       }
+
+       return testName;
+}
+
+tcu::TestCaseGroup* createUnusedVariableTests(tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup>         moduleTests                             (new tcu::TestCaseGroup(testCtx, "unused_variables", "Graphics shaders with unused variables"));
+
+       ShaderTaskArray                                         shaderCombinations[]    =
+       {
+               // Vertex                                       Geometry                                        Tess. Control                           Tess. Evaluation                        Fragment
+               { SHADER_TASK_UNUSED_VAR,       SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NORMAL      },
+               { SHADER_TASK_UNUSED_FUNC,      SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_UNUSED_VAR  },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_UNUSED_FUNC },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_UNUSED_VAR,         SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_UNUSED_FUNC,        SHADER_TASK_NONE,                       SHADER_TASK_NONE,                       SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_UNUSED_VAR,         SHADER_TASK_NORMAL,                     SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_UNUSED_FUNC,        SHADER_TASK_NORMAL,                     SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_NORMAL,                     SHADER_TASK_UNUSED_VAR,         SHADER_TASK_NORMAL      },
+               { SHADER_TASK_NORMAL,           SHADER_TASK_NONE,                       SHADER_TASK_NORMAL,                     SHADER_TASK_UNUSED_FUNC,        SHADER_TASK_NORMAL      }
+       };
+
+       const VariableLocation                          testLocations[] =
+       {
+               // Set          Binding
+               { 0,            5                       },
+               { 5,            5                       },
+       };
+
+       for (size_t combNdx = 0; combNdx < DE_LENGTH_OF_ARRAY(shaderCombinations); ++combNdx)
+       {
+               for (size_t locationNdx = 0; locationNdx < DE_LENGTH_OF_ARRAY(testLocations); ++locationNdx)
+               {
+                       const ShaderTaskArray&  shaderTasks             = shaderCombinations[combNdx];
+                       const VariableLocation& location                = testLocations[locationNdx];
+                       std::string                             testName                = getUnusedVarTestName(shaderTasks, location);
+
+                       addFunctionCaseWithPrograms<UnusedVariableContext>(
+                               moduleTests.get(), testName, "", createUnusedVariableModules, runAndVerifyUnusedVariablePipeline,
+                               createUnusedVariableContext(shaderTasks, location));
+               }
+       }
+
+       return moduleTests.release();
+}
+
 tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
 {
        de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "loop", "Looping control flow"));
@@ -8255,7 +8781,6 @@ tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
                "%then = OpLabel\n"
                "OpControlBarrier %Workgroup %Workgroup %WorkgroupAcquireRelease\n"
                "OpBranch %exit\n"
-
                "%exit = OpLabel\n"
                "%ret = OpPhi %v4f32 %param1 %then %wrong_branch_alert %else\n"
                "OpReturnValue %ret\n"
@@ -8877,7 +9402,7 @@ struct ConvertCase
 
                        if (instruction == "OpUConvert" || instruction == "OpSConvert" || instruction == "OpFConvert")
                        {
-                               // Conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Int16
+                               // Width-only conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Int16
                                if (usesInt32(from, to) || usesFloat32(from, to))
                                        requiresInt16Capability = false;
                        }
@@ -8895,15 +9420,14 @@ struct ConvertCase
                {
                        decl += "%f16        = OpTypeFloat 16\n";
 
-                       // Conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Float16
-                       if (!(usesInt32(from, to) || usesFloat32(from, to)))
+                       // Width-only conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Float16
+                       if (!usesFloat32(from, to))
                                caps += "OpCapability Float16\n";
                }
 
                if (usesInt16(from, to) || usesFloat16(from, to))
                {
-                       caps += "OpCapability StorageUniformBufferBlock16\n"
-                                       "OpCapability StorageUniform16\n";
+                       caps += "OpCapability StorageUniformBufferBlock16\n";
                        exts += "OpExtension \"SPV_KHR_16bit_storage\"\n";
                }
 
@@ -9219,6 +9743,8 @@ void createConvertCases (vector<ConvertCase>& testCases, const string& instructi
                testCases.push_back(ConvertCase(instruction,    DATA_TYPE_FLOAT_64,                     DATA_TYPE_SIGNED_16,            0xc093480000000000,                                     true,   -1234));
                testCases.push_back(ConvertCase(instruction,    DATA_TYPE_FLOAT_64,                     DATA_TYPE_SIGNED_32,            0xc093480000000000,                                     true,   -1234));
                testCases.push_back(ConvertCase(instruction,    DATA_TYPE_FLOAT_64,                     DATA_TYPE_SIGNED_64,            0xc093480000000000,                                     true,   -1234));
+               testCases.push_back(ConvertCase(instruction,    DATA_TYPE_FLOAT_32,                     DATA_TYPE_SIGNED_16,            0x453b9000,                                                     true,    3001,                                                          "p3001"));
+               testCases.push_back(ConvertCase(instruction,    DATA_TYPE_FLOAT_32,                     DATA_TYPE_SIGNED_16,            0xc53b9000,                                                     true,   -3001,                                                          "m3001"));
        }
        else if (instruction == "OpConvertSToF")
        {
@@ -9349,7 +9875,6 @@ tcu::TestCaseGroup* createConvertGraphicsTests (tcu::TestContext& testCtx, const
        for (vector<ConvertCase>::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
        {
                map<string, string>     fragments               = getConvertCaseFragments(instruction, *test);
-               vector<string>          features;
                VulkanFeatures          vulkanFeatures;
                GraphicsResources       resources;
                vector<string>          extensions;
@@ -9365,9 +9890,12 @@ tcu::TestCaseGroup* createConvertGraphicsTests (tcu::TestContext& testCtx, const
 
                getVulkanFeaturesAndExtensions(test->m_fromType, test->m_toType, vulkanFeatures, extensions);
 
+               vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics      = true;
+               vulkanFeatures.coreFeatures.fragmentStoresAndAtomics            = true;
+
                createTestsForAllStages(
                        test->m_name, defaultColors, defaultColors, fragments, noSpecConstants,
-                       noPushConstants, resources, noInterfaces, extensions, features, vulkanFeatures, group.get());
+                       noPushConstants, resources, noInterfaces, extensions, vulkanFeatures, group.get());
        }
        return group.release();
 }
@@ -9532,6 +10060,7 @@ tcu::TestCaseGroup* createOpConstantFloat16Tests(tcu::TestContext& testCtx)
 
        extensions.push_back("VK_KHR_16bit_storage");
        extensions.push_back("VK_KHR_shader_float16_int8");
+       features.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
 
        for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
        {
@@ -9600,7 +10129,9 @@ tcu::TestCaseGroup* createFloat16LogicalSet (tcu::TestContext& testCtx, const bo
        de::MovePtr<tcu::TestCaseGroup>         testGroup                       (new tcu::TestCaseGroup(testCtx, groupName.c_str(), "Float 16 logical tests"));
 
        de::Random                                                      rnd                                     (deStringHash(testGroup->getName()));
-       const StringTemplate                            capabilities            ("OpCapability ${cap}\n");
+       const string                                            spvCapabilities         = string("OpCapability StorageUniformBufferBlock16\n") + (nanSupported ? "OpCapability SignedZeroInfNanPreserve\n" : "");
+       const string                                            spvExtensions           = string("OpExtension \"SPV_KHR_16bit_storage\"\n") + (nanSupported ? "OpExtension \"SPV_KHR_float_controls\"\n" : "");
+       const string                                            spvExecutionMode        = nanSupported ? "OpExecutionMode %BP_main SignedZeroInfNanPreserve 16\n" : "";
        const deUint32                                          numDataPoints           = 16;
        const vector<deFloat16>                         float16Data                     = getFloat16s(rnd, numDataPoints);
        const vector<deFloat16>                         float16Data1            = squarize(float16Data, 0);
@@ -9724,14 +10255,14 @@ tcu::TestCaseGroup* createFloat16LogicalSet (tcu::TestContext& testCtx, const bo
                        map<string, string>     fragments;
                        vector<string>          extensions;
 
-                       specs["cap"]                            = "StorageUniformBufferBlock16";
                        specs["num_data_points"]        = de::toString(iterations);
                        specs["op_code"]                        = testOp.opCode;
                        specs["op_arg1"]                        = (testOp.argCount == 1) ? "" : "%val_src1";
                        specs["op_arg1_calc"]           = (testOp.argCount == 1) ? "" : arg1Calc.specialize(specs);
 
-                       fragments["extension"]          = "OpExtension \"SPV_KHR_16bit_storage\"";
-                       fragments["capability"]         = capabilities.specialize(specs);
+                       fragments["extension"]          = spvExtensions;
+                       fragments["capability"]         = spvCapabilities;
+                       fragments["execution_mode"]     = spvExecutionMode;
                        fragments["decoration"]         = decoration.specialize(specs);
                        fragments["pre_main"]           = preMain.specialize(specs);
                        fragments["testfun"]            = testFun.specialize(specs);
@@ -9850,14 +10381,14 @@ tcu::TestCaseGroup* createFloat16LogicalSet (tcu::TestContext& testCtx, const bo
                        VulkanFeatures          features;
                        map<string, string>     fragments;
 
-                       specs["cap"]                            = "StorageUniformBufferBlock16";
                        specs["num_data_points"]        = de::toString(iterations);
                        specs["op_code"]                        = testOp.opCode;
                        specs["op_arg1"]                        = (testOp.argCount == 1) ? "" : "%val_src1";
                        specs["op_arg1_calc"]           = (testOp.argCount == 1) ? "" : arg1Calc.specialize(specs);
 
-                       fragments["extension"]          = "OpExtension \"SPV_KHR_16bit_storage\"";
-                       fragments["capability"]         = capabilities.specialize(specs);
+                       fragments["extension"]          = spvExtensions;
+                       fragments["capability"]         = spvCapabilities;
+                       fragments["execution_mode"]     = spvExecutionMode;
                        fragments["decoration"]         = decoration.specialize(specs);
                        fragments["pre_main"]           = preMain.specialize(specs);
                        fragments["testfun"]            = testFun.specialize(specs);
@@ -10427,7 +10958,6 @@ tcu::TestCaseGroup* createDerivativeTests (tcu::TestContext& testCtx)
                SpecConstants           noSpecConstants;
                PushConstants           noPushConstants;
                GraphicsInterfaces      noInterfaces;
-               vector<string>          noFeatures;
 
                specs["op_code"]                        = testOp.opCode;
                specs["num_data_points"]        = de::toString(testOp.inputData.size() / N);
@@ -10437,7 +10967,7 @@ tcu::TestCaseGroup* createDerivativeTests (tcu::TestContext& testCtx)
                specs["type_decls"]                     = testType.typeDecls;
 
                fragments["extension"]          = "OpExtension \"SPV_KHR_16bit_storage\"";
-               fragments["capability"]         = "OpCapability DerivativeControl\nOpCapability StorageUniformBufferBlock16\n";
+               fragments["capability"]         = "OpCapability DerivativeControl\nOpCapability StorageUniformBufferBlock16\nOpCapability Float16\n";
                fragments["decoration"]         = decoration.specialize(specs);
                fragments["pre_main"]           = preMain.specialize(specs);
                fragments["testfun"]            = testFun.specialize(specs);
@@ -10453,7 +10983,7 @@ tcu::TestCaseGroup* createDerivativeTests (tcu::TestContext& testCtx)
                features.ext16BitStorage        = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
 
                createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, testName.c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
-                                                       noPushConstants, specResource, noInterfaces, extensions, noFeatures, features, testGroup.get(), QP_TEST_RESULT_FAIL, string(), true);
+                                                       noPushConstants, specResource, noInterfaces, extensions, features, testGroup.get(), QP_TEST_RESULT_FAIL, string(), true);
        }
 
        return testGroup.release();
@@ -13429,6 +13959,12 @@ struct fp16SmoothStep : public fp16PerComponent
 
 struct fp16Fma : public fp16PerComponent
 {
+       fp16Fma()
+       {
+               flavorNames.push_back("DoubleCalc");
+               flavorNames.push_back("EmulatingFP16");
+       }
+
        virtual double getULPs(vector<const deFloat16*>& in)
        {
                DE_UNREF(in);
@@ -13448,10 +13984,30 @@ struct fp16Fma : public fp16PerComponent
                const fp16type  a               (*in[0]);
                const fp16type  b               (*in[1]);
                const fp16type  c               (*in[2]);
-               const double    ad              (a.asDouble());
-               const double    bd              (b.asDouble());
-               const double    cd              (c.asDouble());
-               const double    result  (deMadd(ad, bd, cd));
+               double                  result  (0.0);
+
+               if (getFlavor() == 0)
+               {
+                       const double    ad      (a.asDouble());
+                       const double    bd      (b.asDouble());
+                       const double    cd      (c.asDouble());
+
+                       result  = deMadd(ad, bd, cd);
+               }
+               else if (getFlavor() == 1)
+               {
+                       const double    ad      (a.asDouble());
+                       const double    bd      (b.asDouble());
+                       const double    cd      (c.asDouble());
+                       const fp16type  ab      (ad * bd);
+                       const fp16type  r       (ab.asDouble() + cd);
+
+                       result  = r.asDouble();
+               }
+               else
+               {
+                       TCU_THROW(InternalError, "Unknown flavor");
+               }
 
                out[0] = fp16type(result).bits();
                min[0] = getMin(result, getULPs(in));
@@ -17304,26 +17860,26 @@ tcu::TestCaseGroup* createOpNopTests (tcu::TestContext& testCtx)
 
 tcu::TestCaseGroup* createOpNameTests (tcu::TestContext& testCtx)
 {
-       de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "opname","Test OpName"));
+       de::MovePtr<tcu::TestCaseGroup> testGroup       (new tcu::TestCaseGroup(testCtx, "opname","Test OpName"));
        RGBA                                                    defaultColors[4];
        map<string, string>                             opNameFragments;
 
        getDefaultColors(defaultColors);
 
-       opNameFragments["debug"]                =
-               "OpName %BP_main \"not_main\"";
-
-       opNameFragments["testfun"]              =
-               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
-               "%param1 = OpFunctionParameter %v4f32\n"
+       opNameFragments["testfun"] =
+               "%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"
-               "%b = OpFAdd %f32 %a %a\n"
-               "%c = OpFSub %f32 %b %a\n"
-               "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+               "%a          = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+               "%b          = OpFAdd %f32 %a %a\n"
+               "%c          = OpFSub %f32 %b %a\n"
+               "%ret        = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
                "OpReturnValue %ret\n"
                "OpFunctionEnd\n";
 
+       opNameFragments["debug"] =
+               "OpName %BP_main \"not_main\"";
+
        createTestsForAllStages("opname", defaultColors, defaultColors, opNameFragments, testGroup.get());
 
        return testGroup.release();
@@ -17334,6 +17890,7 @@ tcu::TestCaseGroup* createFloat16Tests (tcu::TestContext& testCtx)
        de::MovePtr<tcu::TestCaseGroup>         testGroup                       (new tcu::TestCaseGroup(testCtx, "float16", "Float 16 tests"));
 
        testGroup->addChild(createOpConstantFloat16Tests(testCtx));
+       testGroup->addChild(createFloat16LogicalSet<GraphicsResources>(testCtx, TEST_WITH_NAN));
        testGroup->addChild(createFloat16LogicalSet<GraphicsResources>(testCtx, TEST_WITHOUT_NAN));
        testGroup->addChild(createFloat16FuncSet<GraphicsResources>(testCtx));
        testGroup->addChild(createDerivativeTests<256, 1>(testCtx));
@@ -17359,6 +17916,7 @@ tcu::TestCaseGroup* createFloat16Group (tcu::TestContext& testCtx)
        de::MovePtr<tcu::TestCaseGroup>         testGroup                       (new tcu::TestCaseGroup(testCtx, "float16", "Float 16 tests"));
 
        testGroup->addChild(createFloat16OpConstantCompositeGroup(testCtx));
+       testGroup->addChild(createFloat16LogicalSet<ComputeShaderSpec>(testCtx, TEST_WITH_NAN));
        testGroup->addChild(createFloat16LogicalSet<ComputeShaderSpec>(testCtx, TEST_WITHOUT_NAN));
        testGroup->addChild(createFloat16FuncSet<ComputeShaderSpec>(testCtx));
        testGroup->addChild(createFloat16VectorExtractSet<ComputeShaderSpec>(testCtx));
@@ -17376,6 +17934,648 @@ tcu::TestCaseGroup* createFloat16Group (tcu::TestContext& testCtx)
        return testGroup.release();
 }
 
+tcu::TestCaseGroup* createBoolMixedBitSizeGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "mixed_bitsize", "Tests boolean operands produced from instructions of different bit-sizes"));
+
+       de::Random                                              rnd                             (deStringHash(group->getName()));
+       const int               numElements             = 100;
+       vector<float>   inputData               (numElements, 0);
+       vector<float>   outputData              (numElements, 0);
+       fillRandomScalars(rnd, 0.0f, 100.0f, &inputData[0], 100);
+
+       const StringTemplate                    shaderTemplate  (
+               "${CAPS}\n"
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"main\" %id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n"
+               "OpSource GLSL 430\n"
+               "OpName %main           \"main\"\n"
+               "OpName %id             \"gl_GlobalInvocationID\"\n"
+
+               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+               + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
+
+               "%id        = OpVariable %uvec3ptr Input\n"
+               "${CONST}\n"
+               "%main      = OpFunction %void None %voidf\n"
+               "%label     = OpLabel\n"
+               "%idval     = OpLoad %uvec3 %id\n"
+               "%x         = OpCompositeExtract %u32 %idval 0\n"
+               "%inloc     = OpAccessChain %f32ptr %indata %c0i32 %x\n"
+
+               "${TEST}\n"
+
+               "%outloc    = OpAccessChain %f32ptr %outdata %c0i32 %x\n"
+               "             OpStore %outloc %res\n"
+               "             OpReturn\n"
+               "             OpFunctionEnd\n"
+       );
+
+       // Each test case produces 4 boolean values, and we want each of these values
+       // to come froma different combination of the available bit-sizes, so compute
+       // all possible combinations here.
+       vector<deUint32>        widths;
+       widths.push_back(32);
+       widths.push_back(16);
+       widths.push_back(8);
+
+       vector<IVec4>   cases;
+       for (size_t width0 = 0; width0 < widths.size(); width0++)
+       {
+               for (size_t width1 = 0; width1 < widths.size(); width1++)
+               {
+                       for (size_t width2 = 0; width2 < widths.size(); width2++)
+                       {
+                               for (size_t width3 = 0; width3 < widths.size(); width3++)
+                               {
+                                       cases.push_back(IVec4(widths[width0], widths[width1], widths[width2], widths[width3]));
+                               }
+                       }
+               }
+       }
+
+       for (size_t caseNdx = 0; caseNdx < cases.size(); caseNdx++)
+       {
+               /// Skip cases where all bitsizes are the same, we are only interested in testing booleans produced from instructions with different native bit-sizes
+               if (cases[caseNdx][0] == cases[caseNdx][1] && cases[caseNdx][0] == cases[caseNdx][2] && cases[caseNdx][0] == cases[caseNdx][3])
+                       continue;
+
+               map<string, string>     specializations;
+               ComputeShaderSpec       spec;
+
+               // Inject appropriate capabilities and reference constants depending
+               // on the bit-sizes required by this test case
+               bool hasFloat32 = cases[caseNdx][0] == 32 || cases[caseNdx][1] == 32 || cases[caseNdx][2] == 32 || cases[caseNdx][3] == 32;
+               bool hasFloat16 = cases[caseNdx][0] == 16 || cases[caseNdx][1] == 16 || cases[caseNdx][2] == 16 || cases[caseNdx][3] == 16;
+               bool hasInt8    = cases[caseNdx][0] == 8 || cases[caseNdx][1] == 8 || cases[caseNdx][2] == 8 || cases[caseNdx][3] == 8;
+
+               string capsStr  = "OpCapability Shader\n";
+               string constStr =
+                       "%c0i32     = OpConstant %i32 0\n"
+                       "%c1f32     = OpConstant %f32 1.0\n"
+                       "%c0f32     = OpConstant %f32 0.0\n";
+
+               if (hasFloat32)
+               {
+                       constStr        +=
+                               "%c10f32    = OpConstant %f32 10.0\n"
+                               "%c25f32    = OpConstant %f32 25.0\n"
+                               "%c50f32    = OpConstant %f32 50.0\n"
+                               "%c90f32    = OpConstant %f32 90.0\n";
+               }
+
+               if (hasFloat16)
+               {
+                       capsStr         += "OpCapability Float16\n";
+                       constStr        +=
+                               "%f16       = OpTypeFloat 16\n"
+                               "%c10f16    = OpConstant %f16 10.0\n"
+                               "%c25f16    = OpConstant %f16 25.0\n"
+                               "%c50f16    = OpConstant %f16 50.0\n"
+                               "%c90f16    = OpConstant %f16 90.0\n";
+               }
+
+               if (hasInt8)
+               {
+                       capsStr         += "OpCapability Int8\n";
+                       constStr        +=
+                               "%i8        = OpTypeInt 8 1\n"
+                               "%c10i8     = OpConstant %i8 10\n"
+                               "%c25i8     = OpConstant %i8 25\n"
+                               "%c50i8     = OpConstant %i8 50\n"
+                               "%c90i8     = OpConstant %i8 90\n";
+               }
+
+               // Each invocation reads a different float32 value as input. Depending on
+               // the bit-sizes required by the particular test case, we also produce
+               // float16 and/or and int8 values by converting from the 32-bit float.
+               string testStr  = "";
+               testStr                 += "%inval32   = OpLoad %f32 %inloc\n";
+               if (hasFloat16)
+                       testStr         += "%inval16   = OpFConvert %f16 %inval32\n";
+               if (hasInt8)
+                       testStr         += "%inval8    = OpConvertFToS %i8 %inval32\n";
+
+               // Because conversions from Float to Int round towards 0 we want our "greater" comparisons to be >=,
+               // that way a float32/float16 comparison such as 50.6f >= 50.0f will preserve its result
+               // when converted to int8, since FtoS(50.6f) results in 50. For "less" comparisons, it is the
+               // other way around, so in this case we want < instead of <=.
+               if (cases[caseNdx][0] == 32)
+                       testStr         += "%cmp1      = OpFOrdGreaterThanEqual %bool %inval32 %c25f32\n";
+               else if (cases[caseNdx][0] == 16)
+                       testStr         += "%cmp1      = OpFOrdGreaterThanEqual %bool %inval16 %c25f16\n";
+               else
+                       testStr         += "%cmp1      = OpSGreaterThanEqual %bool %inval8 %c25i8\n";
+
+               if (cases[caseNdx][1] == 32)
+                       testStr         += "%cmp2      = OpFOrdLessThan %bool %inval32 %c50f32\n";
+               else if (cases[caseNdx][1] == 16)
+                       testStr         += "%cmp2      = OpFOrdLessThan %bool %inval16 %c50f16\n";
+               else
+                       testStr         += "%cmp2      = OpSLessThan %bool %inval8 %c50i8\n";
+
+               if (cases[caseNdx][2] == 32)
+                       testStr         += "%cmp3      = OpFOrdLessThan %bool %inval32 %c10f32\n";
+               else if (cases[caseNdx][2] == 16)
+                       testStr         += "%cmp3      = OpFOrdLessThan %bool %inval16 %c10f16\n";
+               else
+                       testStr         += "%cmp3      = OpSLessThan %bool %inval8 %c10i8\n";
+
+               if (cases[caseNdx][3] == 32)
+                       testStr         += "%cmp4      = OpFOrdGreaterThanEqual %bool %inval32 %c90f32\n";
+               else if (cases[caseNdx][3] == 16)
+                       testStr         += "%cmp4      = OpFOrdGreaterThanEqual %bool %inval16 %c90f16\n";
+               else
+                       testStr         += "%cmp4      = OpSGreaterThanEqual %bool %inval8 %c90i8\n";
+
+               testStr                 += "%and1      = OpLogicalAnd %bool %cmp1 %cmp2\n";
+               testStr                 += "%or1       = OpLogicalOr %bool %cmp3 %cmp4\n";
+               testStr                 += "%or2       = OpLogicalOr %bool %and1 %or1\n";
+               testStr                 += "%not1      = OpLogicalNot %bool %or2\n";
+               testStr                 += "%res       = OpSelect %f32 %not1 %c1f32 %c0f32\n";
+
+               specializations["CAPS"]         = capsStr;
+               specializations["CONST"]        = constStr;
+               specializations["TEST"]         = testStr;
+
+               // Compute expected result by evaluating the boolean expression computed in the shader for each input value
+               for (size_t ndx = 0; ndx < numElements; ++ndx)
+                       outputData[ndx] = !((inputData[ndx] >= 25.0f && inputData[ndx] < 50.0f) || (inputData[ndx] < 10.0f || inputData[ndx] >= 90.0f));
+
+               spec.assembly = shaderTemplate.specialize(specializations);
+               spec.inputs.push_back(BufferSp(new Float32Buffer(inputData)));
+               spec.outputs.push_back(BufferSp(new Float32Buffer(outputData)));
+               spec.numWorkGroups = IVec3(numElements, 1, 1);
+               if (hasFloat16)
+                       spec.requestedVulkanFeatures.extFloat16Int8 |= EXTFLOAT16INT8FEATURES_FLOAT16;
+               if (hasInt8)
+                       spec.requestedVulkanFeatures.extFloat16Int8 |= EXTFLOAT16INT8FEATURES_INT8;
+               spec.extensions.push_back("VK_KHR_shader_float16_int8");
+
+               string testName = "b" + de::toString(cases[caseNdx][0]) + "b" + de::toString(cases[caseNdx][1]) + "b" + de::toString(cases[caseNdx][2]) + "b" + de::toString(cases[caseNdx][3]);
+               group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "", spec));
+       }
+
+       return group.release();
+}
+
+tcu::TestCaseGroup* createBoolGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup>         testGroup                       (new tcu::TestCaseGroup(testCtx, "bool", "Boolean tests"));
+
+       testGroup->addChild(createBoolMixedBitSizeGroup(testCtx));
+
+       return testGroup.release();
+}
+
+tcu::TestCaseGroup* createOpNameAbuseTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "opname_abuse", "OpName abuse tests"));
+       vector<CaseParameter>                   abuseCases;
+       RGBA                                                    defaultColors[4];
+       map<string, string>                             opNameFragments;
+
+       getOpNameAbuseCases(abuseCases);
+       getDefaultColors(defaultColors);
+
+       opNameFragments["testfun"] =
+               "%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"
+               "%b          = OpFAdd %f32 %a %a\n"
+               "%c          = OpFSub %f32 %b %a\n"
+               "%ret        = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+               "OpReturnValue %ret\n"
+               "OpFunctionEnd\n";
+
+       for (unsigned int i = 0; i < abuseCases.size(); i++)
+       {
+               string casename;
+               casename = string("main") + abuseCases[i].name;
+
+               opNameFragments["debug"] =
+                       "OpName %BP_main \"" + abuseCases[i].param + "\"";
+
+               createTestsForAllStages(casename, defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       for (unsigned int i = 0; i < abuseCases.size(); i++)
+       {
+               string casename;
+               casename = string("b") + abuseCases[i].name;
+
+               opNameFragments["debug"] =
+                       "OpName %b \"" + abuseCases[i].param + "\"";
+
+               createTestsForAllStages(casename, defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       {
+               opNameFragments["debug"] =
+                       "OpName %test_code \"name1\"\n"
+                       "OpName %param1    \"name2\"\n"
+                       "OpName %a         \"name3\"\n"
+                       "OpName %b         \"name4\"\n"
+                       "OpName %c         \"name5\"\n"
+                       "OpName %ret       \"name6\"\n";
+
+               createTestsForAllStages("everything_named", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       {
+               opNameFragments["debug"] =
+                       "OpName %test_code \"the_same\"\n"
+                       "OpName %param1    \"the_same\"\n"
+                       "OpName %a         \"the_same\"\n"
+                       "OpName %b         \"the_same\"\n"
+                       "OpName %c         \"the_same\"\n"
+                       "OpName %ret       \"the_same\"\n";
+
+               createTestsForAllStages("everything_named_the_same", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       {
+               opNameFragments["debug"] =
+                       "OpName %BP_main \"to_be\"\n"
+                       "OpName %BP_main \"or_not\"\n"
+                       "OpName %BP_main \"to_be\"\n";
+
+               createTestsForAllStages("main_has_multiple_names", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       {
+               opNameFragments["debug"] =
+                       "OpName %b \"to_be\"\n"
+                       "OpName %b \"or_not\"\n"
+                       "OpName %b \"to_be\"\n";
+
+               createTestsForAllStages("b_has_multiple_names", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+       }
+
+       return abuseGroup.release();
+}
+
+
+tcu::TestCaseGroup* createOpMemberNameAbuseTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "opmembername_abuse", "OpName abuse tests"));
+       vector<CaseParameter>                   abuseCases;
+       RGBA                                                    defaultColors[4];
+       map<string, string>                             opMemberNameFragments;
+
+       getOpNameAbuseCases(abuseCases);
+       getDefaultColors(defaultColors);
+
+       opMemberNameFragments["pre_main"] =
+               "%f3str = OpTypeStruct %f32 %f32 %f32\n";
+
+       opMemberNameFragments["testfun"] =
+               "%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"
+               "%b          = OpFAdd %f32 %a %a\n"
+               "%c          = OpFSub %f32 %b %a\n"
+               "%cstr       = OpCompositeConstruct %f3str %c %c %c\n"
+               "%d          = OpCompositeExtract %f32 %cstr 0\n"
+               "%ret        = OpVectorInsertDynamic %v4f32 %param1 %d %c_i32_0\n"
+               "OpReturnValue %ret\n"
+               "OpFunctionEnd\n";
+
+       for (unsigned int i = 0; i < abuseCases.size(); i++)
+       {
+               string casename;
+               casename = string("f3str_x") + abuseCases[i].name;
+
+               opMemberNameFragments["debug"] =
+                       "OpMemberName %f3str 0 \"" + abuseCases[i].param + "\"";
+
+               createTestsForAllStages(casename, defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+       }
+
+       {
+               opMemberNameFragments["debug"] =
+                       "OpMemberName %f3str 0 \"name1\"\n"
+                       "OpMemberName %f3str 1 \"name2\"\n"
+                       "OpMemberName %f3str 2 \"name3\"\n";
+
+               createTestsForAllStages("everything_named", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+       }
+
+       {
+               opMemberNameFragments["debug"] =
+                       "OpMemberName %f3str 0 \"the_same\"\n"
+                       "OpMemberName %f3str 1 \"the_same\"\n"
+                       "OpMemberName %f3str 2 \"the_same\"\n";
+
+               createTestsForAllStages("everything_named_the_same", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+       }
+
+       {
+               opMemberNameFragments["debug"] =
+                       "OpMemberName %f3str 0 \"to_be\"\n"
+                       "OpMemberName %f3str 1 \"or_not\"\n"
+                       "OpMemberName %f3str 0 \"to_be\"\n"
+                       "OpMemberName %f3str 2 \"makes_no\"\n"
+                       "OpMemberName %f3str 0 \"difference\"\n"
+                       "OpMemberName %f3str 0 \"to_me\"\n";
+
+
+               createTestsForAllStages("f3str_x_has_multiple_names", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+       }
+
+       return abuseGroup.release();
+}
+
+vector<deUint32> getSparseIdsAbuseData (const deUint32 numDataPoints, const deUint32 seed)
+{
+       vector<deUint32>        result;
+       de::Random                      rnd             (seed);
+
+       result.reserve(numDataPoints);
+
+       for (deUint32 dataPointNdx = 0; dataPointNdx < numDataPoints; ++dataPointNdx)
+               result.push_back(rnd.getUint32());
+
+       return result;
+}
+
+vector<deUint32> getSparseIdsAbuseResults (const vector<deUint32>& inData1, const vector<deUint32>& inData2)
+{
+       vector<deUint32>        result;
+
+       result.reserve(inData1.size());
+
+       for (size_t dataPointNdx = 0; dataPointNdx < inData1.size(); ++dataPointNdx)
+               result.push_back(inData1[dataPointNdx] + inData2[dataPointNdx]);
+
+       return result;
+}
+
+template<class SpecResource>
+void createSparseIdsAbuseTest (tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup>& testGroup)
+{
+       const deUint32                  numDataPoints   = 16;
+       const std::string               testName                ("sparse_ids");
+       const deUint32                  seed                    (deStringHash(testName.c_str()));
+       const vector<deUint32>  inData1                 (getSparseIdsAbuseData(numDataPoints, seed + 1));
+       const vector<deUint32>  inData2                 (getSparseIdsAbuseData(numDataPoints, seed + 2));
+       const vector<deUint32>  outData                 (getSparseIdsAbuseResults(inData1, inData2));
+       const StringTemplate    preMain
+       (
+               "%c_i32_ndp = OpConstant %i32 ${num_data_points}\n"
+               "   %up_u32 = OpTypePointer Uniform %u32\n"
+               "   %ra_u32 = OpTypeArray %u32 %c_i32_ndp\n"
+               "   %SSBO32 = OpTypeStruct %ra_u32\n"
+               "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
+               "%ssbo_src0 = OpVariable %up_SSBO32 Uniform\n"
+               "%ssbo_src1 = OpVariable %up_SSBO32 Uniform\n"
+               " %ssbo_dst = OpVariable %up_SSBO32 Uniform\n"
+       );
+       const StringTemplate    decoration
+       (
+               "OpDecorate %ra_u32 ArrayStride 4\n"
+               "OpMemberDecorate %SSBO32 0 Offset 0\n"
+               "OpDecorate %SSBO32 BufferBlock\n"
+               "OpDecorate %ssbo_src0 DescriptorSet 0\n"
+               "OpDecorate %ssbo_src0 Binding 0\n"
+               "OpDecorate %ssbo_src1 DescriptorSet 0\n"
+               "OpDecorate %ssbo_src1 Binding 1\n"
+               "OpDecorate %ssbo_dst DescriptorSet 0\n"
+               "OpDecorate %ssbo_dst Binding 2\n"
+       );
+       const StringTemplate    testFun
+       (
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+               "    %param = OpFunctionParameter %v4f32\n"
+
+               "    %entry = OpLabel\n"
+               "        %i = OpVariable %fp_i32 Function\n"
+               "             OpStore %i %c_i32_0\n"
+               "             OpBranch %loop\n"
+
+               "     %loop = OpLabel\n"
+               "    %i_cmp = OpLoad %i32 %i\n"
+               "       %lt = OpSLessThan %bool %i_cmp %c_i32_ndp\n"
+               "             OpLoopMerge %merge %next None\n"
+               "             OpBranchConditional %lt %write %merge\n"
+
+               "    %write = OpLabel\n"
+               "      %ndx = OpLoad %i32 %i\n"
+
+               "      %127 = OpAccessChain %up_u32 %ssbo_src0 %c_i32_0 %ndx\n"
+               "      %128 = OpLoad %u32 %127\n"
+
+               // The test relies on SPIR-V compiler option SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS set in assembleSpirV()
+               "  %4194000 = OpAccessChain %up_u32 %ssbo_src1 %c_i32_0 %ndx\n"
+               "  %4194001 = OpLoad %u32 %4194000\n"
+
+               "  %2097151 = OpIAdd %u32 %128 %4194001\n"
+               "  %2097152 = OpAccessChain %up_u32 %ssbo_dst %c_i32_0 %ndx\n"
+               "             OpStore %2097152 %2097151\n"
+               "             OpBranch %next\n"
+
+               "     %next = OpLabel\n"
+               "    %i_cur = OpLoad %i32 %i\n"
+               "    %i_new = OpIAdd %i32 %i_cur %c_i32_1\n"
+               "             OpStore %i %i_new\n"
+               "             OpBranch %loop\n"
+
+               "    %merge = OpLabel\n"
+               "             OpReturnValue %param\n"
+
+               "             OpFunctionEnd\n"
+       );
+       SpecResource                    specResource;
+       map<string, string>             specs;
+       VulkanFeatures                  features;
+       map<string, string>             fragments;
+       vector<string>                  extensions;
+
+       specs["num_data_points"]        = de::toString(numDataPoints);
+
+       fragments["decoration"]         = decoration.specialize(specs);
+       fragments["pre_main"]           = preMain.specialize(specs);
+       fragments["testfun"]            = testFun.specialize(specs);
+
+       specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData1)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+       specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData2)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+       specResource.outputs.push_back(Resource(BufferSp(new Uint32Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+
+       features.coreFeatures.vertexPipelineStoresAndAtomics    = true;
+       features.coreFeatures.fragmentStoresAndAtomics                  = true;
+
+       finalizeTestsCreation(specResource, fragments, testCtx, *testGroup.get(), testName, features, extensions, IVec3(1, 1, 1));
+}
+
+vector<deUint32> getLotsIdsAbuseData (const deUint32 numDataPoints, const deUint32 seed)
+{
+       vector<deUint32>        result;
+       de::Random                      rnd             (seed);
+
+       result.reserve(numDataPoints);
+
+       // Fixed value
+       result.push_back(1u);
+
+       // Random values
+       for (deUint32 dataPointNdx = 1; dataPointNdx < numDataPoints; ++dataPointNdx)
+               result.push_back(rnd.getUint8());
+
+       return result;
+}
+
+vector<deUint32> getLotsIdsAbuseResults (const vector<deUint32>& inData1, const vector<deUint32>& inData2, const deUint32 count)
+{
+       vector<deUint32>        result;
+
+       result.reserve(inData1.size());
+
+       for (size_t dataPointNdx = 0; dataPointNdx < inData1.size(); ++dataPointNdx)
+               result.push_back(inData1[dataPointNdx] + count * inData2[dataPointNdx]);
+
+       return result;
+}
+
+template<class SpecResource>
+void createLotsIdsAbuseTest (tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup>& testGroup)
+{
+       const deUint32                  numDataPoints   = 16;
+       const deUint32                  firstNdx                = 100u;
+       const deUint32                  sequenceCount   = 10000u;
+       const std::string               testName                ("lots_ids");
+       const deUint32                  seed                    (deStringHash(testName.c_str()));
+       const vector<deUint32>  inData1                 (getLotsIdsAbuseData(numDataPoints, seed + 1));
+       const vector<deUint32>  inData2                 (getLotsIdsAbuseData(numDataPoints, seed + 2));
+       const vector<deUint32>  outData                 (getLotsIdsAbuseResults(inData1, inData2, sequenceCount));
+       const StringTemplate preMain
+       (
+               "%c_i32_ndp = OpConstant %i32 ${num_data_points}\n"
+               "   %up_u32 = OpTypePointer Uniform %u32\n"
+               "   %ra_u32 = OpTypeArray %u32 %c_i32_ndp\n"
+               "   %SSBO32 = OpTypeStruct %ra_u32\n"
+               "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
+               "%ssbo_src0 = OpVariable %up_SSBO32 Uniform\n"
+               "%ssbo_src1 = OpVariable %up_SSBO32 Uniform\n"
+               " %ssbo_dst = OpVariable %up_SSBO32 Uniform\n"
+       );
+       const StringTemplate decoration
+       (
+               "OpDecorate %ra_u32 ArrayStride 4\n"
+               "OpMemberDecorate %SSBO32 0 Offset 0\n"
+               "OpDecorate %SSBO32 BufferBlock\n"
+               "OpDecorate %ssbo_src0 DescriptorSet 0\n"
+               "OpDecorate %ssbo_src0 Binding 0\n"
+               "OpDecorate %ssbo_src1 DescriptorSet 0\n"
+               "OpDecorate %ssbo_src1 Binding 1\n"
+               "OpDecorate %ssbo_dst DescriptorSet 0\n"
+               "OpDecorate %ssbo_dst Binding 2\n"
+       );
+       const StringTemplate testFun
+       (
+               "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+               "    %param = OpFunctionParameter %v4f32\n"
+
+               "    %entry = OpLabel\n"
+               "        %i = OpVariable %fp_i32 Function\n"
+               "             OpStore %i %c_i32_0\n"
+               "             OpBranch %loop\n"
+
+               "     %loop = OpLabel\n"
+               "    %i_cmp = OpLoad %i32 %i\n"
+               "       %lt = OpSLessThan %bool %i_cmp %c_i32_ndp\n"
+               "             OpLoopMerge %merge %next None\n"
+               "             OpBranchConditional %lt %write %merge\n"
+
+               "    %write = OpLabel\n"
+               "      %ndx = OpLoad %i32 %i\n"
+
+               "       %90 = OpAccessChain %up_u32 %ssbo_src1 %c_i32_0 %ndx\n"
+               "       %91 = OpLoad %u32 %90\n"
+
+               "       %98 = OpAccessChain %up_u32 %ssbo_src0 %c_i32_0 %ndx\n"
+               "       %${zeroth_id} = OpLoad %u32 %98\n"
+
+               "${seq}\n"
+
+               // The test relies on SPIR-V compiler option SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS set in assembleSpirV()
+               "      %dst = OpAccessChain %up_u32 %ssbo_dst %c_i32_0 %ndx\n"
+               "             OpStore %dst %${last_id}\n"
+               "             OpBranch %next\n"
+
+               "     %next = OpLabel\n"
+               "    %i_cur = OpLoad %i32 %i\n"
+               "    %i_new = OpIAdd %i32 %i_cur %c_i32_1\n"
+               "             OpStore %i %i_new\n"
+               "             OpBranch %loop\n"
+
+               "    %merge = OpLabel\n"
+               "             OpReturnValue %param\n"
+
+               "             OpFunctionEnd\n"
+       );
+       deUint32                                lastId                  = firstNdx;
+       SpecResource                    specResource;
+       map<string, string>             specs;
+       VulkanFeatures                  features;
+       map<string, string>             fragments;
+       vector<string>                  extensions;
+       std::string                             sequence;
+
+       for (deUint32 sequenceNdx = 0; sequenceNdx < sequenceCount; ++sequenceNdx)
+       {
+               const deUint32          sequenceId              = sequenceNdx + firstNdx;
+               const std::string       sequenceIdStr   = de::toString(sequenceId);
+
+               sequence += "%" + sequenceIdStr + " = OpIAdd %u32 %91 %" + de::toString(sequenceId - 1) + "\n";
+               lastId = sequenceId;
+
+               if (sequenceNdx == 0)
+                       sequence.reserve((10 + sequence.length()) * sequenceCount);
+       }
+
+       specs["num_data_points"]        = de::toString(numDataPoints);
+       specs["zeroth_id"]                      = de::toString(firstNdx - 1);
+       specs["last_id"]                        = de::toString(lastId);
+       specs["seq"]                            = sequence;
+
+       fragments["decoration"]         = decoration.specialize(specs);
+       fragments["pre_main"]           = preMain.specialize(specs);
+       fragments["testfun"]            = testFun.specialize(specs);
+
+       specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData1)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+       specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData2)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+       specResource.outputs.push_back(Resource(BufferSp(new Uint32Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+
+       features.coreFeatures.vertexPipelineStoresAndAtomics    = true;
+       features.coreFeatures.fragmentStoresAndAtomics                  = true;
+
+       finalizeTestsCreation(specResource, fragments, testCtx, *testGroup.get(), testName, features, extensions, IVec3(1, 1, 1));
+}
+
+tcu::TestCaseGroup* createSpirvIdsAbuseTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> testGroup       (new tcu::TestCaseGroup(testCtx, "spirv_ids_abuse", "SPIR-V abuse tests"));
+
+       createSparseIdsAbuseTest<GraphicsResources>(testCtx, testGroup);
+       createLotsIdsAbuseTest<GraphicsResources>(testCtx, testGroup);
+
+       return testGroup.release();
+}
+
+tcu::TestCaseGroup* createSpirvIdsAbuseGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> testGroup       (new tcu::TestCaseGroup(testCtx, "spirv_ids_abuse", "SPIR-V abuse tests"));
+
+       createSparseIdsAbuseTest<ComputeShaderSpec>(testCtx, testGroup);
+       createLotsIdsAbuseTest<ComputeShaderSpec>(testCtx, testGroup);
+
+       return testGroup.release();
+}
+
 tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
 {
        const bool testComputePipeline = true;
@@ -17387,7 +18587,8 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createSpivVersionCheckTests(testCtx, testComputePipeline));
        computeTests->addChild(createLocalSizeGroup(testCtx));
        computeTests->addChild(createOpNopGroup(testCtx));
-       computeTests->addChild(createOpFUnordGroup(testCtx));
+       computeTests->addChild(createOpFUnordGroup(testCtx, TEST_WITHOUT_NAN));
+       computeTests->addChild(createOpFUnordGroup(testCtx, TEST_WITH_NAN));
        computeTests->addChild(createOpAtomicGroup(testCtx, false));
        computeTests->addChild(createOpAtomicGroup(testCtx, true));                                     // Using new StorageBuffer decoration
        computeTests->addChild(createOpAtomicGroup(testCtx, false, 1024, true));        // Return value validation
@@ -17445,14 +18646,23 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(create16BitStorageComputeGroup(testCtx));
        computeTests->addChild(createFloatControlsComputeGroup(testCtx));
        computeTests->addChild(createUboMatrixPaddingComputeGroup(testCtx));
+       computeTests->addChild(createCompositeInsertComputeGroup(testCtx));
        computeTests->addChild(createVariableInitComputeGroup(testCtx));
        computeTests->addChild(createConditionalBranchComputeGroup(testCtx));
        computeTests->addChild(createIndexingComputeGroup(testCtx));
        computeTests->addChild(createVariablePointersComputeGroup(testCtx));
+       computeTests->addChild(createPhysicalPointersComputeGroup(testCtx));
        computeTests->addChild(createImageSamplerComputeGroup(testCtx));
        computeTests->addChild(createOpNameGroup(testCtx));
+       computeTests->addChild(createOpMemberNameGroup(testCtx));
        computeTests->addChild(createPointerParameterComputeGroup(testCtx));
        computeTests->addChild(createFloat16Group(testCtx));
+       computeTests->addChild(createBoolGroup(testCtx));
+       computeTests->addChild(createWorkgroupMemoryComputeGroup(testCtx));
+       computeTests->addChild(createSpirvIdsAbuseGroup(testCtx));
+       computeTests->addChild(createSignedIntCompareGroup(testCtx));
+       computeTests->addChild(createUnusedVariableComputeTests(testCtx));
+       computeTests->addChild(createPtrAccessChainGroup(testCtx));
 
        graphicsTests->addChild(createCrossStageInterfaceTests(testCtx));
        graphicsTests->addChild(createSpivVersionCheckTests(testCtx, !testComputePipeline));
@@ -17468,6 +18678,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        graphicsTests->addChild(createOpUndefTests(testCtx));
        graphicsTests->addChild(createSelectionBlockOrderTests(testCtx));
        graphicsTests->addChild(createModuleTests(testCtx));
+       graphicsTests->addChild(createUnusedVariableTests(testCtx));
        graphicsTests->addChild(createSwitchBlockOrderTests(testCtx));
        graphicsTests->addChild(createOpPhiTests(testCtx));
        graphicsTests->addChild(createNoContractionTests(testCtx));
@@ -17490,11 +18701,14 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
                graphicsTests->addChild(graphicsAndroidTests.release());
        }
        graphicsTests->addChild(createOpNameTests(testCtx));
+       graphicsTests->addChild(createOpNameAbuseTests(testCtx));
+       graphicsTests->addChild(createOpMemberNameAbuseTests(testCtx));
 
        graphicsTests->addChild(create8BitStorageGraphicsGroup(testCtx));
        graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
        graphicsTests->addChild(createFloatControlsGraphicsGroup(testCtx));
        graphicsTests->addChild(createUboMatrixPaddingGraphicsGroup(testCtx));
+       graphicsTests->addChild(createCompositeInsertGraphicsGroup(testCtx));
        graphicsTests->addChild(createVariableInitGraphicsGroup(testCtx));
        graphicsTests->addChild(createConditionalBranchGraphicsGroup(testCtx));
        graphicsTests->addChild(createIndexingGraphicsGroup(testCtx));
@@ -17508,8 +18722,9 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpConvertUToF", "convertutof"));
        graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpConvertFToU", "convertftou"));
        graphicsTests->addChild(createPointerParameterGraphicsGroup(testCtx));
-
+       graphicsTests->addChild(createVaryingNameGraphicsGroup(testCtx));
        graphicsTests->addChild(createFloat16Tests(testCtx));
+       graphicsTests->addChild(createSpirvIdsAbuseTests(testCtx));
 
        instructionTests->addChild(computeTests.release());
        instructionTests->addChild(graphicsTests.release());