Merge vk-gl-cts/vulkan-cts-1.0.0 into vk-gl-cts/vulkan-cts-1.0.1
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmInstructionTests.cpp
index fda2674..9e9a134 100644 (file)
@@ -47,7 +47,6 @@
 #include "deUniquePtr.hpp"
 #include "tcuStringTemplate.hpp"
 
-#include <cmath>
 #include "vktSpvAsmComputeShaderCase.hpp"
 #include "vktSpvAsmComputeShaderTestUtil.hpp"
 #include "vktTestCaseUtil.hpp"
@@ -149,10 +148,10 @@ static const char* const s_CommonTypes =
        "%uvec3     = OpTypeVector %u32 3\n"
        "%fvec3     = OpTypeVector %f32 3\n"
        "%uvec3ptr  = OpTypePointer Input %uvec3\n"
+       "%i32ptr    = OpTypePointer Uniform %i32\n"
        "%f32ptr    = OpTypePointer Uniform %f32\n"
-       "%boolptr   = OpTypePointer Uniform %bool\n"
-       "%f32arr    = OpTypeRuntimeArray %f32\n"
-       "%boolarr   = OpTypeRuntimeArray %bool\n";
+       "%i32arr    = OpTypeRuntimeArray %i32\n"
+       "%f32arr    = OpTypeRuntimeArray %f32\n";
 
 // Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]").
 static const char* const s_InputOutputBuffer =
@@ -231,17 +230,17 @@ bool compareFUnord (const std::vector<BufferSp>& inputs, const vector<Allocation
                return false;
 
        const BufferSp& expectedOutput                  = expectedOutputs[0];
-       const VkBool32* expectedOutputAsBool    = static_cast<const VkBool32*>(expectedOutputs[0]->data());
-       const VkBool32* outputAsBool                    = static_cast<const VkBool32*>(outputAllocs[0]->getHostPtr());
+       const deInt32*  expectedOutputAsInt             = static_cast<const deInt32*>(expectedOutputs[0]->data());
+       const deInt32*  outputAsInt                             = static_cast<const deInt32*>(outputAllocs[0]->getHostPtr());
        const float*    input1AsFloat                   = static_cast<const float*>(inputs[0]->data());
        const float*    input2AsFloat                   = static_cast<const float*>(inputs[1]->data());
        bool returnValue                                                = true;
 
-       for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(VkBool32); ++idx)
+       for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(deInt32); ++idx)
        {
-               if (outputAsBool[idx] != expectedOutputAsBool[idx])
+               if (outputAsInt[idx] != expectedOutputAsInt[idx])
                {
-                       log << TestLog::Message << "ERROR: Sub-case failed. inputs: " << input1AsFloat[idx] << "," << input2AsFloat[idx] << " output: " << outputAsBool[idx]<< " expected output: " << expectedOutputAsBool[idx] << TestLog::EndMessage;
+                       log << TestLog::Message << "ERROR: Sub-case failed. inputs: " << input1AsFloat[idx] << "," << input2AsFloat[idx] << " output: " << outputAsInt[idx]<< " expected output: " << expectedOutputAsInt[idx] << TestLog::EndMessage;
                        returnValue = false;
                }
        }
@@ -256,7 +255,7 @@ struct OpFUnordCase
        const char*             opCode;
        compareFuncType compareFunc;
 
-                                       OpFUnordCase                    (const char* _name, const char* _opCode, compareFuncType _compareFunc)
+                                       OpFUnordCase                    (const char* _name, const char* _opCode, compareFuncType _compareFunc)
                                                : name                          (_name)
                                                , opCode                        (_opCode)
                                                , compareFunc           (_compareFunc) {}
@@ -294,7 +293,7 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                "OpDecorate %outdata DescriptorSet 0\n"
                "OpDecorate %outdata Binding 2\n"
                "OpDecorate %f32arr ArrayStride 4\n"
-               "OpDecorate %boolarr ArrayStride 4\n"
+               "OpDecorate %i32arr ArrayStride 4\n"
                "OpMemberDecorate %buf 0 Offset 0\n"
                "OpMemberDecorate %buf2 0 Offset 0\n"
 
@@ -305,12 +304,13 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                "%indata1    = OpVariable %bufptr Uniform\n"
                "%indata2    = OpVariable %bufptr Uniform\n"
 
