#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include "deMath.h"
+#include "deRandom.hpp"
#include "tcuStringTemplate.hpp"
#include "vktSpvAsmCrossStageInterfaceTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktSpvAsmLoopDepLenTests.hpp"
#include "vktSpvAsmLoopDepInfTests.hpp"
+#include "vktSpvAsmCompositeInsertTests.hpp"
+#include "vktSpvAsmVaryingNameTests.hpp"
+#include "vktSpvAsmWorkgroupMemoryTests.hpp"
+#include "vktSpvAsmSignedIntCompareTests.hpp"
+#include "vktSpvAsmPtrAccessChainTests.hpp"
#include <cmath>
#include <limits>
using tcu::StringTemplate;
using tcu::Vec4;
+const bool TEST_WITH_NAN = true;
const bool TEST_WITHOUT_NAN = false;
template<typename T>
{
T* const typedPtr = (T*)dst;
for (int ndx = 0; ndx < numValues; ndx++)
- typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
+ typedPtr[offset + ndx] = de::randomScalar<T>(rnd, minValue, maxValue);
}
// Filter is a function that returns true if a value should pass, false otherwise.
for (int ndx = 0; ndx < numValues; ndx++)
{
do
- value = randomScalar<T>(rnd, minValue, maxValue);
+ value = de::randomScalar<T>(rnd, minValue, maxValue);
while (!filter(value));
typedPtr[offset + ndx] = value;
return group.release();
}
+tcu::TestCaseGroup* createUnusedVariableComputeTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "unused_variables", "Compute shaders with unused variables"));
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> positiveFloats (numElements, 0);
+ vector<float> negativeFloats (numElements, 0);
+
+ fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ negativeFloats[ndx] = -positiveFloats[ndx];
+
+ const VariableLocation testLocations[] =
+ {
+ // Set Binding
+ { 0, 5 },
+ { 5, 5 },
+ };
+
+ for (size_t locationNdx = 0; locationNdx < DE_LENGTH_OF_ARRAY(testLocations); ++locationNdx)
+ {
+ const VariableLocation& location = testLocations[locationNdx];
+
+ // Unused variable.
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly =
+ string(getComputeAsmShaderPreamble()) +
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + getUnusedDecorations(location)
+
+ + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes())
+
+ + getUnusedTypesAndConstants()
+
+ + string(getComputeAsmInputOutputBuffer())
+
+ + getUnusedBuffer() +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ std::string testName = "variable_" + location.toString();
+ std::string testDescription = "Unused variable test with " + location.toDescription();
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testDescription.c_str(), spec));
+ }
+
+ // Unused function.
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly =
+ string(getComputeAsmShaderPreamble("", "", "", getUnusedEntryPoint())) +
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + getUnusedDecorations(location)
+
+ + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes())
+
+ + getUnusedTypesAndConstants() +
+
+ "%c_i32_0 = OpConstant %i32 0\n"
+ "%c_i32_1 = OpConstant %i32 1\n"
+
+ + string(getComputeAsmInputOutputBuffer())
+
+ + getUnusedBuffer() +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n"
+
+ + getUnusedFunctionBody();
+
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+
+ std::string testName = "function_" + location.toString();
+ std::string testDescription = "Unused function test with " + location.toDescription();
+
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testDescription.c_str(), spec));
+ }
+ }
+
+ return group.release();
+}
+
+template<bool nanSupported>
bool compareFUnord (const std::vector<Resource>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<Resource>& expectedOutputs, TestLog& log)
{
if (outputAllocs.size() != 1)
for (size_t idx = 0; idx < expectedBytes.size() / sizeof(deInt32); ++idx)
{
+ if (!nanSupported && (tcu::Float32(input1AsFloat[idx]).isNaN() || tcu::Float32(input2AsFloat[idx]).isNaN()))
+ continue;
+
if (outputAsInt[idx] != expectedOutputAsInt[idx])
{
log << TestLog::Message << "ERROR: Sub-case failed. inputs: " << input1AsFloat[idx] << "," << input2AsFloat[idx] << " output: " << outputAsInt[idx]<< " expected output: " << expectedOutputAsInt[idx] << TestLog::EndMessage;
cases.push_back(OpFUnordCase(#NAME, OPCODE, compare_##NAME::compare)); \
} while (deGetFalse())
-tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
+tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx, const bool testWithNan)
{
- de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opfunord", "Test the OpFUnord* opcodes"));
+ const string nan = testWithNan ? "_nan" : "";
+ const string groupName = "opfunord" + nan;
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, groupName.c_str(), "Test the OpFUnord* opcodes"));
de::Random rnd (deStringHash(group->getName()));
const int numElements = 100;
vector<OpFUnordCase> cases;
-
+ string extensions = testWithNan ? "OpExtension \"SPV_KHR_float_controls\"\n" : "";
+ string capabilities = testWithNan ? "OpCapability SignedZeroInfNanPreserve\n" : "";
+ string exeModes = testWithNan ? "OpExecutionMode %main SignedZeroInfNanPreserve 32\n" : "";
const StringTemplate shaderTemplate (
-
- string(getComputeAsmShaderPreamble()) +
-
+ string(getComputeAsmShaderPreamble(capabilities, extensions, exeModes)) +
"OpSource GLSL 430\n"
"OpName %main \"main\"\n"
"OpName %id \"gl_GlobalInvocationID\"\n"
spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
spec.outputs.push_back(BufferSp(new Int32Buffer(expectedInts)));
- spec.numWorkGroups = IVec3(numElements, 1, 1);
- spec.verifyIO = &compareFUnord;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.verifyIO = testWithNan ? &compareFUnord<true> : &compareFUnord<false>;
+
+ if (testWithNan)
+ {
+ spec.extensions.push_back("VK_KHR_shader_float_controls");
+ spec.requestedVulkanFeatures.floatControlsProperties.shaderSignedZeroInfNanPreserveFloat32 = DE_TRUE;
+ }
+
group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
}
"%id = OpVariable %uvec3ptr Input\n"
"%zero = OpConstant %i32 0\n"
- "%float_0 = OpConstant %f16 0.0\n"
- "%float_1 = OpConstant %f16 1.0\n"
- "%float_n1 = OpConstant %f16 -1.0\n"
+ "%float_0 = OpConstant %f32 0.0\n"
+ "%float_1 = OpConstant %f32 1.0\n"
+ "%float_n1 = OpConstant %f32 -1.0\n"
"%main = OpFunction %void None %voidf\n"
"%entry = OpLabel\n"
"%x = OpCompositeExtract %u32 %idval 0\n"
"%inloc = OpAccessChain %f16ptr %indata %zero %x\n"
"%inval = OpLoad %f16 %inloc\n"
+ "%f32_inval = OpFConvert %f32 %inval\n"
- "%comp = OpFOrdGreaterThan %bool %inval %float_0\n"
+ "%comp = OpFOrdGreaterThan %bool %f32_inval %float_0\n"
" OpSelectionMerge %cm None\n"
" OpBranchConditional %comp %tb %fb\n"
"%tb = OpLabel\n"
"%fb = OpLabel\n"
" OpBranch %cm\n"
"%cm = OpLabel\n"
- "%res = OpPhi %f16 %float_1 %tb %float_n1 %fb\n"
+ "%res = OpPhi %f32 %float_1 %tb %float_n1 %fb\n"
+ "%f16_res = OpFConvert %f16 %res\n"
"%outloc = OpAccessChain %f16ptr %outdata %zero %x\n"
- " OpStore %outloc %res\n"
+ " OpStore %outloc %f16_res\n"
" OpReturn\n"
" OpFunctionEnd\n";
cases.push_back(CaseParameter("none", "None"));
cases.push_back(CaseParameter("unroll", "Unroll"));
cases.push_back(CaseParameter("dont_unroll", "DontUnroll"));
- cases.push_back(CaseParameter("unroll_dont_unroll", "Unroll|DontUnroll"));
fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
return group.release();
}
-tcu::TestCaseGroup* createOpNameGroup(tcu::TestContext& testCtx)
+void getOpNameAbuseCases (vector<CaseParameter> &abuseCases)
+{
+ // Generate a long name.
+ std::string longname;
+ longname.resize(65535, 'k'); // max string literal, spir-v 2.17
+
+ // Some bad names, abusing utf-8 encoding. This may also cause problems
+ // with the logs.
+ // 1. Various illegal code points in utf-8
+ std::string utf8illegal =
+ "Illegal bytes in UTF-8: "
+ "\xc0 \xc1 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff"
+ "illegal surrogates: \xed\xad\xbf \xed\xbe\x80";
+
+ // 2. Zero encoded as overlong, not exactly legal but often supported to differentiate from terminating zero
+ std::string utf8nul = "UTF-8 encoded nul \xC0\x80 (should not end name)";
+
+ // 3. Some overlong encodings
+ std::string utf8overlong =
+ "UTF-8 overlong \xF0\x82\x82\xAC \xfc\x83\xbf\xbf\xbf\xbf \xf8\x87\xbf\xbf\xbf "
+ "\xf0\x8f\xbf\xbf";
+
+ // 4. Internet "zalgo" meme "bleeding text"
+ std::string utf8zalgo =
+ "\x56\xcc\xb5\xcc\x85\xcc\x94\xcc\x88\xcd\x8a\xcc\x91\xcc\x88\xcd\x91\xcc\x83\xcd\x82"
+ "\xcc\x83\xcd\x90\xcc\x8a\xcc\x92\xcc\x92\xcd\x8b\xcc\x94\xcd\x9d\xcc\x98\xcc\xab\xcc"
+ "\xae\xcc\xa9\xcc\xad\xcc\x97\xcc\xb0\x75\xcc\xb6\xcc\xbe\xcc\x80\xcc\x82\xcc\x84\xcd"
+ "\x84\xcc\x90\xcd\x86\xcc\x9a\xcd\x84\xcc\x9b\xcd\x86\xcd\x92\xcc\x9a\xcd\x99\xcd\x99"
+ "\xcc\xbb\xcc\x98\xcd\x8e\xcd\x88\xcd\x9a\xcc\xa6\xcc\x9c\xcc\xab\xcc\x99\xcd\x94\xcd"
+ "\x99\xcd\x95\xcc\xa5\xcc\xab\xcd\x89\x6c\xcc\xb8\xcc\x8e\xcc\x8b\xcc\x8b\xcc\x9a\xcc"
+ "\x8e\xcd\x9d\xcc\x80\xcc\xa1\xcc\xad\xcd\x9c\xcc\xba\xcc\x96\xcc\xb3\xcc\xa2\xcd\x8e"
+ "\xcc\xa2\xcd\x96\x6b\xcc\xb8\xcc\x84\xcd\x81\xcc\xbf\xcc\x8d\xcc\x89\xcc\x85\xcc\x92"
+ "\xcc\x84\xcc\x90\xcd\x81\xcc\x93\xcd\x90\xcd\x92\xcd\x9d\xcc\x84\xcd\x98\xcd\x9d\xcd"
+ "\xa0\xcd\x91\xcc\x94\xcc\xb9\xcd\x93\xcc\xa5\xcd\x87\xcc\xad\xcc\xa7\xcd\x96\xcd\x99"
+ "\xcc\x9d\xcc\xbc\xcd\x96\xcd\x93\xcc\x9d\xcc\x99\xcc\xa8\xcc\xb1\xcd\x85\xcc\xba\xcc"
+ "\xa7\x61\xcc\xb8\xcc\x8e\xcc\x81\xcd\x90\xcd\x84\xcd\x8c\xcc\x8c\xcc\x85\xcd\x86\xcc"
+ "\x84\xcd\x84\xcc\x90\xcc\x84\xcc\x8d\xcd\x99\xcd\x8d\xcc\xb0\xcc\xa3\xcc\xa6\xcd\x89"
+ "\xcd\x8d\xcd\x87\xcc\x98\xcd\x8d\xcc\xa4\xcd\x9a\xcd\x8e\xcc\xab\xcc\xb9\xcc\xac\xcc"
+ "\xa2\xcd\x87\xcc\xa0\xcc\xb3\xcd\x89\xcc\xb9\xcc\xa7\xcc\xa6\xcd\x89\xcd\x95\x6e\xcc"
+ "\xb8\xcd\x8a\xcc\x8a\xcd\x82\xcc\x9b\xcd\x81\xcd\x90\xcc\x85\xcc\x9b\xcd\x80\xcd\x91"
+ "\xcd\x9b\xcc\x81\xcd\x81\xcc\x9a\xcc\xb3\xcd\x9c\xcc\x9e\xcc\x9d\xcd\x99\xcc\xa2\xcd"
+ "\x93\xcd\x96\xcc\x97\xff";
+
+ // General name abuses
+ abuseCases.push_back(CaseParameter("_has_very_long_name", longname));
+ abuseCases.push_back(CaseParameter("_utf8_illegal", utf8illegal));
+ abuseCases.push_back(CaseParameter("_utf8_nul", utf8nul));
+ abuseCases.push_back(CaseParameter("_utf8_overlong", utf8overlong));
+ abuseCases.push_back(CaseParameter("_utf8_zalgo", utf8zalgo));
+
+ // GL keywords
+ abuseCases.push_back(CaseParameter("_is_gl_Position", "gl_Position"));
+ abuseCases.push_back(CaseParameter("_is_gl_InstanceID", "gl_InstanceID"));
+ abuseCases.push_back(CaseParameter("_is_gl_PrimitiveID", "gl_PrimitiveID"));
+ abuseCases.push_back(CaseParameter("_is_gl_TessCoord", "gl_TessCoord"));
+ abuseCases.push_back(CaseParameter("_is_gl_PerVertex", "gl_PerVertex"));
+ abuseCases.push_back(CaseParameter("_is_gl_InvocationID", "gl_InvocationID"));
+ abuseCases.push_back(CaseParameter("_is_gl_PointSize", "gl_PointSize"));
+ abuseCases.push_back(CaseParameter("_is_gl_PointCoord", "gl_PointCoord"));
+ abuseCases.push_back(CaseParameter("_is_gl_Layer", "gl_Layer"));
+ abuseCases.push_back(CaseParameter("_is_gl_FragDepth", "gl_FragDepth"));
+ abuseCases.push_back(CaseParameter("_is_gl_NumWorkGroups", "gl_NumWorkGroups"));
+ abuseCases.push_back(CaseParameter("_is_gl_WorkGroupID", "gl_WorkGroupID"));
+ abuseCases.push_back(CaseParameter("_is_gl_LocalInvocationID", "gl_LocalInvocationID"));
+ abuseCases.push_back(CaseParameter("_is_gl_GlobalInvocationID", "gl_GlobalInvocationID"));
+ abuseCases.push_back(CaseParameter("_is_gl_MaxVertexAttribs", "gl_MaxVertexAttribs"));
+ abuseCases.push_back(CaseParameter("_is_gl_MaxViewports", "gl_MaxViewports"));
+ abuseCases.push_back(CaseParameter("_is_gl_MaxComputeWorkGroupCount", "gl_MaxComputeWorkGroupCount"));
+ abuseCases.push_back(CaseParameter("_is_mat3", "mat3"));
+ abuseCases.push_back(CaseParameter("_is_volatile", "volatile"));
+ abuseCases.push_back(CaseParameter("_is_inout", "inout"));
+ abuseCases.push_back(CaseParameter("_is_isampler3d", "isampler3d"));
+}
+
+tcu::TestCaseGroup* createOpNameGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opname", "Tests OpName cases"));
de::MovePtr<tcu::TestCaseGroup> entryMainGroup (new tcu::TestCaseGroup(testCtx, "entry_main", "OpName tests with entry main"));
de::MovePtr<tcu::TestCaseGroup> entryNotGroup (new tcu::TestCaseGroup(testCtx, "entry_rdc", "OpName tests with entry rdc"));
+ de::MovePtr<tcu::TestCaseGroup> abuseGroup (new tcu::TestCaseGroup(testCtx, "abuse", "OpName abuse tests"));
vector<CaseParameter> cases;
+ vector<CaseParameter> abuseCases;
vector<string> testFunc;
de::Random rnd (deStringHash(group->getName()));
- const int numElements = 100;
+ const int numElements = 128;
vector<float> inputFloats (numElements, 0);
vector<float> outputFloats (numElements, 0);
+ getOpNameAbuseCases(abuseCases);
+
fillRandomScalars(rnd, -100.0f, 100.0f, &inputFloats[0], numElements);
for(size_t ndx = 0; ndx < numElements; ++ndx)
outputFloats[ndx] = -inputFloats[ndx];
- const StringTemplate shaderTemplate (
+ const string commonShaderHeader =
"OpCapability Shader\n"
"OpMemoryModel Logical GLSL450\n"
- "OpEntryPoint GLCompute %main \"${ENTRY}\" %id\n"
- "OpExecutionMode %main LocalSize 1 1 1\n"
-
- "OpName %${FUNC_ID} \"${NAME}\"\n"
+ "OpEntryPoint GLCompute %main \"main\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n";
+ const string commonShaderFooter =
"OpDecorate %id BuiltIn GlobalInvocationId\n"
+ string(getComputeAsmInputOutputBufferTraits())
-
+ string(getComputeAsmCommonTypes())
-
+ string(getComputeAsmInputOutputBuffer()) +
"%id = OpVariable %uvec3ptr Input\n"
"%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
" OpStore %outloc %neg\n"
-
" OpReturn\n"
- " OpFunctionEnd\n");
+ " OpFunctionEnd\n";
+
+ const StringTemplate shaderTemplate (
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint GLCompute %main \"${ENTRY}\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n"
+ "OpName %${ID} \"${NAME}\"\n" +
+ commonShaderFooter);
+
+ const std::string multipleNames =
+ commonShaderHeader +
+ "OpName %main \"to_be\"\n"
+ "OpName %id \"or_not\"\n"
+ "OpName %main \"to_be\"\n"
+ "OpName %main \"makes_no\"\n"
+ "OpName %func \"difference\"\n"
+ "OpName %5 \"to_me\"\n" +
+ commonShaderFooter;
+
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly = multipleNames;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "main_has_multiple_names", "multiple_names", spec));
+ }
+
+ const std::string everythingNamed =
+ commonShaderHeader +
+ "OpName %main \"name1\"\n"
+ "OpName %id \"name2\"\n"
+ "OpName %zero \"name3\"\n"
+ "OpName %entry \"name4\"\n"
+ "OpName %func \"name5\"\n"
+ "OpName %5 \"name6\"\n"
+ "OpName %7 \"name7\"\n"
+ "OpName %idval \"name8\"\n"
+ "OpName %inloc \"name9\"\n"
+ "OpName %inval \"name10\"\n"
+ "OpName %neg \"name11\"\n"
+ "OpName %outloc \"name12\"\n"+
+ commonShaderFooter;
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly = everythingNamed;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named", "everything_named", spec));
+ }
+
+ const std::string everythingNamedTheSame =
+ commonShaderHeader +
+ "OpName %main \"the_same\"\n"
+ "OpName %id \"the_same\"\n"
+ "OpName %zero \"the_same\"\n"
+ "OpName %entry \"the_same\"\n"
+ "OpName %func \"the_same\"\n"
+ "OpName %5 \"the_same\"\n"
+ "OpName %7 \"the_same\"\n"
+ "OpName %idval \"the_same\"\n"
+ "OpName %inloc \"the_same\"\n"
+ "OpName %inval \"the_same\"\n"
+ "OpName %neg \"the_same\"\n"
+ "OpName %outloc \"the_same\"\n"+
+ commonShaderFooter;
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly = everythingNamedTheSame;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named_the_same", "everything_named_the_same", spec));
+ }
+
+ // main_is_...
+ for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["ENTRY"] = "main";
+ specializations["ID"] = "main";
+ specializations["NAME"] = abuseCases[ndx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("main") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+ }
+
+ // x_is_....
+ for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["ENTRY"] = "main";
+ specializations["ID"] = "x";
+ specializations["NAME"] = abuseCases[ndx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("x") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+ }
cases.push_back(CaseParameter("_is_main", "main"));
cases.push_back(CaseParameter("_is_not_main", "not_main"));
-
testFunc.push_back("main");
testFunc.push_back("func");
{
for(size_t ndx = 0; ndx < cases.size(); ++ndx)
{
- map<string, string> specializations;
- ComputeShaderSpec spec;
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
- specializations["ENTRY"] = "main";
- specializations["FUNC_ID"] = testFunc[fNdx];
- specializations["NAME"] = cases[ndx].param;
- spec.assembly = shaderTemplate.specialize(specializations);
- spec.numWorkGroups = IVec3(numElements, 1, 1);
+ specializations["ENTRY"] = "main";
+ specializations["ID"] = testFunc[fNdx];
+ specializations["NAME"] = cases[ndx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
map<string, string> specializations;
ComputeShaderSpec spec;
- specializations["ENTRY"] = "rdc";
- specializations["FUNC_ID"] = testFunc[fNdx];
- specializations["NAME"] = cases[ndx].param;
- spec.assembly = shaderTemplate.specialize(specializations);
- spec.numWorkGroups = IVec3(numElements, 1, 1);
+ specializations["ENTRY"] = "rdc";
+ specializations["ID"] = testFunc[fNdx];
+ specializations["NAME"] = cases[ndx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.entryPoint = "rdc";
spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
- spec.entryPoint = "rdc";
entryNotGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (testFunc[fNdx] + cases[ndx].name).c_str(), cases[ndx].name, spec));
}
group->addChild(entryMainGroup.release());
group->addChild(entryNotGroup.release());
+ group->addChild(abuseGroup.release());
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpMemberNameGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "opmembername", "Tests OpMemberName cases"));
+ de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "abuse", "OpMemberName abuse tests"));
+ vector<CaseParameter> abuseCases;
+ vector<string> testFunc;
+ de::Random rnd(deStringHash(group->getName()));
+ const int numElements = 128;
+ vector<float> inputFloats(numElements, 0);
+ vector<float> outputFloats(numElements, 0);
+
+ getOpNameAbuseCases(abuseCases);
+
+ fillRandomScalars(rnd, -100.0f, 100.0f, &inputFloats[0], numElements);
+
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputFloats[ndx] = -inputFloats[ndx];
+
+ const string commonShaderHeader =
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint GLCompute %main \"main\" %id\n"
+ "OpExecutionMode %main LocalSize 1 1 1\n";
+
+ const string commonShaderFooter =
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(getComputeAsmInputOutputBufferTraits())
+ + string(getComputeAsmCommonTypes())
+ + string(getComputeAsmInputOutputBuffer()) +
+
+ "%u3str = OpTypeStruct %u32 %u32 %u32\n"
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "%zero = OpConstant %i32 0\n"
+
+ "%main = OpFunction %void None %voidf\n"
+ "%entry = OpLabel\n"
+
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x0 = OpCompositeExtract %u32 %idval 0\n"
+
+ "%idstr = OpCompositeConstruct %u3str %x0 %x0 %x0\n"
+ "%x = OpCompositeExtract %u32 %idstr 0\n"
+
+ "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
+ "%inval = OpLoad %f32 %inloc\n"
+ "%neg = OpFNegate %f32 %inval\n"
+ "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
+ " OpStore %outloc %neg\n"
+
+ " OpReturn\n"
+ " OpFunctionEnd\n";
+
+ const StringTemplate shaderTemplate(
+ commonShaderHeader +
+ "OpMemberName %u3str 0 \"${NAME}\"\n" +
+ commonShaderFooter);
+
+ const std::string multipleNames =
+ commonShaderHeader +
+ "OpMemberName %u3str 0 \"to_be\"\n"
+ "OpMemberName %u3str 1 \"or_not\"\n"
+ "OpMemberName %u3str 0 \"to_be\"\n"
+ "OpMemberName %u3str 2 \"makes_no\"\n"
+ "OpMemberName %u3str 0 \"difference\"\n"
+ "OpMemberName %u3str 0 \"to_me\"\n" +
+ commonShaderFooter;
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly = multipleNames;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "u3str_x_has_multiple_names", "multiple_names", spec));
+ }
+
+ const std::string everythingNamedTheSame =
+ commonShaderHeader +
+ "OpMemberName %u3str 0 \"the_same\"\n"
+ "OpMemberName %u3str 1 \"the_same\"\n"
+ "OpMemberName %u3str 2 \"the_same\"\n" +
+ commonShaderFooter;
+
+ {
+ ComputeShaderSpec spec;
+
+ spec.assembly = everythingNamedTheSame;
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "everything_named_the_same", "everything_named_the_same", spec));
+ }
+
+ // u3str_x_is_....
+ for (size_t ndx = 0; ndx < abuseCases.size(); ++ndx)
+ {
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ specializations["NAME"] = abuseCases[ndx].param;
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
+
+ abuseGroup->addChild(new SpvAsmComputeShaderCase(testCtx, (std::string("u3str_x") + abuseCases[ndx].name).c_str(), abuseCases[ndx].name, spec));
+ }
+
+ group->addChild(abuseGroup.release());
return group.release();
}
spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
spec.numWorkGroups = IVec3(numElements, 1, 1);
+
spec.extensions.push_back("VK_KHR_16bit_storage");
+ spec.extensions.push_back("VK_KHR_shader_float16_int8");
+
+ spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
+ spec.requestedVulkanFeatures.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
}
return group.release();
}
-// IEEE-754 floating point numbers:
-// +--------+------+----------+-------------+
-// | binary | sign | exponent | significand |
-// +--------+------+----------+-------------+
-// | 16-bit | 1 | 5 | 10 |
-// +--------+------+----------+-------------+
-// | 32-bit | 1 | 8 | 23 |
-// +--------+------+----------+-------------+
-//
-// 16-bit floats:
-//
-// 0 000 00 00 0000 0001 (0x0001: 2e-24: minimum positive denormalized)
-// 0 000 00 11 1111 1111 (0x03ff: 2e-14 - 2e-24: maximum positive denormalized)
-// 0 000 01 00 0000 0000 (0x0400: 2e-14: minimum positive normalized)
-//
-// 0 000 00 00 0000 0000 (0x0000: +0)
-// 0 111 11 00 0000 0000 (0x7c00: +Inf)
-// 0 000 00 11 1111 0000 (0x03f0: +Denorm)
-// 0 000 01 00 0000 0001 (0x0401: +Norm)
-// 0 111 11 00 0000 1111 (0x7c0f: +SNaN)
-// 0 111 11 11 1111 0000 (0x7ff0: +QNaN)
-
-// Generate and return 16-bit floats and their corresponding 32-bit values.
-//
-// The first 14 number pairs are manually picked, while the rest are randomly generated.
-// Expected count to be at least 14 (numPicks).
-vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count)
+const vector<deFloat16> squarize(const vector<deFloat16>& inData, const deUint32 argNo)
{
- vector<deFloat16> float16;
+ const size_t inDataLength = inData.size();
+ vector<deFloat16> result;
- float16.reserve(count);
+ result.reserve(inDataLength * inDataLength);
- // Zero
- float16.push_back(deUint16(0x0000));
- float16.push_back(deUint16(0x8000));
- // Infinity
- float16.push_back(deUint16(0x7c00));
- float16.push_back(deUint16(0xfc00));
- // SNaN
- float16.push_back(deUint16(0x7c0f));
- float16.push_back(deUint16(0xfc0f));
- // QNaN
- float16.push_back(deUint16(0x7ff0));
- float16.push_back(deUint16(0xfff0));
-
- // Denormalized
- float16.push_back(deUint16(0x03f0));
- float16.push_back(deUint16(0x83f0));
- // Normalized
- float16.push_back(deUint16(0x0401));
- float16.push_back(deUint16(0x8401));
- // Some normal number
- float16.push_back(deUint16(0x14cb));
- float16.push_back(deUint16(0x94cb));
-
- const deUint32 numPicks = static_cast<deUint32>(float16.size());
-
- DE_ASSERT(count >= numPicks);
- count -= numPicks;
-
- for (deUint32 numIdx = 0; numIdx < count; ++numIdx)
- float16.push_back(rnd.getUint16());
-
- return float16;
-}
-
-const vector<deFloat16> squarize(const vector<deFloat16>& inData, const deUint32 argNo)
-{
- const size_t inDataLength = inData.size();
- vector<deFloat16> result;
-
- result.reserve(inDataLength * inDataLength);
-
- if (argNo == 0)
- {
- for (size_t numIdx = 0; numIdx < inDataLength; ++numIdx)
- result.insert(result.end(), inData.begin(), inData.end());
- }
+ if (argNo == 0)
+ {
+ for (size_t numIdx = 0; numIdx < inDataLength; ++numIdx)
+ result.insert(result.end(), inData.begin(), inData.end());
+ }
if (argNo == 1)
{
map<string, string> specializations;
map<string, string> fragments;
SpecConstants specConstants;
- vector<string> features;
PushConstants noPushConstants;
GraphicsResources noResources;
GraphicsInterfaces noInterfaces;
- std::vector<std::string> noExtensions;
+ vector<string> extensions;
+ VulkanFeatures requiredFeatures;
// Special SPIR-V code for SConvert-case
if (strcmp(cases[caseNdx].caseName, "sconvert") == 0)
{
- features.push_back("shaderInt16");
+ requiredFeatures.coreFeatures.shaderInt16 = VK_TRUE;
fragments["capability"] = "OpCapability Int16\n"; // Adds 16-bit integer capability
specializations["OPTYPE_DEFINITIONS"] = "%i16 = OpTypeInt 16 1\n"; // Adds 16-bit integer type
specializations["TYPE_CONVERT"] = "%sc_op32 = OpSConvert %i32 %sc_op\n"; // Converts 16-bit integer to 32-bit integer
// Special SPIR-V code for FConvert-case
if (strcmp(cases[caseNdx].caseName, "fconvert") == 0)
{
- features.push_back("shaderFloat64");
+ requiredFeatures.coreFeatures.shaderFloat64 = VK_TRUE;
fragments["capability"] = "OpCapability Float64\n"; // Adds 64-bit float capability
specializations["OPTYPE_DEFINITIONS"] = "%f64 = OpTypeFloat 64\n"; // Adds 64-bit float type
specializations["TYPE_CONVERT"] = "%sc_op32 = OpConvertFToS %i32 %sc_op\n"; // Converts 64-bit float to 32-bit integer
// Special SPIR-V code for FConvert-case for 16-bit floats
if (strcmp(cases[caseNdx].caseName, "fconvert16") == 0)
{
+ extensions.push_back("VK_KHR_shader_float16_int8");
+ requiredFeatures.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
fragments["capability"] = "OpCapability Float16\n"; // Adds 16-bit float capability
specializations["OPTYPE_DEFINITIONS"] = "%f16 = OpTypeFloat 16\n"; // Adds 16-bit float type
specializations["TYPE_CONVERT"] = "%sc_op32 = OpConvertFToS %i32 %sc_op\n"; // Converts 16-bit float to 32-bit integer
createTestsForAllStages(
cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants,
- noPushConstants, noResources, noInterfaces, noExtensions, features, VulkanFeatures(), group.get());
+ noPushConstants, noResources, noInterfaces, extensions, requiredFeatures, group.get());
}
const char decorations2[] =
RGBA invertedColors[4];
de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders"));
- const ShaderElement combinedPipeline[] =
- {
- ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
- };
-
getDefaultColors(defaultColors);
getInvertedDefaultColors(invertedColors);
- addFunctionCaseWithPrograms<InstanceContext>(
- moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
- createInstanceContext(combinedPipeline, map<string, string>()));
+
+ // Combined module tests
+ {
+ // Shader stages: vertex and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, geometry and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, tessellation control, tessellation evaluation and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_tessc_tesse", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, tessellation control, tessellation evaluation, geometry and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_tessc_tesse_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+ }
const char* numbers[] =
{
return moduleTests.release();
}
+std::string getUnusedVarTestNamePiece(const std::string& prefix, ShaderTask task)
+{
+ switch (task)
+ {
+ case SHADER_TASK_NONE: return "";
+ case SHADER_TASK_NORMAL: return prefix + "_normal";
+ case SHADER_TASK_UNUSED_VAR: return prefix + "_unused_var";
+ case SHADER_TASK_UNUSED_FUNC: return prefix + "_unused_func";
+ default: DE_ASSERT(DE_FALSE);
+ }
+ // unreachable
+ return "";
+}
+
+std::string getShaderTaskIndexName(ShaderTaskIndex index)
+{
+ switch (index)
+ {
+ case SHADER_TASK_INDEX_VERTEX: return "vertex";
+ case SHADER_TASK_INDEX_GEOMETRY: return "geom";
+ case SHADER_TASK_INDEX_TESS_CONTROL: return "tessc";
+ case SHADER_TASK_INDEX_TESS_EVAL: return "tesse";
+ case SHADER_TASK_INDEX_FRAGMENT: return "frag";
+ default: DE_ASSERT(DE_FALSE);
+ }
+ // unreachable
+ return "";
+}
+
+std::string getUnusedVarTestName(const ShaderTaskArray& shaderTasks, const VariableLocation& location)
+{
+ std::string testName = location.toString();
+
+ for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(shaderTasks); ++i)
+ {
+ if (shaderTasks[i] != SHADER_TASK_NONE)
+ {
+ testName += "_" + getUnusedVarTestNamePiece(getShaderTaskIndexName((ShaderTaskIndex)i), shaderTasks[i]);
+ }
+ }
+
+ return testName;
+}
+
+tcu::TestCaseGroup* createUnusedVariableTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "unused_variables", "Graphics shaders with unused variables"));
+
+ ShaderTaskArray shaderCombinations[] =
+ {
+ // Vertex Geometry Tess. Control Tess. Evaluation Fragment
+ { SHADER_TASK_UNUSED_VAR, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NORMAL },
+ { SHADER_TASK_UNUSED_FUNC, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_UNUSED_VAR },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_UNUSED_FUNC },
+ { SHADER_TASK_NORMAL, SHADER_TASK_UNUSED_VAR, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_UNUSED_FUNC, SHADER_TASK_NONE, SHADER_TASK_NONE, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_UNUSED_VAR, SHADER_TASK_NORMAL, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_UNUSED_FUNC, SHADER_TASK_NORMAL, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_NORMAL, SHADER_TASK_UNUSED_VAR, SHADER_TASK_NORMAL },
+ { SHADER_TASK_NORMAL, SHADER_TASK_NONE, SHADER_TASK_NORMAL, SHADER_TASK_UNUSED_FUNC, SHADER_TASK_NORMAL }
+ };
+
+ const VariableLocation testLocations[] =
+ {
+ // Set Binding
+ { 0, 5 },
+ { 5, 5 },
+ };
+
+ for (size_t combNdx = 0; combNdx < DE_LENGTH_OF_ARRAY(shaderCombinations); ++combNdx)
+ {
+ for (size_t locationNdx = 0; locationNdx < DE_LENGTH_OF_ARRAY(testLocations); ++locationNdx)
+ {
+ const ShaderTaskArray& shaderTasks = shaderCombinations[combNdx];
+ const VariableLocation& location = testLocations[locationNdx];
+ std::string testName = getUnusedVarTestName(shaderTasks, location);
+
+ addFunctionCaseWithPrograms<UnusedVariableContext>(
+ moduleTests.get(), testName, "", createUnusedVariableModules, runAndVerifyUnusedVariablePipeline,
+ createUnusedVariableContext(shaderTasks, location));
+ }
+ }
+
+ return moduleTests.release();
+}
+
tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "loop", "Looping control flow"));
"%then = OpLabel\n"
"OpControlBarrier %Workgroup %Workgroup %WorkgroupAcquireRelease\n"
"OpBranch %exit\n"
-
"%exit = OpLabel\n"
"%ret = OpPhi %v4f32 %param1 %then %wrong_branch_alert %else\n"
"OpReturnValue %ret\n"
if (instruction == "OpUConvert" || instruction == "OpSConvert" || instruction == "OpFConvert")
{
- // Conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Int16
+ // Width-only conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Int16
if (usesInt32(from, to) || usesFloat32(from, to))
requiresInt16Capability = false;
}
{
decl += "%f16 = OpTypeFloat 16\n";
- // Conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Float16
- if (!(usesInt32(from, to) || usesFloat32(from, to)))
+ // Width-only conversions between 16 and 32 bit are provided by SPV_KHR_16bit_storage. The rest requires explicit Float16
+ if (!usesFloat32(from, to))
caps += "OpCapability Float16\n";
}
if (usesInt16(from, to) || usesFloat16(from, to))
{
- caps += "OpCapability StorageUniformBufferBlock16\n"
- "OpCapability StorageUniform16\n";
+ caps += "OpCapability StorageUniformBufferBlock16\n";
exts += "OpExtension \"SPV_KHR_16bit_storage\"\n";
}
testCases.push_back(ConvertCase(instruction, DATA_TYPE_FLOAT_64, DATA_TYPE_SIGNED_16, 0xc093480000000000, true, -1234));
testCases.push_back(ConvertCase(instruction, DATA_TYPE_FLOAT_64, DATA_TYPE_SIGNED_32, 0xc093480000000000, true, -1234));
testCases.push_back(ConvertCase(instruction, DATA_TYPE_FLOAT_64, DATA_TYPE_SIGNED_64, 0xc093480000000000, true, -1234));
+ testCases.push_back(ConvertCase(instruction, DATA_TYPE_FLOAT_32, DATA_TYPE_SIGNED_16, 0x453b9000, true, 3001, "p3001"));
+ testCases.push_back(ConvertCase(instruction, DATA_TYPE_FLOAT_32, DATA_TYPE_SIGNED_16, 0xc53b9000, true, -3001, "m3001"));
}
else if (instruction == "OpConvertSToF")
{
for (vector<ConvertCase>::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
{
map<string, string> fragments = getConvertCaseFragments(instruction, *test);
- vector<string> features;
VulkanFeatures vulkanFeatures;
GraphicsResources resources;
vector<string> extensions;
getVulkanFeaturesAndExtensions(test->m_fromType, test->m_toType, vulkanFeatures, extensions);
+ vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = true;
+ vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = true;
+
createTestsForAllStages(
test->m_name, defaultColors, defaultColors, fragments, noSpecConstants,
- noPushConstants, resources, noInterfaces, extensions, features, vulkanFeatures, group.get());
+ noPushConstants, resources, noInterfaces, extensions, vulkanFeatures, group.get());
}
return group.release();
}
extensions.push_back("VK_KHR_16bit_storage");
extensions.push_back("VK_KHR_shader_float16_int8");
+ features.extFloat16Int8 = EXTFLOAT16INT8FEATURES_FLOAT16;
for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
{
de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, groupName.c_str(), "Float 16 logical tests"));
de::Random rnd (deStringHash(testGroup->getName()));
- const StringTemplate capabilities ("OpCapability ${cap}\n");
+ const string spvCapabilities = string("OpCapability StorageUniformBufferBlock16\n") + (nanSupported ? "OpCapability SignedZeroInfNanPreserve\n" : "");
+ const string spvExtensions = string("OpExtension \"SPV_KHR_16bit_storage\"\n") + (nanSupported ? "OpExtension \"SPV_KHR_float_controls\"\n" : "");
+ const string spvExecutionMode = nanSupported ? "OpExecutionMode %BP_main SignedZeroInfNanPreserve 16\n" : "";
const deUint32 numDataPoints = 16;
const vector<deFloat16> float16Data = getFloat16s(rnd, numDataPoints);
const vector<deFloat16> float16Data1 = squarize(float16Data, 0);
map<string, string> fragments;
vector<string> extensions;
- specs["cap"] = "StorageUniformBufferBlock16";
specs["num_data_points"] = de::toString(iterations);
specs["op_code"] = testOp.opCode;
specs["op_arg1"] = (testOp.argCount == 1) ? "" : "%val_src1";
specs["op_arg1_calc"] = (testOp.argCount == 1) ? "" : arg1Calc.specialize(specs);
- fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
- fragments["capability"] = capabilities.specialize(specs);
+ fragments["extension"] = spvExtensions;
+ fragments["capability"] = spvCapabilities;
+ fragments["execution_mode"] = spvExecutionMode;
fragments["decoration"] = decoration.specialize(specs);
fragments["pre_main"] = preMain.specialize(specs);
fragments["testfun"] = testFun.specialize(specs);
VulkanFeatures features;
map<string, string> fragments;
- specs["cap"] = "StorageUniformBufferBlock16";
specs["num_data_points"] = de::toString(iterations);
specs["op_code"] = testOp.opCode;
specs["op_arg1"] = (testOp.argCount == 1) ? "" : "%val_src1";
specs["op_arg1_calc"] = (testOp.argCount == 1) ? "" : arg1Calc.specialize(specs);
- fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
- fragments["capability"] = capabilities.specialize(specs);
+ fragments["extension"] = spvExtensions;
+ fragments["capability"] = spvCapabilities;
+ fragments["execution_mode"] = spvExecutionMode;
fragments["decoration"] = decoration.specialize(specs);
fragments["pre_main"] = preMain.specialize(specs);
fragments["testfun"] = testFun.specialize(specs);
SpecConstants noSpecConstants;
PushConstants noPushConstants;
GraphicsInterfaces noInterfaces;
- vector<string> noFeatures;
specs["op_code"] = testOp.opCode;
specs["num_data_points"] = de::toString(testOp.inputData.size() / N);
specs["type_decls"] = testType.typeDecls;
fragments["extension"] = "OpExtension \"SPV_KHR_16bit_storage\"";
- fragments["capability"] = "OpCapability DerivativeControl\nOpCapability StorageUniformBufferBlock16\n";
+ 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);
features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, testName.c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
- noPushConstants, specResource, noInterfaces, extensions, noFeatures, features, testGroup.get(), QP_TEST_RESULT_FAIL, string(), true);
+ noPushConstants, specResource, noInterfaces, extensions, features, testGroup.get(), QP_TEST_RESULT_FAIL, string(), true);
}
return testGroup.release();
tcu::TestCaseGroup* createOpNameTests (tcu::TestContext& testCtx)
{
- de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "opname","Test OpName"));
+ de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "opname","Test OpName"));
RGBA defaultColors[4];
map<string, string> opNameFragments;
getDefaultColors(defaultColors);
- opNameFragments["debug"] =
- "OpName %BP_main \"not_main\"";
-
- opNameFragments["testfun"] =
- "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
- "%param1 = OpFunctionParameter %v4f32\n"
+ opNameFragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
"%label_func = OpLabel\n"
- "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
- "%b = OpFAdd %f32 %a %a\n"
- "%c = OpFSub %f32 %b %a\n"
- "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %a\n"
+ "%c = OpFSub %f32 %b %a\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
"OpReturnValue %ret\n"
"OpFunctionEnd\n";
+ opNameFragments["debug"] =
+ "OpName %BP_main \"not_main\"";
+
createTestsForAllStages("opname", defaultColors, defaultColors, opNameFragments, testGroup.get());
return testGroup.release();
de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "float16", "Float 16 tests"));
testGroup->addChild(createOpConstantFloat16Tests(testCtx));
+ 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));
de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "float16", "Float 16 tests"));
testGroup->addChild(createFloat16OpConstantCompositeGroup(testCtx));
+ testGroup->addChild(createFloat16LogicalSet<ComputeShaderSpec>(testCtx, TEST_WITH_NAN));
testGroup->addChild(createFloat16LogicalSet<ComputeShaderSpec>(testCtx, TEST_WITHOUT_NAN));
testGroup->addChild(createFloat16FuncSet<ComputeShaderSpec>(testCtx));
testGroup->addChild(createFloat16VectorExtractSet<ComputeShaderSpec>(testCtx));
return testGroup.release();
}
+tcu::TestCaseGroup* createBoolMixedBitSizeGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "mixed_bitsize", "Tests boolean operands produced from instructions of different bit-sizes"));
+
+ de::Random rnd (deStringHash(group->getName()));
+ const int numElements = 100;
+ vector<float> inputData (numElements, 0);
+ vector<float> outputData (numElements, 0);
+ fillRandomScalars(rnd, 0.0f, 100.0f, &inputData[0], 100);
+
+ const StringTemplate shaderTemplate (
+ "${CAPS}\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"
+
+ "OpDecorate %id BuiltIn GlobalInvocationId\n"
+
+ + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
+
+ "%id = OpVariable %uvec3ptr Input\n"
+ "${CONST}\n"
+ "%main = OpFunction %void None %voidf\n"
+ "%label = OpLabel\n"
+ "%idval = OpLoad %uvec3 %id\n"
+ "%x = OpCompositeExtract %u32 %idval 0\n"
+ "%inloc = OpAccessChain %f32ptr %indata %c0i32 %x\n"
+
+ "${TEST}\n"
+
+ "%outloc = OpAccessChain %f32ptr %outdata %c0i32 %x\n"
+ " OpStore %outloc %res\n"
+ " OpReturn\n"
+ " OpFunctionEnd\n"
+ );
+
+ // Each test case produces 4 boolean values, and we want each of these values
+ // to come froma different combination of the available bit-sizes, so compute
+ // all possible combinations here.
+ vector<deUint32> widths;
+ widths.push_back(32);
+ widths.push_back(16);
+ widths.push_back(8);
+
+ vector<IVec4> cases;
+ for (size_t width0 = 0; width0 < widths.size(); width0++)
+ {
+ for (size_t width1 = 0; width1 < widths.size(); width1++)
+ {
+ for (size_t width2 = 0; width2 < widths.size(); width2++)
+ {
+ for (size_t width3 = 0; width3 < widths.size(); width3++)
+ {
+ cases.push_back(IVec4(widths[width0], widths[width1], widths[width2], widths[width3]));
+ }
+ }
+ }
+ }
+
+ for (size_t caseNdx = 0; caseNdx < cases.size(); caseNdx++)
+ {
+ /// Skip cases where all bitsizes are the same, we are only interested in testing booleans produced from instructions with different native bit-sizes
+ if (cases[caseNdx][0] == cases[caseNdx][1] && cases[caseNdx][0] == cases[caseNdx][2] && cases[caseNdx][0] == cases[caseNdx][3])
+ continue;
+
+ map<string, string> specializations;
+ ComputeShaderSpec spec;
+
+ // Inject appropriate capabilities and reference constants depending
+ // on the bit-sizes required by this test case
+ bool hasFloat32 = cases[caseNdx][0] == 32 || cases[caseNdx][1] == 32 || cases[caseNdx][2] == 32 || cases[caseNdx][3] == 32;
+ bool hasFloat16 = cases[caseNdx][0] == 16 || cases[caseNdx][1] == 16 || cases[caseNdx][2] == 16 || cases[caseNdx][3] == 16;
+ bool hasInt8 = cases[caseNdx][0] == 8 || cases[caseNdx][1] == 8 || cases[caseNdx][2] == 8 || cases[caseNdx][3] == 8;
+
+ string capsStr = "OpCapability Shader\n";
+ string constStr =
+ "%c0i32 = OpConstant %i32 0\n"
+ "%c1f32 = OpConstant %f32 1.0\n"
+ "%c0f32 = OpConstant %f32 0.0\n";
+
+ if (hasFloat32)
+ {
+ constStr +=
+ "%c10f32 = OpConstant %f32 10.0\n"
+ "%c25f32 = OpConstant %f32 25.0\n"
+ "%c50f32 = OpConstant %f32 50.0\n"
+ "%c90f32 = OpConstant %f32 90.0\n";
+ }
+
+ if (hasFloat16)
+ {
+ capsStr += "OpCapability Float16\n";
+ constStr +=
+ "%f16 = OpTypeFloat 16\n"
+ "%c10f16 = OpConstant %f16 10.0\n"
+ "%c25f16 = OpConstant %f16 25.0\n"
+ "%c50f16 = OpConstant %f16 50.0\n"
+ "%c90f16 = OpConstant %f16 90.0\n";
+ }
+
+ if (hasInt8)
+ {
+ capsStr += "OpCapability Int8\n";
+ constStr +=
+ "%i8 = OpTypeInt 8 1\n"
+ "%c10i8 = OpConstant %i8 10\n"
+ "%c25i8 = OpConstant %i8 25\n"
+ "%c50i8 = OpConstant %i8 50\n"
+ "%c90i8 = OpConstant %i8 90\n";
+ }
+
+ // Each invocation reads a different float32 value as input. Depending on
+ // the bit-sizes required by the particular test case, we also produce
+ // float16 and/or and int8 values by converting from the 32-bit float.
+ string testStr = "";
+ testStr += "%inval32 = OpLoad %f32 %inloc\n";
+ if (hasFloat16)
+ testStr += "%inval16 = OpFConvert %f16 %inval32\n";
+ if (hasInt8)
+ testStr += "%inval8 = OpConvertFToS %i8 %inval32\n";
+
+ // Because conversions from Float to Int round towards 0 we want our "greater" comparisons to be >=,
+ // that way a float32/float16 comparison such as 50.6f >= 50.0f will preserve its result
+ // when converted to int8, since FtoS(50.6f) results in 50. For "less" comparisons, it is the
+ // other way around, so in this case we want < instead of <=.
+ if (cases[caseNdx][0] == 32)
+ testStr += "%cmp1 = OpFOrdGreaterThanEqual %bool %inval32 %c25f32\n";
+ else if (cases[caseNdx][0] == 16)
+ testStr += "%cmp1 = OpFOrdGreaterThanEqual %bool %inval16 %c25f16\n";
+ else
+ testStr += "%cmp1 = OpSGreaterThanEqual %bool %inval8 %c25i8\n";
+
+ if (cases[caseNdx][1] == 32)
+ testStr += "%cmp2 = OpFOrdLessThan %bool %inval32 %c50f32\n";
+ else if (cases[caseNdx][1] == 16)
+ testStr += "%cmp2 = OpFOrdLessThan %bool %inval16 %c50f16\n";
+ else
+ testStr += "%cmp2 = OpSLessThan %bool %inval8 %c50i8\n";
+
+ if (cases[caseNdx][2] == 32)
+ testStr += "%cmp3 = OpFOrdLessThan %bool %inval32 %c10f32\n";
+ else if (cases[caseNdx][2] == 16)
+ testStr += "%cmp3 = OpFOrdLessThan %bool %inval16 %c10f16\n";
+ else
+ testStr += "%cmp3 = OpSLessThan %bool %inval8 %c10i8\n";
+
+ if (cases[caseNdx][3] == 32)
+ testStr += "%cmp4 = OpFOrdGreaterThanEqual %bool %inval32 %c90f32\n";
+ else if (cases[caseNdx][3] == 16)
+ testStr += "%cmp4 = OpFOrdGreaterThanEqual %bool %inval16 %c90f16\n";
+ else
+ testStr += "%cmp4 = OpSGreaterThanEqual %bool %inval8 %c90i8\n";
+
+ testStr += "%and1 = OpLogicalAnd %bool %cmp1 %cmp2\n";
+ testStr += "%or1 = OpLogicalOr %bool %cmp3 %cmp4\n";
+ testStr += "%or2 = OpLogicalOr %bool %and1 %or1\n";
+ testStr += "%not1 = OpLogicalNot %bool %or2\n";
+ testStr += "%res = OpSelect %f32 %not1 %c1f32 %c0f32\n";
+
+ specializations["CAPS"] = capsStr;
+ specializations["CONST"] = constStr;
+ specializations["TEST"] = testStr;
+
+ // Compute expected result by evaluating the boolean expression computed in the shader for each input value
+ for (size_t ndx = 0; ndx < numElements; ++ndx)
+ outputData[ndx] = !((inputData[ndx] >= 25.0f && inputData[ndx] < 50.0f) || (inputData[ndx] < 10.0f || inputData[ndx] >= 90.0f));
+
+ spec.assembly = shaderTemplate.specialize(specializations);
+ spec.inputs.push_back(BufferSp(new Float32Buffer(inputData)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(outputData)));
+ spec.numWorkGroups = IVec3(numElements, 1, 1);
+ if (hasFloat16)
+ spec.requestedVulkanFeatures.extFloat16Int8 |= EXTFLOAT16INT8FEATURES_FLOAT16;
+ if (hasInt8)
+ spec.requestedVulkanFeatures.extFloat16Int8 |= EXTFLOAT16INT8FEATURES_INT8;
+ spec.extensions.push_back("VK_KHR_shader_float16_int8");
+
+ string testName = "b" + de::toString(cases[caseNdx][0]) + "b" + de::toString(cases[caseNdx][1]) + "b" + de::toString(cases[caseNdx][2]) + "b" + de::toString(cases[caseNdx][3]);
+ group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "", spec));
+ }
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createBoolGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "bool", "Boolean tests"));
+
+ testGroup->addChild(createBoolMixedBitSizeGroup(testCtx));
+
+ return testGroup.release();
+}
+
+tcu::TestCaseGroup* createOpNameAbuseTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "opname_abuse", "OpName abuse tests"));
+ vector<CaseParameter> abuseCases;
+ RGBA defaultColors[4];
+ map<string, string> opNameFragments;
+
+ getOpNameAbuseCases(abuseCases);
+ getDefaultColors(defaultColors);
+
+ opNameFragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_func = OpLabel\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %a\n"
+ "%c = OpFSub %f32 %b %a\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n";
+
+ for (unsigned int i = 0; i < abuseCases.size(); i++)
+ {
+ string casename;
+ casename = string("main") + abuseCases[i].name;
+
+ opNameFragments["debug"] =
+ "OpName %BP_main \"" + abuseCases[i].param + "\"";
+
+ createTestsForAllStages(casename, defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ for (unsigned int i = 0; i < abuseCases.size(); i++)
+ {
+ string casename;
+ casename = string("b") + abuseCases[i].name;
+
+ opNameFragments["debug"] =
+ "OpName %b \"" + abuseCases[i].param + "\"";
+
+ createTestsForAllStages(casename, defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ {
+ opNameFragments["debug"] =
+ "OpName %test_code \"name1\"\n"
+ "OpName %param1 \"name2\"\n"
+ "OpName %a \"name3\"\n"
+ "OpName %b \"name4\"\n"
+ "OpName %c \"name5\"\n"
+ "OpName %ret \"name6\"\n";
+
+ createTestsForAllStages("everything_named", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ {
+ opNameFragments["debug"] =
+ "OpName %test_code \"the_same\"\n"
+ "OpName %param1 \"the_same\"\n"
+ "OpName %a \"the_same\"\n"
+ "OpName %b \"the_same\"\n"
+ "OpName %c \"the_same\"\n"
+ "OpName %ret \"the_same\"\n";
+
+ createTestsForAllStages("everything_named_the_same", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ {
+ opNameFragments["debug"] =
+ "OpName %BP_main \"to_be\"\n"
+ "OpName %BP_main \"or_not\"\n"
+ "OpName %BP_main \"to_be\"\n";
+
+ createTestsForAllStages("main_has_multiple_names", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ {
+ opNameFragments["debug"] =
+ "OpName %b \"to_be\"\n"
+ "OpName %b \"or_not\"\n"
+ "OpName %b \"to_be\"\n";
+
+ createTestsForAllStages("b_has_multiple_names", defaultColors, defaultColors, opNameFragments, abuseGroup.get());
+ }
+
+ return abuseGroup.release();
+}
+
+
+tcu::TestCaseGroup* createOpMemberNameAbuseTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> abuseGroup(new tcu::TestCaseGroup(testCtx, "opmembername_abuse", "OpName abuse tests"));
+ vector<CaseParameter> abuseCases;
+ RGBA defaultColors[4];
+ map<string, string> opMemberNameFragments;
+
+ getOpNameAbuseCases(abuseCases);
+ getDefaultColors(defaultColors);
+
+ opMemberNameFragments["pre_main"] =
+ "%f3str = OpTypeStruct %f32 %f32 %f32\n";
+
+ opMemberNameFragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_func = OpLabel\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %a\n"
+ "%c = OpFSub %f32 %b %a\n"
+ "%cstr = OpCompositeConstruct %f3str %c %c %c\n"
+ "%d = OpCompositeExtract %f32 %cstr 0\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %d %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n";
+
+ for (unsigned int i = 0; i < abuseCases.size(); i++)
+ {
+ string casename;
+ casename = string("f3str_x") + abuseCases[i].name;
+
+ opMemberNameFragments["debug"] =
+ "OpMemberName %f3str 0 \"" + abuseCases[i].param + "\"";
+
+ createTestsForAllStages(casename, defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+ }
+
+ {
+ opMemberNameFragments["debug"] =
+ "OpMemberName %f3str 0 \"name1\"\n"
+ "OpMemberName %f3str 1 \"name2\"\n"
+ "OpMemberName %f3str 2 \"name3\"\n";
+
+ createTestsForAllStages("everything_named", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+ }
+
+ {
+ opMemberNameFragments["debug"] =
+ "OpMemberName %f3str 0 \"the_same\"\n"
+ "OpMemberName %f3str 1 \"the_same\"\n"
+ "OpMemberName %f3str 2 \"the_same\"\n";
+
+ createTestsForAllStages("everything_named_the_same", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+ }
+
+ {
+ opMemberNameFragments["debug"] =
+ "OpMemberName %f3str 0 \"to_be\"\n"
+ "OpMemberName %f3str 1 \"or_not\"\n"
+ "OpMemberName %f3str 0 \"to_be\"\n"
+ "OpMemberName %f3str 2 \"makes_no\"\n"
+ "OpMemberName %f3str 0 \"difference\"\n"
+ "OpMemberName %f3str 0 \"to_me\"\n";
+
+
+ createTestsForAllStages("f3str_x_has_multiple_names", defaultColors, defaultColors, opMemberNameFragments, abuseGroup.get());
+ }
+
+ return abuseGroup.release();
+}
+
+vector<deUint32> getSparseIdsAbuseData (const deUint32 numDataPoints, const deUint32 seed)
+{
+ vector<deUint32> result;
+ de::Random rnd (seed);
+
+ result.reserve(numDataPoints);
+
+ for (deUint32 dataPointNdx = 0; dataPointNdx < numDataPoints; ++dataPointNdx)
+ result.push_back(rnd.getUint32());
+
+ return result;
+}
+
+vector<deUint32> getSparseIdsAbuseResults (const vector<deUint32>& inData1, const vector<deUint32>& inData2)
+{
+ vector<deUint32> result;
+
+ result.reserve(inData1.size());
+
+ for (size_t dataPointNdx = 0; dataPointNdx < inData1.size(); ++dataPointNdx)
+ result.push_back(inData1[dataPointNdx] + inData2[dataPointNdx]);
+
+ return result;
+}
+
+template<class SpecResource>
+void createSparseIdsAbuseTest (tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup>& testGroup)
+{
+ const deUint32 numDataPoints = 16;
+ const std::string testName ("sparse_ids");
+ const deUint32 seed (deStringHash(testName.c_str()));
+ const vector<deUint32> inData1 (getSparseIdsAbuseData(numDataPoints, seed + 1));
+ const vector<deUint32> inData2 (getSparseIdsAbuseData(numDataPoints, seed + 2));
+ const vector<deUint32> outData (getSparseIdsAbuseResults(inData1, inData2));
+ const StringTemplate preMain
+ (
+ "%c_i32_ndp = OpConstant %i32 ${num_data_points}\n"
+ " %up_u32 = OpTypePointer Uniform %u32\n"
+ " %ra_u32 = OpTypeArray %u32 %c_i32_ndp\n"
+ " %SSBO32 = OpTypeStruct %ra_u32\n"
+ "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
+ "%ssbo_src0 = OpVariable %up_SSBO32 Uniform\n"
+ "%ssbo_src1 = OpVariable %up_SSBO32 Uniform\n"
+ " %ssbo_dst = OpVariable %up_SSBO32 Uniform\n"
+ );
+ const StringTemplate decoration
+ (
+ "OpDecorate %ra_u32 ArrayStride 4\n"
+ "OpMemberDecorate %SSBO32 0 Offset 0\n"
+ "OpDecorate %SSBO32 BufferBlock\n"
+ "OpDecorate %ssbo_src0 DescriptorSet 0\n"
+ "OpDecorate %ssbo_src0 Binding 0\n"
+ "OpDecorate %ssbo_src1 DescriptorSet 0\n"
+ "OpDecorate %ssbo_src1 Binding 1\n"
+ "OpDecorate %ssbo_dst DescriptorSet 0\n"
+ "OpDecorate %ssbo_dst Binding 2\n"
+ );
+ const StringTemplate testFun
+ (
+ "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+ " %param = OpFunctionParameter %v4f32\n"
+
+ " %entry = OpLabel\n"
+ " %i = OpVariable %fp_i32 Function\n"
+ " OpStore %i %c_i32_0\n"
+ " OpBranch %loop\n"
+
+ " %loop = OpLabel\n"
+ " %i_cmp = OpLoad %i32 %i\n"
+ " %lt = OpSLessThan %bool %i_cmp %c_i32_ndp\n"
+ " OpLoopMerge %merge %next None\n"
+ " OpBranchConditional %lt %write %merge\n"
+
+ " %write = OpLabel\n"
+ " %ndx = OpLoad %i32 %i\n"
+
+ " %127 = OpAccessChain %up_u32 %ssbo_src0 %c_i32_0 %ndx\n"
+ " %128 = OpLoad %u32 %127\n"
+
+ // The test relies on SPIR-V compiler option SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS set in assembleSpirV()
+ " %4194000 = OpAccessChain %up_u32 %ssbo_src1 %c_i32_0 %ndx\n"
+ " %4194001 = OpLoad %u32 %4194000\n"
+
+ " %2097151 = OpIAdd %u32 %128 %4194001\n"
+ " %2097152 = OpAccessChain %up_u32 %ssbo_dst %c_i32_0 %ndx\n"
+ " OpStore %2097152 %2097151\n"
+ " OpBranch %next\n"
+
+ " %next = OpLabel\n"
+ " %i_cur = OpLoad %i32 %i\n"
+ " %i_new = OpIAdd %i32 %i_cur %c_i32_1\n"
+ " OpStore %i %i_new\n"
+ " OpBranch %loop\n"
+
+ " %merge = OpLabel\n"
+ " OpReturnValue %param\n"
+
+ " OpFunctionEnd\n"
+ );
+ SpecResource specResource;
+ map<string, string> specs;
+ VulkanFeatures features;
+ map<string, string> fragments;
+ vector<string> extensions;
+
+ specs["num_data_points"] = de::toString(numDataPoints);
+
+ fragments["decoration"] = decoration.specialize(specs);
+ fragments["pre_main"] = preMain.specialize(specs);
+ fragments["testfun"] = testFun.specialize(specs);
+
+ specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData1)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+ specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData2)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+ specResource.outputs.push_back(Resource(BufferSp(new Uint32Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+
+ features.coreFeatures.vertexPipelineStoresAndAtomics = true;
+ features.coreFeatures.fragmentStoresAndAtomics = true;
+
+ finalizeTestsCreation(specResource, fragments, testCtx, *testGroup.get(), testName, features, extensions, IVec3(1, 1, 1));
+}
+
+vector<deUint32> getLotsIdsAbuseData (const deUint32 numDataPoints, const deUint32 seed)
+{
+ vector<deUint32> result;
+ de::Random rnd (seed);
+
+ result.reserve(numDataPoints);
+
+ // Fixed value
+ result.push_back(1u);
+
+ // Random values
+ for (deUint32 dataPointNdx = 1; dataPointNdx < numDataPoints; ++dataPointNdx)
+ result.push_back(rnd.getUint8());
+
+ return result;
+}
+
+vector<deUint32> getLotsIdsAbuseResults (const vector<deUint32>& inData1, const vector<deUint32>& inData2, const deUint32 count)
+{
+ vector<deUint32> result;
+
+ result.reserve(inData1.size());
+
+ for (size_t dataPointNdx = 0; dataPointNdx < inData1.size(); ++dataPointNdx)
+ result.push_back(inData1[dataPointNdx] + count * inData2[dataPointNdx]);
+
+ return result;
+}
+
+template<class SpecResource>
+void createLotsIdsAbuseTest (tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup>& testGroup)
+{
+ const deUint32 numDataPoints = 16;
+ const deUint32 firstNdx = 100u;
+ const deUint32 sequenceCount = 10000u;
+ const std::string testName ("lots_ids");
+ const deUint32 seed (deStringHash(testName.c_str()));
+ const vector<deUint32> inData1 (getLotsIdsAbuseData(numDataPoints, seed + 1));
+ const vector<deUint32> inData2 (getLotsIdsAbuseData(numDataPoints, seed + 2));
+ const vector<deUint32> outData (getLotsIdsAbuseResults(inData1, inData2, sequenceCount));
+ const StringTemplate preMain
+ (
+ "%c_i32_ndp = OpConstant %i32 ${num_data_points}\n"
+ " %up_u32 = OpTypePointer Uniform %u32\n"
+ " %ra_u32 = OpTypeArray %u32 %c_i32_ndp\n"
+ " %SSBO32 = OpTypeStruct %ra_u32\n"
+ "%up_SSBO32 = OpTypePointer Uniform %SSBO32\n"
+ "%ssbo_src0 = OpVariable %up_SSBO32 Uniform\n"
+ "%ssbo_src1 = OpVariable %up_SSBO32 Uniform\n"
+ " %ssbo_dst = OpVariable %up_SSBO32 Uniform\n"
+ );
+ const StringTemplate decoration
+ (
+ "OpDecorate %ra_u32 ArrayStride 4\n"
+ "OpMemberDecorate %SSBO32 0 Offset 0\n"
+ "OpDecorate %SSBO32 BufferBlock\n"
+ "OpDecorate %ssbo_src0 DescriptorSet 0\n"
+ "OpDecorate %ssbo_src0 Binding 0\n"
+ "OpDecorate %ssbo_src1 DescriptorSet 0\n"
+ "OpDecorate %ssbo_src1 Binding 1\n"
+ "OpDecorate %ssbo_dst DescriptorSet 0\n"
+ "OpDecorate %ssbo_dst Binding 2\n"
+ );
+ const StringTemplate testFun
+ (
+ "%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
+ " %param = OpFunctionParameter %v4f32\n"
+
+ " %entry = OpLabel\n"
+ " %i = OpVariable %fp_i32 Function\n"
+ " OpStore %i %c_i32_0\n"
+ " OpBranch %loop\n"
+
+ " %loop = OpLabel\n"
+ " %i_cmp = OpLoad %i32 %i\n"
+ " %lt = OpSLessThan %bool %i_cmp %c_i32_ndp\n"
+ " OpLoopMerge %merge %next None\n"
+ " OpBranchConditional %lt %write %merge\n"
+
+ " %write = OpLabel\n"
+ " %ndx = OpLoad %i32 %i\n"
+
+ " %90 = OpAccessChain %up_u32 %ssbo_src1 %c_i32_0 %ndx\n"
+ " %91 = OpLoad %u32 %90\n"
+
+ " %98 = OpAccessChain %up_u32 %ssbo_src0 %c_i32_0 %ndx\n"
+ " %${zeroth_id} = OpLoad %u32 %98\n"
+
+ "${seq}\n"
+
+ // The test relies on SPIR-V compiler option SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS set in assembleSpirV()
+ " %dst = OpAccessChain %up_u32 %ssbo_dst %c_i32_0 %ndx\n"
+ " OpStore %dst %${last_id}\n"
+ " OpBranch %next\n"
+
+ " %next = OpLabel\n"
+ " %i_cur = OpLoad %i32 %i\n"
+ " %i_new = OpIAdd %i32 %i_cur %c_i32_1\n"
+ " OpStore %i %i_new\n"
+ " OpBranch %loop\n"
+
+ " %merge = OpLabel\n"
+ " OpReturnValue %param\n"
+
+ " OpFunctionEnd\n"
+ );
+ deUint32 lastId = firstNdx;
+ SpecResource specResource;
+ map<string, string> specs;
+ VulkanFeatures features;
+ map<string, string> fragments;
+ vector<string> extensions;
+ std::string sequence;
+
+ for (deUint32 sequenceNdx = 0; sequenceNdx < sequenceCount; ++sequenceNdx)
+ {
+ const deUint32 sequenceId = sequenceNdx + firstNdx;
+ const std::string sequenceIdStr = de::toString(sequenceId);
+
+ sequence += "%" + sequenceIdStr + " = OpIAdd %u32 %91 %" + de::toString(sequenceId - 1) + "\n";
+ lastId = sequenceId;
+
+ if (sequenceNdx == 0)
+ sequence.reserve((10 + sequence.length()) * sequenceCount);
+ }
+
+ specs["num_data_points"] = de::toString(numDataPoints);
+ specs["zeroth_id"] = de::toString(firstNdx - 1);
+ specs["last_id"] = de::toString(lastId);
+ specs["seq"] = sequence;
+
+ fragments["decoration"] = decoration.specialize(specs);
+ fragments["pre_main"] = preMain.specialize(specs);
+ fragments["testfun"] = testFun.specialize(specs);
+
+ specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData1)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+ specResource.inputs.push_back(Resource(BufferSp(new Uint32Buffer(inData2)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+ specResource.outputs.push_back(Resource(BufferSp(new Uint32Buffer(outData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
+
+ features.coreFeatures.vertexPipelineStoresAndAtomics = true;
+ features.coreFeatures.fragmentStoresAndAtomics = true;
+
+ finalizeTestsCreation(specResource, fragments, testCtx, *testGroup.get(), testName, features, extensions, IVec3(1, 1, 1));
+}
+
+tcu::TestCaseGroup* createSpirvIdsAbuseTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "spirv_ids_abuse", "SPIR-V abuse tests"));
+
+ createSparseIdsAbuseTest<GraphicsResources>(testCtx, testGroup);
+ createLotsIdsAbuseTest<GraphicsResources>(testCtx, testGroup);
+
+ return testGroup.release();
+}
+
+tcu::TestCaseGroup* createSpirvIdsAbuseGroup (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "spirv_ids_abuse", "SPIR-V abuse tests"));
+
+ createSparseIdsAbuseTest<ComputeShaderSpec>(testCtx, testGroup);
+ createLotsIdsAbuseTest<ComputeShaderSpec>(testCtx, testGroup);
+
+ return testGroup.release();
+}
+
tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
{
const bool testComputePipeline = true;
computeTests->addChild(createSpivVersionCheckTests(testCtx, testComputePipeline));
computeTests->addChild(createLocalSizeGroup(testCtx));
computeTests->addChild(createOpNopGroup(testCtx));
- computeTests->addChild(createOpFUnordGroup(testCtx));
+ computeTests->addChild(createOpFUnordGroup(testCtx, TEST_WITHOUT_NAN));
+ computeTests->addChild(createOpFUnordGroup(testCtx, TEST_WITH_NAN));
computeTests->addChild(createOpAtomicGroup(testCtx, false));
computeTests->addChild(createOpAtomicGroup(testCtx, true)); // Using new StorageBuffer decoration
computeTests->addChild(createOpAtomicGroup(testCtx, false, 1024, true)); // Return value validation
computeTests->addChild(create16BitStorageComputeGroup(testCtx));
computeTests->addChild(createFloatControlsComputeGroup(testCtx));
computeTests->addChild(createUboMatrixPaddingComputeGroup(testCtx));
+ computeTests->addChild(createCompositeInsertComputeGroup(testCtx));
computeTests->addChild(createVariableInitComputeGroup(testCtx));
computeTests->addChild(createConditionalBranchComputeGroup(testCtx));
computeTests->addChild(createIndexingComputeGroup(testCtx));
computeTests->addChild(createVariablePointersComputeGroup(testCtx));
+ computeTests->addChild(createPhysicalPointersComputeGroup(testCtx));
computeTests->addChild(createImageSamplerComputeGroup(testCtx));
computeTests->addChild(createOpNameGroup(testCtx));
+ computeTests->addChild(createOpMemberNameGroup(testCtx));
computeTests->addChild(createPointerParameterComputeGroup(testCtx));
computeTests->addChild(createFloat16Group(testCtx));
+ computeTests->addChild(createBoolGroup(testCtx));
+ computeTests->addChild(createWorkgroupMemoryComputeGroup(testCtx));
+ computeTests->addChild(createSpirvIdsAbuseGroup(testCtx));
+ computeTests->addChild(createSignedIntCompareGroup(testCtx));
+ computeTests->addChild(createUnusedVariableComputeTests(testCtx));
+ computeTests->addChild(createPtrAccessChainGroup(testCtx));
graphicsTests->addChild(createCrossStageInterfaceTests(testCtx));
graphicsTests->addChild(createSpivVersionCheckTests(testCtx, !testComputePipeline));
graphicsTests->addChild(createOpUndefTests(testCtx));
graphicsTests->addChild(createSelectionBlockOrderTests(testCtx));
graphicsTests->addChild(createModuleTests(testCtx));
+ graphicsTests->addChild(createUnusedVariableTests(testCtx));
graphicsTests->addChild(createSwitchBlockOrderTests(testCtx));
graphicsTests->addChild(createOpPhiTests(testCtx));
graphicsTests->addChild(createNoContractionTests(testCtx));
graphicsTests->addChild(graphicsAndroidTests.release());
}
graphicsTests->addChild(createOpNameTests(testCtx));
+ graphicsTests->addChild(createOpNameAbuseTests(testCtx));
+ graphicsTests->addChild(createOpMemberNameAbuseTests(testCtx));
graphicsTests->addChild(create8BitStorageGraphicsGroup(testCtx));
graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
graphicsTests->addChild(createFloatControlsGraphicsGroup(testCtx));
graphicsTests->addChild(createUboMatrixPaddingGraphicsGroup(testCtx));
+ graphicsTests->addChild(createCompositeInsertGraphicsGroup(testCtx));
graphicsTests->addChild(createVariableInitGraphicsGroup(testCtx));
graphicsTests->addChild(createConditionalBranchGraphicsGroup(testCtx));
graphicsTests->addChild(createIndexingGraphicsGroup(testCtx));
graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpConvertUToF", "convertutof"));
graphicsTests->addChild(createConvertGraphicsTests(testCtx, "OpConvertFToU", "convertftou"));
graphicsTests->addChild(createPointerParameterGraphicsGroup(testCtx));
-
+ graphicsTests->addChild(createVaryingNameGraphicsGroup(testCtx));
graphicsTests->addChild(createFloat16Tests(testCtx));
+ graphicsTests->addChild(createSpirvIdsAbuseTests(testCtx));
instructionTests->addChild(computeTests.release());
instructionTests->addChild(graphicsTests.release());