#include "deUniquePtr.hpp"
#include "tcuStringTemplate.hpp"
-#include <cmath>
#include "vktSpvAsmComputeShaderCase.hpp"
#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "vktTestCaseUtil.hpp"
"%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 =
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;
}
}
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"
"%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"
"%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");
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);
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));
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"));
+ 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"
+ 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"
" 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"
"%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"
"%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.);
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;
}
"%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_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));
{
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));
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);
"%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
// 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"
computeTests->addChild(createOpNopGroup(testCtx));
computeTests->addChild(createOpFUnordGroup(testCtx));
+ computeTests->addChild(createOpAtomicGroup(testCtx));
computeTests->addChild(createOpLineGroup(testCtx));
computeTests->addChild(createOpNoLineGroup(testCtx));
computeTests->addChild(createOpConstantNullGroup(testCtx));