-               "%buf2       = OpTypeStruct %boolarr\n"
+               "%buf2       = OpTypeStruct %i32arr\n"
                "%buf2ptr    = OpTypePointer Uniform %buf2\n"
                "%outdata    = OpVariable %buf2ptr Uniform\n"
 
                "%id        = OpVariable %uvec3ptr Input\n"
                "%zero      = OpConstant %i32 0\n"
+               "%consti1   = OpConstant %i32 1\n"
                "%constf1   = OpConstant %f32 1.0\n"
 
                "%main      = OpFunction %void None %voidf\n"
@@ -322,10 +322,11 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                "%inval1    = OpLoad %f32 %inloc1\n"
                "%inloc2    = OpAccessChain %f32ptr %indata2 %zero %x\n"
                "%inval2    = OpLoad %f32 %inloc2\n"
-               "%outloc    = OpAccessChain %boolptr %outdata %zero %x\n"
+               "%outloc    = OpAccessChain %i32ptr %outdata %zero %x\n"
 
                "%result    = ${OPCODE} %bool %inval1 %inval2\n"
-               "             OpStore %outloc %result\n"
+               "%int_res   = OpSelect %i32 %result %consti1 %zero\n"
+               "             OpStore %outloc %int_res\n"
 
                "             OpReturn\n"
                "             OpFunctionEnd\n");
@@ -344,7 +345,7 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                const float                                     NaN                             = std::numeric_limits<float>::quiet_NaN();
                vector<float>                           inputFloats1    (numElements, 0);
                vector<float>                           inputFloats2    (numElements, 0);
-               vector<VkBool32>                        expectedBools   (numElements, VK_FALSE);
+               vector<deInt32>                         expectedInts    (numElements, 0);
 
                specializations["OPCODE"]       = cases[caseNdx].opCode;
                spec.assembly                           = shaderTemplate.specialize(specializations);
@@ -361,12 +362,12 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
                                case 4:         inputFloats2[ndx] = inputFloats1[ndx];  inputFloats1[ndx] = NaN; break;
                                case 5:         inputFloats2[ndx] = NaN;                                inputFloats1[ndx] = NaN; break;
                        }
-                       expectedBools[ndx] = tcu::Float32(inputFloats1[ndx]).isNaN() || tcu::Float32(inputFloats2[ndx]).isNaN() || cases[caseNdx].compareFunc(inputFloats1[ndx], inputFloats2[ndx]);
+                       expectedInts[ndx] = tcu::Float32(inputFloats1[ndx]).isNaN() || tcu::Float32(inputFloats2[ndx]).isNaN() || cases[caseNdx].compareFunc(inputFloats1[ndx], inputFloats2[ndx]);
                }
 
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
                spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
-               spec.outputs.push_back(BufferSp(new BoolBuffer(expectedBools)));
+               spec.outputs.push_back(BufferSp(new Int32Buffer(expectedInts)));
                spec.numWorkGroups = IVec3(numElements, 1, 1);
                spec.verifyIO = &compareFUnord;
                group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
@@ -375,6 +376,129 @@ tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
        return group.release();
 }
 
