From f5ceec91baed6c97fdb6ca35bbbbdd2e32abdc39 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 1 Mar 2017 16:48:20 -0800 Subject: [PATCH] dEQP-VK: Add 64-bit versions of the SPIR-V SMod and SRem tests This adds the following tests: dEQP-VK.spirv_assembly.instruction.compute.opsrem64.positive dEQP-VK.spirv_assembly.instruction.compute.opsrem64.all dEQP-VK.spirv_assembly.instruction.compute.opsmod64.positive dEQP-VK.spirv_assembly.instruction.compute.opsmod64.all Components: Vulkan Change-Id: Id2c78e94632637f110726c805fd287b63adbde68 --- android/cts/master/vk-master.txt | 4 + .../vktSpvAsmComputeShaderTestUtil.cpp | 8 + .../vktSpvAsmComputeShaderTestUtil.hpp | 2 + .../spirv_assembly/vktSpvAsmInstructionTests.cpp | 270 ++++++++++++++++++++- external/vulkancts/mustpass/1.0.3/vk-default.txt | 4 + 5 files changed, 287 insertions(+), 1 deletion(-) diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index db875b7..d7f606b 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -132169,8 +132169,12 @@ dEQP-VK.spirv_assembly.instruction.compute.opquantize.rounded dEQP-VK.spirv_assembly.instruction.compute.opfrem.all dEQP-VK.spirv_assembly.instruction.compute.opsrem.positive dEQP-VK.spirv_assembly.instruction.compute.opsrem.all +dEQP-VK.spirv_assembly.instruction.compute.opsrem64.positive +dEQP-VK.spirv_assembly.instruction.compute.opsrem64.all dEQP-VK.spirv_assembly.instruction.compute.opsmod.positive dEQP-VK.spirv_assembly.instruction.compute.opsmod.all +dEQP-VK.spirv_assembly.instruction.compute.opsmod64.positive +dEQP-VK.spirv_assembly.instruction.compute.opsmod64.all dEQP-VK.spirv_assembly.instruction.compute.sconvert.int16_to_int32 dEQP-VK.spirv_assembly.instruction.compute.sconvert.int16_to_int64 dEQP-VK.spirv_assembly.instruction.compute.sconvert.int32_to_int64 diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp index 2d60026..8dc32fe 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp @@ -55,6 +55,14 @@ const char* getComputeAsmCommonTypes (void) "%f32arr = OpTypeRuntimeArray %f32\n"; } +const char* getComputeAsmCommonInt64Types (void) +{ + return + "%i64 = OpTypeInt 64 1\n" + "%i64ptr = OpTypePointer Uniform %i64\n" + "%i64arr = OpTypeRuntimeArray %i64\n"; +} + const char* getComputeAsmInputOutputBuffer (void) { return diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp index cbc05c8..948197b 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp @@ -78,6 +78,7 @@ DE_STATIC_ASSERT(sizeof(tcu::Vec4) == 4 * sizeof(float)); typedef Buffer Float32Buffer; typedef Buffer Int32Buffer; +typedef Buffer Int64Buffer; typedef Buffer Vec4Buffer; @@ -120,6 +121,7 @@ struct ComputeShaderSpec const char* getComputeAsmShaderPreamble (void); const char* getComputeAsmCommonTypes (void); +const char* getComputeAsmCommonInt64Types (void); /*--------------------------------------------------------------------*//*! * Declares two uniform variables (indata, outdata) of type diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp index f6c9a68..f0ff5c2 100644 --- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp +++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp @@ -107,7 +107,46 @@ static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* ds } } -inline bool filterNotZero (const deInt32 value) +// Gets a 64-bit integer with a more logarithmic distribution +deInt64 randomInt64LogDistributed (de::Random& rnd) +{ + deInt64 val = rnd.getUint64(); + val &= (1ull << rnd.getInt(1, 63)) - 1; + if (rnd.getBool()) + val = -val; + return val; +} + +static void fillRandomInt64sLogDistributed (de::Random& rnd, vector& dst, int numValues) +{ + for (int ndx = 0; ndx < numValues; ndx++) + dst[ndx] = randomInt64LogDistributed(rnd); +} + +template +static void fillRandomInt64sLogDistributed (de::Random& rnd, vector& dst, int numValues, FilterT filter) +{ + for (int ndx = 0; ndx < numValues; ndx++) + { + deInt64 value; + do { + value = randomInt64LogDistributed(rnd); + } while (!filter(value)); + dst[ndx] = value; + } +} + +inline bool filterNonNegative (const deInt64 value) +{ + return value >= 0; +} + +inline bool filterPositive (const deInt64 value) +{ + return value > 0; +} + +inline bool filterNotZero (const deInt64 value) { return value != 0; } @@ -911,6 +950,109 @@ tcu::TestCaseGroup* createOpSRemComputeGroup (tcu::TestContext& testCtx, qpTestR return group.release(); } +tcu::TestCaseGroup* createOpSRemComputeGroup64 (tcu::TestContext& testCtx, qpTestResult negFailResult) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opsrem64", "Test the 64-bit OpSRem instruction")); + de::Random rnd (deStringHash(group->getName())); + const int numElements = 200; + + const struct CaseParams + { + const char* name; + const char* failMessage; // customized status message + qpTestResult failResult; // override status on failure + bool positive; + } cases[] = + { + { "positive", "Output doesn't match with expected", QP_TEST_RESULT_FAIL, true }, + { "all", "Inconsistent results, but within specification", negFailResult, false }, // see below + }; + // If either operand is negative the result is undefined. Some implementations may still return correct values. + + for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) + { + const CaseParams& params = cases[caseNdx]; + ComputeShaderSpec spec; + vector inputInts1 (numElements, 0); + vector inputInts2 (numElements, 0); + vector outputInts (numElements, 0); + + if (params.positive) + { + fillRandomInt64sLogDistributed(rnd, inputInts1, numElements, filterNonNegative); + fillRandomInt64sLogDistributed(rnd, inputInts2, numElements, filterPositive); + } + else + { + fillRandomInt64sLogDistributed(rnd, inputInts1, numElements); + fillRandomInt64sLogDistributed(rnd, inputInts2, numElements, filterNotZero); + } + + for (int ndx = 0; ndx < numElements; ++ndx) + { + // The return value of std::fmod() has the same sign as its first operand, which is how OpFRem spec'd. + outputInts[ndx] = inputInts1[ndx] % inputInts2[ndx]; + } + + spec.assembly = + "OpCapability Int64\n" + + + string(getComputeAsmShaderPreamble()) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + "OpDecorate %buf BufferBlock\n" + "OpDecorate %indata1 DescriptorSet 0\n" + "OpDecorate %indata1 Binding 0\n" + "OpDecorate %indata2 DescriptorSet 0\n" + "OpDecorate %indata2 Binding 1\n" + "OpDecorate %outdata DescriptorSet 0\n" + "OpDecorate %outdata Binding 2\n" + "OpDecorate %i64arr ArrayStride 8\n" + "OpMemberDecorate %buf 0 Offset 0\n" + + + string(getComputeAsmCommonTypes()) + + string(getComputeAsmCommonInt64Types()) + + + "%buf = OpTypeStruct %i64arr\n" + "%bufptr = OpTypePointer Uniform %buf\n" + "%indata1 = OpVariable %bufptr Uniform\n" + "%indata2 = OpVariable %bufptr Uniform\n" + "%outdata = OpVariable %bufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i64 0\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc1 = OpAccessChain %i64ptr %indata1 %zero %x\n" + "%inval1 = OpLoad %i64 %inloc1\n" + "%inloc2 = OpAccessChain %i64ptr %indata2 %zero %x\n" + "%inval2 = OpLoad %i64 %inloc2\n" + "%rem = OpSRem %i64 %inval1 %inval2\n" + "%outloc = OpAccessChain %i64ptr %outdata %zero %x\n" + " OpStore %outloc %rem\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec.inputs.push_back (BufferSp(new Int64Buffer(inputInts1))); + spec.inputs.push_back (BufferSp(new Int64Buffer(inputInts2))); + spec.outputs.push_back (BufferSp(new Int64Buffer(outputInts))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.failResult = params.failResult; + spec.failMessage = params.failMessage; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, params.name, "", spec, COMPUTE_TEST_USES_INT64)); + } + + return group.release(); +} + tcu::TestCaseGroup* createOpSModComputeGroup (tcu::TestContext& testCtx, qpTestResult negFailResult) { de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opsmod", "Test the OpSMod instruction")); @@ -1024,6 +1166,130 @@ tcu::TestCaseGroup* createOpSModComputeGroup (tcu::TestContext& testCtx, qpTestR return group.release(); } +tcu::TestCaseGroup* createOpSModComputeGroup64 (tcu::TestContext& testCtx, qpTestResult negFailResult) +{ + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "opsmod64", "Test the OpSMod instruction")); + de::Random rnd (deStringHash(group->getName())); + const int numElements = 200; + + const struct CaseParams + { + const char* name; + const char* failMessage; // customized status message + qpTestResult failResult; // override status on failure + bool positive; + } cases[] = + { + { "positive", "Output doesn't match with expected", QP_TEST_RESULT_FAIL, true }, + { "all", "Inconsistent results, but within specification", negFailResult, false }, // see below + }; + // If either operand is negative the result is undefined. Some implementations may still return correct values. + + for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) + { + const CaseParams& params = cases[caseNdx]; + + ComputeShaderSpec spec; + vector inputInts1 (numElements, 0); + vector inputInts2 (numElements, 0); + vector outputInts (numElements, 0); + + + if (params.positive) + { + fillRandomInt64sLogDistributed(rnd, inputInts1, numElements, filterNonNegative); + fillRandomInt64sLogDistributed(rnd, inputInts2, numElements, filterPositive); + } + else + { + fillRandomInt64sLogDistributed(rnd, inputInts1, numElements); + fillRandomInt64sLogDistributed(rnd, inputInts2, numElements, filterNotZero); + } + + for (int ndx = 0; ndx < numElements; ++ndx) + { + deInt64 rem = inputInts1[ndx] % inputInts2[ndx]; + if (rem == 0) + { + outputInts[ndx] = 0; + } + else if ((inputInts1[ndx] >= 0) == (inputInts2[ndx] >= 0)) + { + // They have the same sign + outputInts[ndx] = rem; + } + else + { + // They have opposite sign. The remainder operation takes the + // sign inputInts1[ndx] but OpSMod is supposed to take ths sign + // of inputInts2[ndx]. Adding inputInts2[ndx] will ensure that + // the result has the correct sign and that it is still + // congruent to inputInts1[ndx] modulo inputInts2[ndx] + // + // See also http://mathforum.org/library/drmath/view/52343.html + outputInts[ndx] = rem + inputInts2[ndx]; + } + } + + spec.assembly = + "OpCapability Int64\n" + + + string(getComputeAsmShaderPreamble()) + + + "OpName %main \"main\"\n" + "OpName %id \"gl_GlobalInvocationID\"\n" + + "OpDecorate %id BuiltIn GlobalInvocationId\n" + + "OpDecorate %buf BufferBlock\n" + "OpDecorate %indata1 DescriptorSet 0\n" + "OpDecorate %indata1 Binding 0\n" + "OpDecorate %indata2 DescriptorSet 0\n" + "OpDecorate %indata2 Binding 1\n" + "OpDecorate %outdata DescriptorSet 0\n" + "OpDecorate %outdata Binding 2\n" + "OpDecorate %i64arr ArrayStride 8\n" + "OpMemberDecorate %buf 0 Offset 0\n" + + + string(getComputeAsmCommonTypes()) + + string(getComputeAsmCommonInt64Types()) + + + "%buf = OpTypeStruct %i64arr\n" + "%bufptr = OpTypePointer Uniform %buf\n" + "%indata1 = OpVariable %bufptr Uniform\n" + "%indata2 = OpVariable %bufptr Uniform\n" + "%outdata = OpVariable %bufptr Uniform\n" + + "%id = OpVariable %uvec3ptr Input\n" + "%zero = OpConstant %i64 0\n" + + "%main = OpFunction %void None %voidf\n" + "%label = OpLabel\n" + "%idval = OpLoad %uvec3 %id\n" + "%x = OpCompositeExtract %u32 %idval 0\n" + "%inloc1 = OpAccessChain %i64ptr %indata1 %zero %x\n" + "%inval1 = OpLoad %i64 %inloc1\n" + "%inloc2 = OpAccessChain %i64ptr %indata2 %zero %x\n" + "%inval2 = OpLoad %i64 %inloc2\n" + "%rem = OpSMod %i64 %inval1 %inval2\n" + "%outloc = OpAccessChain %i64ptr %outdata %zero %x\n" + " OpStore %outloc %rem\n" + " OpReturn\n" + " OpFunctionEnd\n"; + + spec.inputs.push_back (BufferSp(new Int64Buffer(inputInts1))); + spec.inputs.push_back (BufferSp(new Int64Buffer(inputInts2))); + spec.outputs.push_back (BufferSp(new Int64Buffer(outputInts))); + spec.numWorkGroups = IVec3(numElements, 1, 1); + spec.failResult = params.failResult; + spec.failMessage = params.failMessage; + + group->addChild(new SpvAsmComputeShaderCase(testCtx, params.name, "", spec, COMPUTE_TEST_USES_INT64)); + } + + return group.release(); +} + // Copy contents in the input buffer to the output buffer. tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) { @@ -7134,7 +7400,9 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) computeTests ->addChild(createOpQuantizeToF16Group(testCtx)); computeTests ->addChild(createOpFRemGroup(testCtx)); computeTests->addChild(createOpSRemComputeGroup(testCtx, QP_TEST_RESULT_PASS)); + computeTests->addChild(createOpSRemComputeGroup64(testCtx, QP_TEST_RESULT_PASS)); computeTests->addChild(createOpSModComputeGroup(testCtx, QP_TEST_RESULT_PASS)); + computeTests->addChild(createOpSModComputeGroup64(testCtx, QP_TEST_RESULT_PASS)); computeTests->addChild(createSConvertTests(testCtx)); computeTests->addChild(createUConvertTests(testCtx)); computeTests->addChild(createOpCompositeInsertGroup(testCtx)); diff --git a/external/vulkancts/mustpass/1.0.3/vk-default.txt b/external/vulkancts/mustpass/1.0.3/vk-default.txt index 075b149..4abfb55 100644 --- a/external/vulkancts/mustpass/1.0.3/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.3/vk-default.txt @@ -154302,8 +154302,12 @@ dEQP-VK.spirv_assembly.instruction.compute.opquantize.rounded dEQP-VK.spirv_assembly.instruction.compute.opfrem.all dEQP-VK.spirv_assembly.instruction.compute.opsrem.positive dEQP-VK.spirv_assembly.instruction.compute.opsrem.all +dEQP-VK.spirv_assembly.instruction.compute.opsrem64.positive +dEQP-VK.spirv_assembly.instruction.compute.opsrem64.all dEQP-VK.spirv_assembly.instruction.compute.opsmod.positive dEQP-VK.spirv_assembly.instruction.compute.opsmod.all +dEQP-VK.spirv_assembly.instruction.compute.opsmod64.positive +dEQP-VK.spirv_assembly.instruction.compute.opsmod64.all dEQP-VK.spirv_assembly.instruction.compute.sconvert.int16_to_int32 dEQP-VK.spirv_assembly.instruction.compute.sconvert.int16_to_int64 dEQP-VK.spirv_assembly.instruction.compute.sconvert.int32_to_int64 -- 2.7.4