"%i32ptr = OpTypePointer Uniform %i32\n"
"%f32ptr = OpTypePointer Uniform %f32\n"
"%i32arr = OpTypeRuntimeArray %i32\n"
- "%f32arr = OpTypeRuntimeArray %f32\n"
- "%boolarr = OpTypeRuntimeArray %bool\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 =
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) {}
"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"
"%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"
const char* name;
const char* assembly;
void (*calculateExpected)(deInt32&, deInt32);
+ deInt32 numOutputElements;
- OpAtomicCase (const char* _name, const char* _assembly, void (*_calculateExpected)(deInt32&, deInt32) )
+ OpAtomicCase (const char* _name, const char* _assembly, void (*_calculateExpected)(deInt32&, deInt32), deInt32 _numOutputElements)
: name (_name)
, assembly (_assembly)
- , calculateExpected (_calculateExpected) {}
+ , calculateExpected (_calculateExpected)
+ , numOutputElements (_numOutputElements) {}
};
tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx)
"%bufptr = OpTypePointer Uniform %buf\n"
"%indata = OpVariable %bufptr Uniform\n"
- "%sumbuf = OpTypeStruct %i32\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"
"%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
"%inval = OpLoad %i32 %inloc\n"
- "%outloc = OpAccessChain %i32ptr %sum %zero\n"
+ "%outloc = OpAccessChain %i32ptr %sum %zero ${INDEX}\n"
"${INSTRUCTION}"
+
" OpReturn\n"
" OpFunctionEnd\n");
- #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED) \
+ #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, NUM_OUTPUT_ELEMENTS) \
do { \
- struct calculateExpected_##NAME { static void calculateExpected(deInt32& expected, deInt32 input) CALCULATE_EXPECTED }; \
- cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, calculateExpected_##NAME::calculateExpected)); \
+ DE_STATIC_ASSERT((NUM_OUTPUT_ELEMENTS) == 1 || (NUM_OUTPUT_ELEMENTS) == numElements); \
+ struct calculateExpected_##NAME { static void calculateExpected(deInt32& expected, deInt32 input) CALCULATE_EXPECTED }; /* NOLINT(CALCULATE_EXPECTED) */ \
+ cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, calculateExpected_##NAME::calculateExpected, NUM_OUTPUT_ELEMENTS)); \
} while (deGetFalse())
-
- ADD_OPATOMIC_CASE(iadd, "%unused = OpAtomicIAdd %i32 %outloc %one %zero %inval\n", { expected += input; } );
- ADD_OPATOMIC_CASE(isub, "%unused = OpAtomicISub %i32 %outloc %one %zero %inval\n", { expected -= input; } );
- ADD_OPATOMIC_CASE(iinc, "%unused = OpAtomicIIncrement %i32 %outloc %one %zero\n", { ++expected; (void)input;} );
- ADD_OPATOMIC_CASE(idec, "%unused = OpAtomicIDecrement %i32 %outloc %one %zero\n", { --expected; (void)input;} );
+ #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 (1, -1);
+ 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(expected[0], inputInts[ndx]);
+ cases[caseNdx].calculateExpected((cases[caseNdx].numOutputElements == 1) ? expected[0] : expected[ndx], inputInts[ndx]);
}
spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
" 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"
" 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"
"%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"
"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"
"%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"
"%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"
"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"
"%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"
"%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"
"%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"
"%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"
"%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.
"%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.
"%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"
}
}
+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);
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)
{
}
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
{
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
{
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_outputBuffer);
spec.numWorkGroups = IVec3(1, 1, 1);
{
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_outputBuffer);
spec.numWorkGroups = IVec3(1, 1, 1);
string widthStr = numberToString(width);
int index = rnd.getInt(0, width-1);
- params["name"] = "vec_" + widthStr;
+ params["type"] = "vec";
+ params["name"] = params["type"] + "_" + widthStr;
params["compositeType"] = "%composite = OpTypeVector %custom " + widthStr +"\n";
params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n";
params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %filler", width) + "\n";
string widthStr = numberToString(width);
int index = rnd.getInt(0, width-1);
- params["name"] = "array_" + widthStr;
+ params["type"] = "array";
+ params["name"] = params["type"] + "_" + widthStr;
params["compositeType"] = string("%arraywidth = OpConstant %u32 " + widthStr + "\n")
+ "%composite = OpTypeArray %custom %arraywidth\n";
string randomConst = numberToString(getInt(rnd));
int index = rnd.getInt(0, width-1);
- params["name"] = "struct_" + numberToString(width);
+ params["type"] = "struct";
+ params["name"] = params["type"] + "_" + numberToString(width);
params["compositeType"] = "%composite = OpTypeStruct" + repeatString(" %custom", width) + "\n";
params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n";
params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %filler", width) + "\n";
int index_1 = rnd.getInt(0, width-1);
string columnStr = numberToString(column);
- params["name"] = "matrix_" + widthStr + "x" + columnStr;
+ params["type"] = "matrix";
+ params["name"] = params["type"] + "_" + widthStr + "x" + columnStr;
params["compositeType"] = string("%vectype = OpTypeVector %custom " + widthStr + "\n")
+ "%composite = OpTypeMatrix %vectype " + columnStr + "\n";
parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
+ parameters["compositeDecorator"] = (parameters["type"] == "array") ? "OpDecorate %composite ArrayStride 4\n" : "";
+
return StringTemplate (
"OpCapability Shader\n"
"OpCapability Matrix\n"
"OpDecorate %outdata DescriptorSet 0\n"
"OpDecorate %outdata Binding 1\n"
"OpDecorate %customarr ArrayStride 4\n"
+ "${compositeDecorator}"
"OpMemberDecorate %buf 0 Offset 0\n"
// General types
return group.release();
}
+struct AssemblyStructInfo
+{
+ AssemblyStructInfo (const deUint32 comp, const deUint32 idx)
+ : components (comp)
+ , index (idx)
+ {}
+
+ deUint32 components;
+ deUint32 index;
+};
+
+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");
+ // Convert it to list of indexes
+ vector<string> indexes = de::splitString(fullIndex, ' ');
+
+ map<string, string> parameters (params);
+ parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
+ parameters["structType"] = repeatString(" %composite", structInfo.components);
+ parameters["structConstruct"] = repeatString(" %instance", structInfo.components);
+ parameters["insertIndexes"] = fullIndex;
+
+ // In matrix cases the last two index is the CompositeExtract indexes
+ const deUint32 extractIndexes = (parameters["type"] == "matrix") ? 2 : 1;
+
+ // Construct the extractIndex
+ for (vector<string>::const_iterator index = indexes.end() - extractIndexes; index != indexes.end(); ++index)
+ {
+ parameters["extractIndexes"] += " " + *index;
+ }
+
+ // Remove the last 1 or 2 element depends on matrix case or not
+ indexes.erase(indexes.end() - extractIndexes, indexes.end());
+
+ deUint32 id = 0;
+ // Generate AccessChain index expressions (except for the last one, because we use ptr to the composite)
+ for (vector<string>::const_iterator index = indexes.begin(); index != indexes.end(); ++index)
+ {
+ string indexId = "%index_" + numberToString(id++);
+ parameters["accessChainConstDeclaration"] += indexId + " = OpConstant %u32 " + *index + "\n";
+ parameters["accessChainIndexes"] += " " + indexId;
+ }
+
+ parameters["compositeDecorator"] = (parameters["type"] == "array") ? "OpDecorate %composite ArrayStride 4\n" : "";
+
+ return StringTemplate (
+ "OpCapability Shader\n"
+ "OpCapability Matrix\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"
+ // Decorators
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+ "OpDecorate %buf BufferBlock\n"
+ "OpDecorate %indata DescriptorSet 0\n"
+ "OpDecorate %indata Binding 0\n"
+ "OpDecorate %outdata DescriptorSet 0\n"
+ "OpDecorate %outdata Binding 1\n"
+ "OpDecorate %customarr ArrayStride 4\n"
+ "${compositeDecorator}"
+ "OpMemberDecorate %buf 0 Offset 0\n"
+ // General types
+ "%void = OpTypeVoid\n"
+ "%voidf = OpTypeFunction %void\n"
+ "%u32 = OpTypeInt 32 0\n"
+ "%uvec3 = OpTypeVector %u32 3\n"
+ "%uvec3ptr = OpTypePointer Input %uvec3\n"
+ // Custom type
+ "%custom = ${typeDeclaration}\n"
+ // Custom types
+ "${compositeType}"
+ // Inherited from composite
+ "%composite_p = OpTypePointer Function %composite\n"
+ "%struct_t = OpTypeStruct${structType}\n"
+ "%struct_p = OpTypePointer Function %struct_t\n"
+ // Constants
+ "${filler}"
+ "${accessChainConstDeclaration}"
+ // Inherited from custom
+ "%customptr = OpTypePointer Uniform %custom\n"
+ "%customarr = OpTypeRuntimeArray %custom\n"
+ "%buf = OpTypeStruct %customarr\n"
+ "%bufptr = OpTypePointer Uniform %buf\n"
+ "%indata = OpVariable %bufptr Uniform\n"
+ "%outdata = OpVariable %bufptr Uniform\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%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
+ "%inloc = OpInBoundsAccessChain %customptr %indata %zero %x\n"
+ "%outloc = OpInBoundsAccessChain %customptr %outdata %zero %x\n"
+ // Read the input value
+ "%inval = OpLoad %custom %inloc\n"
+ // Create the composite and fill it
+ "${compositeConstruct}"
+ // Create the struct and fill it with the composite
+ "%struct = OpCompositeConstruct %struct_t${structConstruct}\n"
+ // Insert the value
+ "%comp_obj = OpCompositeInsert %struct_t %inval %struct ${insertIndexes}\n"
+ // Store the object
+ " OpStore %struct_v %comp_obj\n"
+ // Get deepest possible composite pointer
+ "%inner_ptr = OpInBoundsAccessChain %composite_p %struct_v${accessChainIndexes}\n"
+ "%read_obj = OpLoad %composite %inner_ptr\n"
+ // Read back the stored value
+ "%read_val = OpCompositeExtract %custom %read_obj${extractIndexes}\n"
+ " OpStore %outloc %read_val\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n").specialize(parameters);
+}
+
+tcu::TestCaseGroup* createOpInBoundsAccessChainGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opinboundsaccesschain", "Test the OpInBoundsAccessChain instruction"));
+ de::Random rnd (deStringHash(group->getName()));
+
+ for (int type = TYPE_INT; type != TYPE_END; ++type)
+ {
+ NumberType numberType = NumberType(type);
+ const string typeName = getNumberTypeName(numberType);
+ const string description = "Test the OpInBoundsAccessChain instruction with " + typeName + "s";
+ de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, typeName.c_str(), description.c_str()));
+
+ vector<map<string, string> > testCases;
+ createCompositeCases(testCases, rnd, numberType);
+
+ for (vector<map<string, string> >::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
+ {
+ ComputeShaderSpec spec;
+
+ // Number of components inside of a struct
+ deUint32 structComponents = rnd.getInt(2, 8);
+ // Component index value
+ deUint32 structIndex = rnd.getInt(0, structComponents - 1);
+ AssemblyStructInfo structInfo(structComponents, structIndex);
+
+ spec.assembly = specializeInBoundsShaderTemplate(numberType, structInfo, *test);
+
+ switch (numberType)
+ {
+ case TYPE_INT:
+ {
+ deInt32 number = getInt(rnd);
+ spec.inputs.push_back(createCompositeBuffer<deInt32>(number));
+ spec.outputs.push_back(createCompositeBuffer<deInt32>(number));
+ break;
+ }
+ case TYPE_UINT:
+ {
+ deUint32 number = rnd.getUint32();
+ spec.inputs.push_back(createCompositeBuffer<deUint32>(number));
+ spec.outputs.push_back(createCompositeBuffer<deUint32>(number));
+ break;
+ }
+ case TYPE_FLOAT:
+ {
+ float number = rnd.getFloat();
+ spec.inputs.push_back(createCompositeBuffer<float>(number));
+ spec.outputs.push_back(createCompositeBuffer<float>(number));
+ break;
+ }
+ default:
+ DE_ASSERT(false);
+ }
+ spec.numWorkGroups = IVec3(1, 1, 1);
+ subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, test->at("name").c_str(), "OpInBoundsAccessChain test", spec));
+ }
+ group->addChild(subGroup.release());
+ }
+ return group.release();
+}
+
+// If the params missing, uninitialized case
+const string specializeDefaultOutputShaderTemplate (const NumberType type, const map<string, string>& params = map<string, string>())
+{
+ map<string, string> parameters(params);
+
+ parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
+
+ // Declare the const value, and use it in the initializer
+ if (params.find("constValue") != params.end())
+ {
+ parameters["constDeclaration"] = "%const = OpConstant %in_type " + params.at("constValue") + "\n";
+ parameters["variableInitializer"] = "%const";
+ }
+ // Uninitialized case
+ else
+ {
+ parameters["constDeclaration"] = "";
+ parameters["variableInitializer"] = "";
+ }
+
+ return StringTemplate(
+ "OpCapability Shader\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"
+ // 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 4\n"
+ "OpDecorate %in_buf BufferBlock\n"
+ "OpMemberDecorate %in_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 = ${typeDeclaration}\n"
+ // "%const = OpConstant %in_type ${constValue}\n"
+ "${constDeclaration}\n"
+ // Derived types
+ "%in_ptr = OpTypePointer Uniform %in_type\n"
+ "%in_arr = OpTypeRuntimeArray %in_type\n"
+ "%in_buf = OpTypeStruct %in_arr\n"
+ "%in_bufptr = OpTypePointer Uniform %in_buf\n"
+ "%indata = OpVariable %in_bufptr Uniform\n"
+ "%outdata = OpVariable %in_bufptr Uniform\n"
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%var_ptr = OpTypePointer Function %in_type\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 %in_ptr %outdata %zero %x\n"
+
+ "%out_var = OpVariable %var_ptr Function ${variableInitializer}\n"
+ "%outval = OpLoad %in_type %out_var\n"
+ " OpStore %outloc %outval\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n"
+ ).specialize(parameters);
+}
+
+bool compareFloats (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog& log)
+{
+ DE_ASSERT(outputAllocs.size() != 0);
+ DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
+
+ // Use custom epsilon because of the float->string conversion
+ const float epsilon = 0.00001f;
+
+ for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
+ {
+ float expected;
+ memcpy(&expected, expectedOutputs[outputNdx]->data(), expectedOutputs[outputNdx]->getNumBytes());
+
+ float actual;
+ memcpy(&actual, outputAllocs[outputNdx]->getHostPtr(), expectedOutputs[outputNdx]->getNumBytes());
+
+ // Test with epsilon
+ if (fabs(expected - actual) > epsilon)
+ {
+ log << TestLog::Message << "Error: The actual and expected values not matching."
+ << " Expected: " << expected << " Actual: " << actual << " Epsilon: " << epsilon << TestLog::EndMessage;
+ return false;
+ }
+ }
+ return true;
+}
+
+// Checks if the driver crash with uninitialized cases
+bool passthruVerify (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
+{
+ DE_ASSERT(outputAllocs.size() != 0);
+ DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
+
+ // Copy and discard the result.
+ for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
+ {
+ size_t width = expectedOutputs[outputNdx]->getNumBytes();
+
+ vector<char> data(width);
+ memcpy(&data[0], outputAllocs[outputNdx]->getHostPtr(), width);
+ }
+ return true;
+}
+
+tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_default_output", "Test shader default output."));
+ de::Random rnd (deStringHash(group->getName()));
+
+ for (int type = TYPE_INT; type != TYPE_END; ++type)
+ {
+ NumberType numberType = NumberType(type);
+ const string typeName = getNumberTypeName(numberType);
+ const string description = "Test the OpVariable initializer with " + typeName + ".";
+ de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, typeName.c_str(), description.c_str()));
+
+ // 2 similar subcases (initialized and uninitialized)
+ for (int subCase = 0; subCase < 2; ++subCase)
+ {
+ ComputeShaderSpec spec;
+ spec.numWorkGroups = IVec3(1, 1, 1);
+
+ map<string, string> params;
+
+ switch (numberType)
+ {
+ case TYPE_INT:
+ {
+ deInt32 number = getInt(rnd);
+ spec.inputs.push_back(createCompositeBuffer<deInt32>(number));
+ spec.outputs.push_back(createCompositeBuffer<deInt32>(number));
+ params["constValue"] = numberToString(number);
+ break;
+ }
+ case TYPE_UINT:
+ {
+ deUint32 number = rnd.getUint32();
+ spec.inputs.push_back(createCompositeBuffer<deUint32>(number));
+ spec.outputs.push_back(createCompositeBuffer<deUint32>(number));
+ params["constValue"] = numberToString(number);
+ break;
+ }
+ case TYPE_FLOAT:
+ {
+ float number = rnd.getFloat();
+ spec.inputs.push_back(createCompositeBuffer<float>(number));
+ spec.outputs.push_back(createCompositeBuffer<float>(number));
+ spec.verifyIO = &compareFloats;
+ params["constValue"] = numberToString(number);
+ break;
+ }
+ default:
+ DE_ASSERT(false);
+ }
+
+ // Initialized subcase
+ if (!subCase)
+ {
+ spec.assembly = specializeDefaultOutputShaderTemplate(numberType, params);
+ subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "initialized", "OpVariable initializer tests.", spec));
+ }
+ // Uninitialized subcase
+ else
+ {
+ spec.assembly = specializeDefaultOutputShaderTemplate(numberType);
+ spec.verifyIO = &passthruVerify;
+ subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "uninitialized", "OpVariable initializer tests.", spec));
+ }
+ }
+ group->addChild(subGroup.release());
+ }
+ return group.release();
+}
+
tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
computeTests->addChild(createSConvertTests(testCtx));
computeTests->addChild(createUConvertTests(testCtx));
computeTests->addChild(createOpCompositeInsertGroup(testCtx));
+ computeTests->addChild(createOpInBoundsAccessChainGroup(testCtx));
+ computeTests->addChild(createShaderDefaultOutputGroup(testCtx));
RGBA defaultColors[4];
getDefaultColors(defaultColors);