+struct OpAtomicCase
+{
+       const char*             name;
+       const char*             assembly;
+       void                    (*calculateExpected)(deInt32&, deInt32);
+       deInt32                 numOutputElements;
+
+                                       OpAtomicCase                    (const char* _name, const char* _assembly, void (*_calculateExpected)(deInt32&, deInt32), deInt32 _numOutputElements)
+                                               : name                          (_name)
+                                               , assembly                      (_assembly)
+                                               , calculateExpected     (_calculateExpected)
+                                               , numOutputElements (_numOutputElements) {}
+};
+
+tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opatomic", "Test the OpAtomic* opcodes"));
+       de::Random                                              rnd                             (deStringHash(group->getName()));
+       const int                                               numElements             = 1000000;
+       vector<OpAtomicCase>                    cases;
+
+       const StringTemplate                    shaderTemplate  (
+
+               string(s_ShaderPreamble) +
+
+               "OpSource GLSL 430\n"
+               "OpName %main           \"main\"\n"
+               "OpName %id             \"gl_GlobalInvocationID\"\n"
+
+               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+               "OpDecorate %buf BufferBlock\n"
+               "OpDecorate %indata DescriptorSet 0\n"
+               "OpDecorate %indata Binding 0\n"
+               "OpDecorate %i32arr ArrayStride 4\n"
+               "OpMemberDecorate %buf 0 Offset 0\n"
+
+               "OpDecorate %sumbuf BufferBlock\n"
+               "OpDecorate %sum DescriptorSet 0\n"
+               "OpDecorate %sum Binding 1\n"
+               "OpMemberDecorate %sumbuf 0 Coherent\n"
+               "OpMemberDecorate %sumbuf 0 Offset 0\n"
+
+               + string(s_CommonTypes) +
+
+               "%buf       = OpTypeStruct %i32arr\n"
+               "%bufptr    = OpTypePointer Uniform %buf\n"
+               "%indata    = OpVariable %bufptr Uniform\n"
+
+               "%sumbuf    = OpTypeStruct %i32arr\n"
+               "%sumbufptr = OpTypePointer Uniform %sumbuf\n"
+               "%sum       = OpVariable %sumbufptr Uniform\n"
+
+               "%id        = OpVariable %uvec3ptr Input\n"
+               "%minusone  = OpConstant %i32 -1\n"
+               "%zero      = OpConstant %i32 0\n"
+               "%one       = OpConstant %u32 1\n"
+               "%two       = OpConstant %i32 2\n"
+
+               "%main      = OpFunction %void None %voidf\n"
+               "%label     = OpLabel\n"
+               "%idval     = OpLoad %uvec3 %id\n"
+               "%x         = OpCompositeExtract %u32 %idval 0\n"
+
+               "%inloc     = OpAccessChain %i32ptr %indata %zero %x\n"
+               "%inval     = OpLoad %i32 %inloc\n"
+
+               "%outloc    = OpAccessChain %i32ptr %sum %zero ${INDEX}\n"
+               "${INSTRUCTION}"
+
+               "             OpReturn\n"
+               "             OpFunctionEnd\n");
+
+       #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, NUM_OUTPUT_ELEMENTS) \
+       do { \
+               DE_STATIC_ASSERT(NUM_OUTPUT_ELEMENTS == 1 || NUM_OUTPUT_ELEMENTS == numElements); \
+               struct calculateExpected_##NAME { static void calculateExpected(deInt32& expected, deInt32 input) CALCULATE_EXPECTED }; \
+               cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, calculateExpected_##NAME::calculateExpected, NUM_OUTPUT_ELEMENTS)); \
+       } while (deGetFalse())
+       #define ADD_OPATOMIC_CASE_1(NAME, ASSEMBLY, CALCULATE_EXPECTED) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, 1)
+       #define ADD_OPATOMIC_CASE_N(NAME, ASSEMBLY, CALCULATE_EXPECTED) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, numElements)
+
+       ADD_OPATOMIC_CASE_1(iadd,       "%unused    = OpAtomicIAdd %i32 %outloc %one %zero %inval\n", { expected += input; } );
+       ADD_OPATOMIC_CASE_1(isub,       "%unused    = OpAtomicISub %i32 %outloc %one %zero %inval\n", { expected -= input; } );
+       ADD_OPATOMIC_CASE_1(iinc,       "%unused    = OpAtomicIIncrement %i32 %outloc %one %zero\n",  { ++expected; (void)input;} );
+       ADD_OPATOMIC_CASE_1(idec,       "%unused    = OpAtomicIDecrement %i32 %outloc %one %zero\n",  { --expected; (void)input;} );
+       ADD_OPATOMIC_CASE_N(load,       "%inval2    = OpAtomicLoad %i32 %inloc %zero %zero\n"
+                                                               "             OpStore %outloc %inval2\n",  { expected = input;} );
+       ADD_OPATOMIC_CASE_N(store,      "             OpAtomicStore %outloc %zero %zero %inval\n",  { expected = input;} );
+       ADD_OPATOMIC_CASE_N(compex, "%even      = OpSMod %i32 %inval %two\n"
+                                                               "             OpStore %outloc %even\n"
+                                                               "%unused    = OpAtomicCompareExchange %i32 %outloc %one %zero %zero %minusone %zero\n",  { expected = (input % 2) == 0 ? -1 : 1;} );
+
+       #undef ADD_OPATOMIC_CASE
+       #undef ADD_OPATOMIC_CASE_1
+       #undef ADD_OPATOMIC_CASE_N
+
+       for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
+       {
+               map<string, string>                     specializations;
+               ComputeShaderSpec                       spec;
+               vector<deInt32>                         inputInts               (numElements, 0);
+               vector<deInt32>                         expected                (cases[caseNdx].numOutputElements, -1);
+
+               specializations["INDEX"]                = (cases[caseNdx].numOutputElements == 1) ? "%zero" : "%x";
+               specializations["INSTRUCTION"]  = cases[caseNdx].assembly;
+               spec.assembly                                   = shaderTemplate.specialize(specializations);
+
+               fillRandomScalars(rnd, 1, 100, &inputInts[0], numElements);
+               for (size_t ndx = 0; ndx < numElements; ++ndx)
+               {
+                       cases[caseNdx].calculateExpected((cases[caseNdx].numOutputElements == 1) ? expected[0] : expected[ndx], inputInts[ndx]);
+               }
+
+               spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
+               spec.outputs.push_back(BufferSp(new Int32Buffer(expected)));
+               spec.numWorkGroups = IVec3(numElements, 1, 1);
+               group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
+       }
+
+       return group.release();
+}
+
 tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
 {
        de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction"));
@@ -1379,8 +1503,6 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
 
                + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
 
-               "%i32ptr    = OpTypePointer Uniform %i32\n"
-               "%i32arr    = OpTypeRuntimeArray %i32\n"
                "%buf     = OpTypeStruct %i32arr\n"
                "%bufptr  = OpTypePointer Uniform %buf\n"
                "%indata    = OpVariable %bufptr Uniform\n"
@@ -1490,8 +1612,6 @@ tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
                + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
 
                "%ivec3     = OpTypeVector %i32 3\n"
-               "%i32ptr    = OpTypePointer Uniform %i32\n"
-               "%i32arr    = OpTypeRuntimeArray %i32\n"
                "%buf     = OpTypeStruct %i32arr\n"
                "%bufptr  = OpTypePointer Uniform %buf\n"
                "%indata    = OpVariable %bufptr Uniform\n"
@@ -1814,20 +1934,6 @@ tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
                "            OpSelectionMerge %if_merge None\n"
                "            OpBranchConditional %cmp %if_true %if_false\n"
 
-               // Merge block for switch-statement: placed at the beginning.
-               "%switch_merge = OpLabel\n"
-               "                OpBranch %if_merge\n"
-
-               // Case 1 for switch-statement.
-               "%case1    = OpLabel\n"
-               "%x_1      = OpLoad %u32 %xvar\n"
-               "%inloc_1  = OpAccessChain %f32ptr %indata %zero %x_1\n"
-               "%inval_1  = OpLoad %f32 %inloc_1\n"
-               "%addf42   = OpFAdd %f32 %inval_1 %constf42\n"
-               "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
-               "            OpStore %outloc_1 %addf42\n"
-               "            OpBranch %switch_merge\n"
-
                // False branch for if-statement: placed in the middle of switch cases and before true branch.
                "%if_false = OpLabel\n"
                "%x_f      = OpLoad %u32 %xvar\n"
@@ -1849,6 +1955,22 @@ tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
                "            OpSelectionMerge %switch_merge None\n"
                "            OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n"
 
+               // Merge block for switch-statement: placed before the case
+                // bodies.  But it must follow OpSwitch which dominates it.
+               "%switch_merge = OpLabel\n"
+               "                OpBranch %if_merge\n"
+
+               // Case 1 for switch-statement: placed before case 0.
+                // It must follow the OpSwitch that dominates it.
+               "%case1    = OpLabel\n"
+               "%x_1      = OpLoad %u32 %xvar\n"
+               "%inloc_1  = OpAccessChain %f32ptr %indata %zero %x_1\n"
+               "%inval_1  = OpLoad %f32 %inloc_1\n"
+               "%addf42   = OpFAdd %f32 %inval_1 %constf42\n"
+               "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
+               "            OpStore %outloc_1 %addf42\n"
+               "            OpBranch %switch_merge\n"
+
                // Case 2 for switch-statement.
                "%case2    = OpLabel\n"
                "%x_2      = OpLoad %u32 %xvar\n"
@@ -1937,7 +2059,7 @@ tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx)
                "%one        = OpConstant %u32 1\n"
                "%c_f32_1    = OpConstant %f32 1\n"
 
