return testGroup.release();
}
-struct getV_ { deUint32 inline operator()(deUint32 v) const { return v; } getV_(){} };
-struct getV0 { deUint32 inline operator()(deUint32 v) const { return v & (~1); } getV0(){} };
-struct getV1 { deUint32 inline operator()(deUint32 v) const { return v | ( 1); } getV1(){} };
-
-template<deUint32 R, deUint32 N>
-inline static deUint32 getOffset(deUint32 x, deUint32 y, deUint32 n)
-{
- return N * ((R * y) + x) + n;
-}
-
-template<deUint32 R, deUint32 N, class X0, class X1, class Y0, class Y1>
-struct getFDelta
-{
- float operator() (const deFloat16* data, deUint32 x, deUint32 y, deUint32 n, deUint32 flavor) const
- {
- DE_STATIC_ASSERT(R%2 == 0);
- DE_ASSERT(flavor == 0);
- DE_UNREF(flavor);
-
- const X0 x0;
- const X1 x1;
- const Y0 y0;
- const Y1 y1;
- const deFloat16 v0 = data[getOffset<R, N>(x0(x), y0(y), n)];
- const deFloat16 v1 = data[getOffset<R, N>(x1(x), y1(y), n)];
- const tcu::Float16 f0 = tcu::Float16(v0);
- const tcu::Float16 f1 = tcu::Float16(v1);
- const float d0 = f0.asFloat();
- const float d1 = f1.asFloat();
- const float d = d1 - d0;
-
- return d;
- }
-
- getFDelta(){}
-};
-
-template<deUint32 F, class Class0, class Class1>
-struct getFOneOf
-{
- float operator() (const deFloat16* data, deUint32 x, deUint32 y, deUint32 n, deUint32 flavor) const
- {
- DE_ASSERT(flavor < F);
-
- if (flavor == 0)
- {
- Class0 c;
-
- return c(data, x, y, n, flavor);
- }
- else
- {
- Class1 c;
-
- return c(data, x, y, n, flavor - 1);
- }
- }
-
- getFOneOf(){}
-};
-
-template<class FineX0, class FineX1, class FineY0, class FineY1>
-struct calcWidthOf4
-{
- float operator() (const deFloat16* data, deUint32 x, deUint32 y, deUint32 n, deUint32 flavor) const
- {
- DE_ASSERT(flavor < 4);
-
- const deUint32 flavorX = (flavor & 1) == 0 ? 0 : 1;
- const deUint32 flavorY = (flavor & 2) == 0 ? 0 : 1;
- const getFOneOf<2, FineX0, FineX1> cx;
- const getFOneOf<2, FineY0, FineY1> cy;
- float v = 0;
-
- v += fabsf(cx(data, x, y, n, flavorX));
- v += fabsf(cy(data, x, y, n, flavorY));
-
- return v;
- }
-
- calcWidthOf4(){}
-};
-
-template<deUint32 R, deUint32 N, class Derivative>
-bool compareDerivativeWithFlavor (const deFloat16* inputAsFP16, const deFloat16* outputAsFP16, deUint32 flavor, std::string& error)
-{
- const deUint32 numDataPointsByAxis = R;
- const Derivative derivativeFunc;
-
- for (deUint32 y = 0; y < numDataPointsByAxis; ++y)
- for (deUint32 x = 0; x < numDataPointsByAxis; ++x)
- for (deUint32 n = 0; n < N; ++n)
- {
- const float expectedFloat = derivativeFunc(inputAsFP16, x, y, n, flavor);
- deFloat16 expected = deFloat32To16Round(expectedFloat, DE_ROUNDINGMODE_TO_NEAREST_EVEN);
- const deFloat16 output = outputAsFP16[getOffset<R, N>(x, y, n)];
-
- bool reportError = !compare16BitFloat(expected, output, error);
-
- if (reportError)
- {
- expected = deFloat32To16Round(expectedFloat, DE_ROUNDINGMODE_TO_ZERO);
- reportError = !compare16BitFloat(expected, output, error);
- }
-
- if (reportError)
- {
- error = "subcase at " + de::toString(x) + "," + de::toString(y) + "," + de::toString(n) + ": " + error;
-
- return false;
- }
- }
-
- return true;
-}
-
-template<deUint32 R, deUint32 N, deUint32 FLAVOUR_COUNT, class Derivative>
-bool compareDerivative (const std::vector<Resource>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>&, TestLog& log)
-{
- if (inputs.size() != 1 || outputAllocs.size() != 1)
- return false;
-
- deUint32 successfulRuns = FLAVOUR_COUNT;
- std::string results[FLAVOUR_COUNT];
- vector<deUint8> inputBytes;
-
- inputs[0].getBytes(inputBytes);
-
- const deFloat16* inputAsFP16 = reinterpret_cast<deFloat16* const>(&inputBytes.front());
- const deFloat16* outputAsFP16 = static_cast<deFloat16*>(outputAllocs[0]->getHostPtr());
-
- DE_ASSERT(inputBytes.size() == R * R * N * sizeof(deFloat16));
-
- for (deUint32 flavor = 0; flavor < FLAVOUR_COUNT; ++flavor)
- if (compareDerivativeWithFlavor<R, N, Derivative> (inputAsFP16, outputAsFP16, flavor, results[flavor]))
- {
- break;
- }
- else
- {
- successfulRuns--;
- }
-
- if (successfulRuns == 0)
- for (deUint32 flavor = 0; flavor < FLAVOUR_COUNT; flavor++)
- log << TestLog::Message << "At flavor #" << flavor << " " << results[flavor] << TestLog::EndMessage;
-
- return successfulRuns > 0;
-}
-
-template<deUint32 R, deUint32 N>
-tcu::TestCaseGroup* createDerivativeTests (tcu::TestContext& testCtx)
-{
- typedef getFDelta<R, N, getV0, getV1, getV_, getV_> getFDxFine;
- typedef getFDelta<R, N, getV_, getV_, getV0, getV1> getFDyFine;
-
- typedef getFDelta<R, N, getV0, getV1, getV0, getV0> getFdxCoarse0;
- typedef getFDelta<R, N, getV0, getV1, getV1, getV1> getFdxCoarse1;
- typedef getFDelta<R, N, getV0, getV0, getV0, getV1> getFdyCoarse0;
- typedef getFDelta<R, N, getV1, getV1, getV0, getV1> getFdyCoarse1;
- typedef getFOneOf<2, getFdxCoarse0, getFdxCoarse1> getFDxCoarse;
- typedef getFOneOf<2, getFdyCoarse0, getFdyCoarse1> getFDyCoarse;
-
- typedef calcWidthOf4<getFDxFine, getFDxFine, getFDyFine, getFDyFine> getFWidthFine;
- typedef calcWidthOf4<getFdxCoarse0, getFdxCoarse1, getFdyCoarse0, getFdyCoarse1> getFWidthCoarse;
-
- typedef getFOneOf<3, getFDxFine, getFDxCoarse> getFDx;
- typedef getFOneOf<3, getFDyFine, getFDyCoarse> getFDy;
- typedef getFOneOf<5, getFWidthFine, getFWidthCoarse> getFWidth;
-
- const std::string testGroupName (std::string("derivative_") + de::toString(N));
- de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, testGroupName.c_str(), "Derivative instruction tests"));
-
- de::Random rnd (deStringHash(testGroup->getName()));
- const deUint32 numDataPointsByAxis = R;
- const deUint32 numDataPoints = N * numDataPointsByAxis * numDataPointsByAxis;
- vector<deFloat16> float16InputX;
- vector<deFloat16> float16InputY;
- vector<deFloat16> float16InputW;
- vector<deFloat16> float16OutputDummy (numDataPoints, 0);
- RGBA defaultColors[4];
-
- getDefaultColors(defaultColors);
-
- float16InputX.reserve(numDataPoints);
- for (deUint32 y = 0; y < numDataPointsByAxis; ++y)
- for (deUint32 x = 0; x < numDataPointsByAxis; ++x)
- for (deUint32 n = 0; n < N; ++n)
- {
- const float arg = static_cast<float>(2 * DE_PI) * static_cast<float>(x * (n + 1)) / static_cast<float>(1 * numDataPointsByAxis);
-
- if (y%2 == 0)
- float16InputX.push_back(tcu::Float16(sin(arg)).bits());
- else
- float16InputX.push_back(tcu::Float16(cos(arg)).bits());
- }
-
- float16InputY.reserve(numDataPoints);
- for (deUint32 y = 0; y < numDataPointsByAxis; ++y)
- for (deUint32 x = 0; x < numDataPointsByAxis; ++x)
- for (deUint32 n = 0; n < N; ++n)
- {
- const float arg = static_cast<float>(2 * DE_PI) * static_cast<float>(y * (n + 1)) / static_cast<float>(1 * numDataPointsByAxis);
-
- if (x%2 == 0)
- float16InputY.push_back(tcu::Float16(sin(arg)).bits());
- else
- float16InputY.push_back(tcu::Float16(cos(arg)).bits());
- }
-
- const deFloat16 testNumbers[] =
- {
- tcu::Float16( 2.0 ).bits(),
- tcu::Float16( 4.0 ).bits(),
- tcu::Float16( 8.0 ).bits(),
- tcu::Float16( 16.0 ).bits(),
- tcu::Float16( 32.0 ).bits(),
- tcu::Float16( 64.0 ).bits(),
- tcu::Float16( 128.0).bits(),
- tcu::Float16( 256.0).bits(),
- tcu::Float16( 512.0).bits(),
- tcu::Float16(-2.0 ).bits(),
- tcu::Float16(-4.0 ).bits(),
- tcu::Float16(-8.0 ).bits(),
- tcu::Float16(-16.0 ).bits(),
- tcu::Float16(-32.0 ).bits(),
- tcu::Float16(-64.0 ).bits(),
- tcu::Float16(-128.0).bits(),
- tcu::Float16(-256.0).bits(),
- tcu::Float16(-512.0).bits(),
- };
-
- float16InputW.reserve(numDataPoints);
- for (deUint32 y = 0; y < numDataPointsByAxis; ++y)
- for (deUint32 x = 0; x < numDataPointsByAxis; ++x)
- for (deUint32 n = 0; n < N; ++n)
- float16InputW.push_back(testNumbers[rnd.getInt(0, DE_LENGTH_OF_ARRAY(testNumbers) - 1)]);
-
- struct TestOp
- {
- const char* opCode;
- vector<deFloat16>& inputData;
- VerifyIOFunc verifyFunc;
- };
-
- const TestOp testOps[] =
- {
- { "OpDPdxFine" , float16InputX , compareDerivative<R, N, 1, getFDxFine > },
- { "OpDPdyFine" , float16InputY , compareDerivative<R, N, 1, getFDyFine > },
- { "OpFwidthFine" , float16InputW , compareDerivative<R, N, 1, getFWidthFine > },
- { "OpDPdxCoarse" , float16InputX , compareDerivative<R, N, 3, getFDx > },
- { "OpDPdyCoarse" , float16InputY , compareDerivative<R, N, 3, getFDy > },
- { "OpFwidthCoarse" , float16InputW , compareDerivative<R, N, 5, getFWidth > },
- { "OpDPdx" , float16InputX , compareDerivative<R, N, 3, getFDx > },
- { "OpDPdy" , float16InputY , compareDerivative<R, N, 3, getFDy > },
- { "OpFwidth" , float16InputW , compareDerivative<R, N, 5, getFWidth > },
- };
-
- struct TestType
- {
- const deUint32 typeComponents;
- const char* typeName;
- const char* typeDecls;
- };
-
- const TestType testTypes[] =
- {
- {
- 1,
- "f16",
- ""
- },
- {
- 2,
- "v2f16",
- " %v2f16 = OpTypeVector %f16 2\n"
- },
- {
- 4,
- "v4f16",
- " %v4f16 = OpTypeVector %f16 4\n"
- },
- };
-
- const deUint32 testTypeNdx = (N == 1) ? 0
- : (N == 2) ? 1
- : (N == 4) ? 2
- : DE_LENGTH_OF_ARRAY(testTypes);
- const TestType& testType = testTypes[testTypeNdx];
-
- DE_ASSERT(testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes));
- DE_ASSERT(testType.typeComponents == N);
-
- const StringTemplate preMain
- (
- "%c_i32_ndp = OpConstant %i32 ${num_data_points}\n"
- " %c_u32_xw = OpConstant %u32 ${items_by_x}\n"
- " %f16 = OpTypeFloat 16\n"
- "${type_decls}"
- " %up_${tt} = OpTypePointer Uniform %${tt}\n"
- " %ra_${tt} = OpTypeArray %${tt} %c_i32_ndp\n"
- " %SSBO16 = OpTypeStruct %ra_${tt}\n"
- "%up_SSBO16 = OpTypePointer Uniform %SSBO16\n"
- " %ssbo_src = OpVariable %up_SSBO16 Uniform\n"
- " %ssbo_dst = OpVariable %up_SSBO16 Uniform\n"
- );
-
- const StringTemplate decoration
- (
- "OpDecorate %ra_${tt} ArrayStride ${tt_stride}\n"
- "OpMemberDecorate %SSBO16 0 Offset 0\n"
- "OpDecorate %SSBO16 BufferBlock\n"
- "OpDecorate %ssbo_src DescriptorSet 0\n"
- "OpDecorate %ssbo_src Binding 0\n"
- "OpDecorate %ssbo_dst DescriptorSet 0\n"
- "OpDecorate %ssbo_dst Binding 1\n"
- );
-
- const StringTemplate testFun
- (
- "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
- " %param = OpFunctionParameter %v4f32\n"
- " %entry = OpLabel\n"
-
- " %loc_x_c = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_0\n"
- " %loc_y_c = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_1\n"
- " %x_c = OpLoad %f32 %loc_x_c\n"
- " %y_c = OpLoad %f32 %loc_y_c\n"
- " %x_idx = OpConvertFToU %u32 %x_c\n"
- " %y_idx = OpConvertFToU %u32 %y_c\n"
- " %ndx_y = OpIMul %u32 %y_idx %c_u32_xw\n"
- " %ndx = OpIAdd %u32 %ndx_y %x_idx\n"
-
- " %src = OpAccessChain %up_${tt} %ssbo_src %c_i32_0 %ndx\n"
- " %val_src = OpLoad %${tt} %src\n"
- " %val_dst = ${op_code} %${tt} %val_src\n"
- " %dst = OpAccessChain %up_${tt} %ssbo_dst %c_i32_0 %ndx\n"
- " OpStore %dst %val_dst\n"
- " OpBranch %merge\n"
-
- " %merge = OpLabel\n"
- " OpReturnValue %param\n"
-
- " OpFunctionEnd\n"
- );
-
- for (deUint32 testOpsIdx = 0; testOpsIdx < DE_LENGTH_OF_ARRAY(testOps); ++testOpsIdx)
- {
- const TestOp& testOp = testOps[testOpsIdx];
- const string testName = de::toLower(string(testOp.opCode));
- const size_t typeStride = N * sizeof(deFloat16);
- GraphicsResources specResource;
- map<string, string> specs;
- VulkanFeatures features;
- vector<string> extensions;
- map<string, string> fragments;
- SpecConstants noSpecConstants;
- PushConstants noPushConstants;
- GraphicsInterfaces noInterfaces;
-
- specs["op_code"] = testOp.opCode;
- specs["num_data_points"] = de::toString(testOp.inputData.size() / N);
- specs["items_by_x"] = de::toString(numDataPointsByAxis);
- specs["tt"] = testType.typeName;
- specs["tt_stride"] = de::toString(typeStride);
- specs["type_decls"] = testType.typeDecls;
-
- fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
- fragments["capability"] = "OpCapability DerivativeControl\nOpCapability StorageUniformBufferBlock16\nOpCapability Float16\n";
- fragments["decoration"] = decoration.specialize(specs);
- fragments["pre_main"] = preMain.specialize(specs);
- fragments["testfun"] = testFun.specialize(specs);
-
- specResource.inputs.push_back(Resource(BufferSp(new Float16Buffer(testOp.inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
- specResource.outputs.push_back(Resource(BufferSp(new Float16Buffer(float16OutputDummy)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
- specResource.verifyIO = testOp.verifyFunc;
-
- extensions.push_back("VK_KHR_16bit_storage");
- extensions.push_back("VK_KHR_shader_float16_int8");
-
- features.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
- features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
-
- createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, testName.c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
- noPushConstants, specResource, noInterfaces, extensions, features, testGroup.get(), QP_TEST_RESULT_FAIL, string(), true);
- }
-
- return testGroup.release();
-}
-
bool compareFP16VectorExtractFunc (const std::vector<Resource>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>&, TestLog& log)
{
if (inputs.size() != 2 || outputAllocs.size() != 1)
testGroup->addChild(createFloat16LogicalSet<GraphicsResources>(testCtx, TEST_WITH_NAN));
testGroup->addChild(createFloat16LogicalSet<GraphicsResources>(testCtx, TEST_WITHOUT_NAN));
testGroup->addChild(createFloat16FuncSet<GraphicsResources>(testCtx));
- testGroup->addChild(createDerivativeTests<256, 1>(testCtx));
- testGroup->addChild(createDerivativeTests<256, 2>(testCtx));
- testGroup->addChild(createDerivativeTests<256, 4>(testCtx));
testGroup->addChild(createFloat16VectorExtractSet<GraphicsResources>(testCtx));
testGroup->addChild(createFloat16VectorInsertSet<GraphicsResources>(testCtx));
testGroup->addChild(createFloat16VectorShuffleSet<GraphicsResources>(testCtx));