-               "%i32ptr              = OpTypePointer Input %i32\n"
+               "%i32inputptr         = OpTypePointer Input %i32\n"
                "%vec4                = OpTypeVector %f32 4\n"
                "%vec4ptr             = OpTypePointer Output %vec4\n"
                "%f32arr1             = OpTypeArray %f32 %one\n"
@@ -1946,8 +2068,8 @@ tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx)
                "%vert_builtins       = OpVariable %vert_builtin_st_ptr Output\n"
 
                "%id         = OpVariable %uvec3ptr Input\n"
-               "%vertexIndex = OpVariable %i32ptr Input\n"
-               "%instanceIndex = OpVariable %i32ptr Input\n"
+               "%vertexIndex = OpVariable %i32inputptr Input\n"
+               "%instanceIndex = OpVariable %i32inputptr Input\n"
                "%c_vec4_1   = OpConstantComposite %vec4 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
 
                // gl_Position = vec4(1.);
@@ -2408,7 +2530,7 @@ bool compareNan (const std::vector<BufferSp>&, const vector<AllocationSp>& outpu
 
        for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx)
        {
-               if (!isnan(output_as_float[idx]))
+               if (!deFloatIsNaN(output_as_float[idx]))
                {
                        return false;
                }
@@ -2976,7 +3098,7 @@ tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
                "%loop_entry  = OpLabel\n"
                "%i_val       = OpLoad %u32 %i\n"
                "%cmp_lt      = OpULessThan %bool %i_val %four\n"
-               "               OpLoopMerge %loop_merge %loop_entry ${CONTROL}\n"
+               "               OpLoopMerge %loop_merge %loop_body ${CONTROL}\n"
                "               OpBranchConditional %cmp_lt %loop_body %loop_merge\n"
                "%loop_body   = OpLabel\n"
                "%outval      = OpLoad %f32 %outloc\n"
@@ -4148,6 +4270,8 @@ void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
                "OpExecutionMode %tessc_main OutputVertices 3\n"
 
                "OpExecutionMode %tesse_main Triangles\n"
+               "OpExecutionMode %tesse_main SpacingEqual\n"
+               "OpExecutionMode %tesse_main VertexOrderCcw\n"
 
                "OpExecutionMode %frag_main OriginUpperLeft\n"
 
@@ -4359,9 +4483,9 @@ void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
                "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
                "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
                "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
-               "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_pos_0\n"
-               "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_pos_1\n"
-               "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_pos_2\n"
+               "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n"
+               "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
+               "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
                "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
                "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
                "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
@@ -4372,9 +4496,9 @@ void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
                "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
                "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
                "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
-               "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_clr_0\n"
-               "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_clr_1\n"
-               "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_clr_2\n"
+               "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n"
+               "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
+               "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
                "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
                "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
                "OpStore %tesse_out_color %tesse_computed_clr\n"
@@ -4694,7 +4818,11 @@ void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
                "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
                "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
                "OpExecutionMode %tesse1_main Triangles\n"
+               "OpExecutionMode %tesse1_main SpacingEqual\n"
+               "OpExecutionMode %tesse1_main VertexOrderCcw\n"
                "OpExecutionMode %tesse2_main Triangles\n"
+               "OpExecutionMode %tesse2_main SpacingEqual\n"
+               "OpExecutionMode %tesse2_main VertexOrderCcw\n"
                "OpName %tesse1_main \"tesse1\"\n"
                "OpName %tesse2_main \"tesse2\"\n"
                "OpName %per_vertex_out \"gl_PerVertex\"\n"
@@ -4742,9 +4870,9 @@ void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
                "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
                "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
                "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
-               "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_pos_0\n"
-               "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_pos_1\n"
-               "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_pos_2\n"
+               "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
+               "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
+               "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
                "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
                "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
                "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
@@ -4755,9 +4883,9 @@ void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
                "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
                "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
                "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
-               "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_clr_0\n"
-               "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_clr_1\n"
-               "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_clr_2\n"
+               "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
+               "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
+               "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
                "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
                "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
                "OpStore %out_color %tesse1_computed_clr\n"
@@ -4778,9 +4906,9 @@ void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
                "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
                "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
                "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
-               "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_pos_0\n"
-               "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_pos_1\n"
-               "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_pos_2\n"
+               "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n"
+               "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n"
+               "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n"
                "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
                "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
                "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
@@ -4791,9 +4919,9 @@ void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
                "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
                "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
                "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
-               "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_clr_0\n"
-               "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_clr_1\n"
-               "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_clr_2\n"
+               "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n"
+               "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n"
+               "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n"
                "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
                "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
                "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
@@ -6004,7 +6132,7 @@ tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx)
                "%loop      = OpLabel\n"
                "%ival      = OpLoad %i32 %iptr\n"
                "%lt_4      = OpSLessThan %bool %ival %c_i32_4\n"
-               "             OpLoopMerge %exit %loop None\n"
+               "             OpLoopMerge %exit %if_entry None\n"
                "             OpBranchConditional %lt_4 %if_entry %exit\n"
 
                // Merge block for loop.
@@ -6096,7 +6224,7 @@ tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx)
                "%loop      = OpLabel\n"
                "%ival      = OpLoad %i32 %iptr\n"
                "%lt_4      = OpSLessThan %bool %ival %c_i32_4\n"
-               "             OpLoopMerge %exit %loop None\n"
+               "             OpLoopMerge %exit %switch_exit None\n"
                "             OpBranchConditional %lt_4 %switch_entry %exit\n"
 
                // Merge block for loop.
@@ -6526,7 +6654,7 @@ tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
                "%loop      = OpLabel\n"
                "%ival      = OpLoad %i32 %iptr\n"
                "%lt_4      = OpSLessThan %bool %ival %c_i32_4\n"
-               "             OpLoopMerge %exit %loop None\n"
+               "             OpLoopMerge %exit %phi None\n"
                "             OpBranchConditional %lt_4 %entry %exit\n"
 
                "%entry     = OpLabel\n"
@@ -7816,6 +7944,24 @@ const string getBitWidthStr (IntegerType type)
        }
 }
 
+const string getByteWidthStr (IntegerType type)
+{
+       switch (type)
+       {
+               case INTEGER_TYPE_SIGNED_16:
+               case INTEGER_TYPE_UNSIGNED_16:  return "2";
+
+               case INTEGER_TYPE_SIGNED_32:
+               case INTEGER_TYPE_UNSIGNED_32:  return "4";
+
+               case INTEGER_TYPE_SIGNED_64:
+               case INTEGER_TYPE_UNSIGNED_64:  return "8";
+
+               default:                                                DE_ASSERT(false);
+                                                                               return "";
+       }
+}
+
 bool isSigned (IntegerType type)
 {
        return (type <= INTEGER_TYPE_SIGNED_64);
@@ -7838,71 +7984,6 @@ const string getAsmTypeDeclaration (IntegerType type)
        return "OpTypeInt " + getBitWidthStr(type) + sign;
 }
 
-const string getConvertCaseShaderStr (const string& instruction, map<string, string> types)
-{
-       const StringTemplate shader (
-               "OpCapability Shader\n"
-               "${int_capabilities}"
-               "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"
-               // Decorators
-               "OpDecorate %id BuiltIn GlobalInvocationId\n"
-               "OpDecorate %indata DescriptorSet 0\n"
-               "OpDecorate %indata Binding 0\n"
-               "OpDecorate %outdata DescriptorSet 0\n"
-               "OpDecorate %outdata Binding 1\n"
-               "OpDecorate %in_buf BufferBlock\n"
-               "OpDecorate %out_buf BufferBlock\n"
-               "OpMemberDecorate %in_buf 0 Offset 0\n"
-               "OpMemberDecorate %out_buf 0 Offset 0\n"
-               // Base types
-               "%void       = OpTypeVoid\n"
-               "%voidf      = OpTypeFunction %void\n"
-               "%u32        = OpTypeInt 32 0\n"
-               "%i32        = OpTypeInt 32 1\n"
-               "%uvec3      = OpTypeVector %u32 3\n"
-               "%uvec3ptr   = OpTypePointer Input %uvec3\n"
-               // Custom types
-               "%in_type    = ${inputType}\n"
-               "%out_type   = ${outputType}\n"
-               // Derived types
-               "%in_ptr     = OpTypePointer Uniform %in_type\n"
-               "%out_ptr    = OpTypePointer Uniform %out_type\n"
-               "%in_arr     = OpTypeRuntimeArray %in_type\n"
-               "%out_arr    = OpTypeRuntimeArray %out_type\n"
-               "%in_buf     = OpTypeStruct %in_arr\n"
-               "%out_buf    = OpTypeStruct %out_arr\n"
-               "%in_bufptr  = OpTypePointer Uniform %in_buf\n"
-               "%out_bufptr = OpTypePointer Uniform %out_buf\n"
-               "%indata     = OpVariable %in_bufptr Uniform\n"
-               "%outdata    = OpVariable %out_bufptr Uniform\n"
-               "%inputptr   = OpTypePointer Input %in_type\n"
-               "%id         = OpVariable %uvec3ptr Input\n"
-               // Constants
-               "%zero       = OpConstant %i32 0\n"
-               // Main function
-               "%main       = OpFunction %void None %voidf\n"
-               "%label      = OpLabel\n"
-               "%idval      = OpLoad %uvec3 %id\n"
-               "%x          = OpCompositeExtract %u32 %idval 0\n"
-               "%inloc      = OpAccessChain %in_ptr %indata %zero %x\n"
-               "%outloc     = OpAccessChain %out_ptr %outdata %zero %x\n"
-               "%inval      = OpLoad %in_type %inloc\n"
-               "%conv       = ${instruction} %out_type %inval\n"
-               "              OpStore %outloc %conv\n"
-               "              OpReturn\n"
-               "              OpFunctionEnd\n"
-       );
-
-       types["instruction"] = instruction;
-
-       return shader.specialize(types);
-}
-
 template<typename T>
 BufferSp getSpecializedBuffer (deInt64 number)
 {
@@ -7980,8 +8061,8 @@ struct ConvertCase
                }
                else if (m_features == CONVERT_TEST_USES_INT16_INT64)
                {
-                       m_asmTypes["int_capabilities"] = "OpCapability Int16\n \
-                                                                                         OpCapability Int64\n";
+                       m_asmTypes["int_capabilities"] = string("OpCapability Int16\n") +
+                                                                                                       "OpCapability Int64\n";
                }
                else
                {
@@ -7998,6 +8079,78 @@ struct ConvertCase
        BufferSp                                m_outputBuffer;
 };
 
+const string getConvertCaseShaderStr (const string& instruction, const ConvertCase& convertCase)
+{
+       map<string, string> params = convertCase.m_asmTypes;
+
+       params["instruction"] = instruction;
+
+       params["inDecorator"] = getByteWidthStr(convertCase.m_fromType);
+       params["outDecorator"] = getByteWidthStr(convertCase.m_toType);
+
+       const StringTemplate shader (
+               "OpCapability Shader\n"
+               "${int_capabilities}"
+               "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"
+               // Decorators
+               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+               "OpDecorate %indata DescriptorSet 0\n"
+               "OpDecorate %indata Binding 0\n"
+               "OpDecorate %outdata DescriptorSet 0\n"
+               "OpDecorate %outdata Binding 1\n"
+               "OpDecorate %in_arr ArrayStride ${inDecorator}\n"
+               "OpDecorate %out_arr ArrayStride ${outDecorator}\n"
+               "OpDecorate %in_buf BufferBlock\n"
+               "OpDecorate %out_buf BufferBlock\n"
+               "OpMemberDecorate %in_buf 0 Offset 0\n"
+               "OpMemberDecorate %out_buf 0 Offset 0\n"
+               // Base types
+               "%void       = OpTypeVoid\n"
+               "%voidf      = OpTypeFunction %void\n"
+               "%u32        = OpTypeInt 32 0\n"
+               "%i32        = OpTypeInt 32 1\n"
+               "%uvec3      = OpTypeVector %u32 3\n"
+               "%uvec3ptr   = OpTypePointer Input %uvec3\n"
+               // Custom types
+               "%in_type    = ${inputType}\n"
+               "%out_type   = ${outputType}\n"
+               // Derived types
+               "%in_ptr     = OpTypePointer Uniform %in_type\n"
+               "%out_ptr    = OpTypePointer Uniform %out_type\n"
+               "%in_arr     = OpTypeRuntimeArray %in_type\n"
+               "%out_arr    = OpTypeRuntimeArray %out_type\n"
+               "%in_buf     = OpTypeStruct %in_arr\n"
+               "%out_buf    = OpTypeStruct %out_arr\n"
+               "%in_bufptr  = OpTypePointer Uniform %in_buf\n"
+               "%out_bufptr = OpTypePointer Uniform %out_buf\n"
+               "%indata     = OpVariable %in_bufptr Uniform\n"
+               "%outdata    = OpVariable %out_bufptr Uniform\n"
+               "%inputptr   = OpTypePointer Input %in_type\n"
+               "%id         = OpVariable %uvec3ptr Input\n"
+               // Constants
+               "%zero       = OpConstant %i32 0\n"
+               // Main function
+               "%main       = OpFunction %void None %voidf\n"
+               "%label      = OpLabel\n"
+               "%idval      = OpLoad %uvec3 %id\n"
+               "%x          = OpCompositeExtract %u32 %idval 0\n"
+               "%inloc      = OpAccessChain %in_ptr %indata %zero %x\n"
+               "%outloc     = OpAccessChain %out_ptr %outdata %zero %x\n"
+               "%inval      = OpLoad %in_type %inloc\n"
+               "%conv       = ${instruction} %out_type %inval\n"
+               "              OpStore %outloc %conv\n"
+               "              OpReturn\n"
+               "              OpFunctionEnd\n"
+       );
+
+       return shader.specialize(params);
+}
+
 void createSConvertCases (vector<ConvertCase>& testCases)
 {
        // Convert int to int
@@ -8025,9 +8178,9 @@ tcu::TestCaseGroup* createSConvertTests (tcu::TestContext& testCtx)
        {
                ComputeShaderSpec       spec;
 
-               spec.assembly = getConvertCaseShaderStr(instruction, test->m_asmTypes);
+               spec.assembly = getConvertCaseShaderStr(instruction, *test);
                spec.inputs.push_back(test->m_inputBuffer);
-               spec.outputs.push_back(test->m_inputBuffer);
+               spec.outputs.push_back(test->m_outputBuffer);
                spec.numWorkGroups = IVec3(1, 1, 1);
 
                group->addChild(new ConvertTestCase(testCtx, test->m_name.c_str(), "Convert integers with OpSConvert.", spec, test->m_features));
@@ -8063,9 +8216,9 @@ tcu::TestCaseGroup* createUConvertTests (tcu::TestContext& testCtx)
        {
                ComputeShaderSpec       spec;
 
-               spec.assembly = getConvertCaseShaderStr(instruction, test->m_asmTypes);
+               spec.assembly = getConvertCaseShaderStr(instruction, *test);
                spec.inputs.push_back(test->m_inputBuffer);
-               spec.outputs.push_back(test->m_inputBuffer);
+               spec.outputs.push_back(test->m_outputBuffer);
                spec.numWorkGroups = IVec3(1, 1, 1);
 
                group->addChild(new ConvertTestCase(testCtx, test->m_name.c_str(), "Convert integers with OpUConvert.", spec, test->m_features));
@@ -8418,9 +8571,9 @@ struct AssemblyStructInfo
 const string specializeInBoundsShaderTemplate (const NumberType type, const AssemblyStructInfo& structInfo, const map<string, string>& params)
 {
        // Create the full index string
-       string                          fullIndex       = numberToString(structInfo.index) + " " + params.at("indexes");
+       string                          fullIndex       = numberToString(structInfo.index) + " " + params.at("indexes");
        // Convert it to list of indexes
-       vector<string>          indexes         = de::splitString(fullIndex, ' ');
+       vector<string>          indexes         = de::splitString(fullIndex, ' ');
 
        map<string, string>     parameters      (params);
        parameters["typeDeclaration"]   = getAssemblyTypeDeclaration(type);
@@ -8500,6 +8653,7 @@ const string specializeInBoundsShaderTemplate (const NumberType type, const Asse
                "%zero      = OpConstant %u32 0\n"
                "%main      = OpFunction %void None %voidf\n"
                "%label     = OpLabel\n"
+               "%struct_v  = OpVariable %struct_p Function\n"
                "%idval     = OpLoad %uvec3 %id\n"
                "%x         = OpCompositeExtract %u32 %idval 0\n"
                // Create the input/output type
@@ -8514,7 +8668,6 @@ const string specializeInBoundsShaderTemplate (const NumberType type, const Asse
                // Insert the value
                "%comp_obj  = OpCompositeInsert %struct_t %inval %struct ${insertIndexes}\n"
                // Store the object
-               "%struct_v  = OpVariable %struct_p Function\n"
                "             OpStore %struct_v %comp_obj\n"
                // Get deepest possible composite pointer
                "%inner_ptr = OpInBoundsAccessChain %composite_p %struct_v${accessChainIndexes}\n"
@@ -8595,6 +8748,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
 
        computeTests->addChild(createOpNopGroup(testCtx));
        computeTests->addChild(createOpFUnordGroup(testCtx));
+       computeTests->addChild(createOpAtomicGroup(testCtx));
        computeTests->addChild(createOpLineGroup(testCtx));
        computeTests->addChild(createOpNoLineGroup(testCtx));
        computeTests->addChild(createOpConstantNullGroup(testCtx));