#include "tcuStringTemplate.hpp"
#include <cmath>
-
#include "vktSpvAsmComputeShaderCase.hpp"
#include "vktSpvAsmComputeShaderTestUtil.hpp"
#include "vktTestCaseUtil.hpp"
case 2: outputFloats1[ndx] = inputFloats[ndx] + 1.75f; break;
default: break;
}
-
outputFloats2[ndx] = inputFloats[ndx] + 6.5f * 3;
outputFloats3[ndx] = 8.5f - inputFloats[ndx];
}
"%case0 = OpLabel\n"
" OpBranch %phi\n"
+
// Case 2 after OpPhi.
"%case2 = OpLabel\n"
" OpBranch %phi\n"
vector<float> inputFloats (numElements, 0);
vector<float> outputFloats1 (numElements, 0);
vector<float> outputFloats2 (numElements, 0);
-
fillRandomScalars(rnd, -500.f, 500.f, &inputFloats[0], numElements);
for (size_t ndx = 0; ndx < numElements; ++ndx)
return group.release();
}
+inline std::string makeLongUTF8String (size_t num4ByteChars)
+{
+ // An example of a longest valid UTF-8 character. Be explicit about the
+ // character type because Microsoft compilers can otherwise interpret the
+ // character string as being over wide (16-bit) characters. Ideally, we
+ // would just use a C++11 UTF-8 string literal, but we want to support older
+ // Microsoft compilers.
+ const std::basic_string<char> earthAfrica("\xF0\x9F\x8C\x8D");
+ std::string longString;
+ longString.reserve(num4ByteChars * 4);
+ for (size_t count = 0; count < num4ByteChars; count++)
+ {
+ longString += earthAfrica;
+ }
+ return longString;
+}
+
tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction"));
cases.push_back(CaseParameter("empty_source_code", "%fname = OpString \"filename\"\n"
"OpSource GLSL 430 %fname \"\""));
cases.push_back(CaseParameter("long_source_code", "%fname = OpString \"filename\"\n"
- "OpSource GLSL 430 %fname \"" + string(65530, 'x') + "\"")); // word count: 65535
+ "OpSource GLSL 430 %fname \"" + makeLongUTF8String(65530) + "ccc\"")); // word count: 65535
cases.push_back(CaseParameter("utf8_source_code", "%fname = OpString \"filename\"\n"
"OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol
cases.push_back(CaseParameter("normal_sourcecontinued", "%fname = OpString \"filename\"\n"
"OpSourceContinued \"\""));
cases.push_back(CaseParameter("long_sourcecontinued", "%fname = OpString \"filename\"\n"
"OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
- "OpSourceContinued \"" + string(65533, 'x') + "\"")); // word count: 65535
+ "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\"")); // word count: 65535
cases.push_back(CaseParameter("utf8_sourcecontinued", "%fname = OpString \"filename\"\n"
"OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
"OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol
cases.push_back(CaseParameter("real_extension", "GL_ARB_texture_rectangle"));
cases.push_back(CaseParameter("fake_extension", "GL_ARB_im_the_ultimate_extension"));
cases.push_back(CaseParameter("utf8_extension", "GL_ARB_\xE2\x98\x82\xE2\x98\x85"));
- cases.push_back(CaseParameter("long_extension", string(65533, 'e'))); // word count: 65535
+ cases.push_back(CaseParameter("long_extension", makeLongUTF8String(65533) + "ccc")); // word count: 65535
fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
return group.release();
}
-
// Checks that constant null/composite values can be used in computation.
tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
{
specializations["TYPE"] = cases[caseNdx].param;
spec.assembly = shaderTemplate.specialize(specializations);
- spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
- spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
+ spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
+ spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
spec.numWorkGroups = IVec3(numElements, 1, 1);
spec.entryPoint = "main";
// Concrete SPIR-V code to test via boilerplate specialization.
map<string, string> testCodeFragments;
+ bool hasTessellation;
InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_)
: testCodeFragments (testCodeFragments_)
+ , hasTessellation(false)
{
inputColors[0] = inputs[0];
inputColors[1] = inputs[1];
InstanceContext (const InstanceContext& other)
: moduleMap (other.moduleMap)
, testCodeFragments (other.testCodeFragments)
+ , hasTessellation(other.hasTessellation)
{
inputColors[0] = other.inputColors[0];
inputColors[1] = other.inputColors[1];
struct ShaderElement
{
// The module that contains this shader entrypoint.
- const char* moduleName;
+ string moduleName;
// The name of the entrypoint.
- const char* entryName;
+ string entryName;
// Which shader stage this entry point represents.
VkShaderStageFlagBits stage;
- ShaderElement (const char* moduleName_, const char* entryPoint_, VkShaderStageFlagBits shaderStage_)
+ ShaderElement (const string& moduleName_, const string& entryPoint_, VkShaderStageFlagBits shaderStage_)
: moduleName(moduleName_)
, entryName(entryPoint_)
, stage(shaderStage_)
{
colors[0] = RGBA::white();
colors[1] = RGBA::red();
- colors[2] = RGBA::blue();
- colors[3] = RGBA::green();
+ colors[2] = RGBA::green();
+ colors[3] = RGBA::blue();
+}
+
+void getHalfColorsFullAlpha (RGBA (&colors)[4])
+{
+ colors[0] = RGBA(127, 127, 127, 255);
+ colors[1] = RGBA(127, 0, 0, 255);
+ colors[2] = RGBA(0, 127, 0, 255);
+ colors[3] = RGBA(0, 0, 127, 255);
+}
+
+void getInvertedDefaultColors (RGBA (&colors)[4])
+{
+ colors[0] = RGBA(0, 0, 0, 255);
+ colors[1] = RGBA(0, 255, 255, 255);
+ colors[2] = RGBA(255, 0, 255, 255);
+ colors[3] = RGBA(255, 255, 0, 255);
}
// Turns a statically sized array of ShaderElements into an instance-context
for (size_t i = 0; i < N; ++i)
{
ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
+ if (elements[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
+ elements[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+ {
+ ctx.hasTessellation = true;
+ }
}
return ctx;
}
}
}
-#define SPIRV_ASSEMBLY_TYPES \
- "%void = OpTypeVoid\n" \
- "%bool = OpTypeBool\n" \
- \
- "%i32 = OpTypeInt 32 1\n" \
- "%u32 = OpTypeInt 32 0\n" \
- \
- "%f32 = OpTypeFloat 32\n" \
- "%v3f32 = OpTypeVector %f32 3\n" \
- "%v4f32 = OpTypeVector %f32 4\n" \
- \
- "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \
- "%fun = OpTypeFunction %void\n" \
- \
- "%ip_f32 = OpTypePointer Input %f32\n" \
- "%ip_i32 = OpTypePointer Input %i32\n" \
- "%ip_v3f32 = OpTypePointer Input %v3f32\n" \
- "%ip_v4f32 = OpTypePointer Input %v4f32\n" \
- \
- "%op_f32 = OpTypePointer Output %f32\n" \
- "%op_v4f32 = OpTypePointer Output %v4f32\n"
-
-#define SPIRV_ASSEMBLY_CONSTANTS \
- "%c_f32_1 = OpConstant %f32 1\n" \
- "%c_i32_0 = OpConstant %i32 0\n" \
- "%c_i32_1 = OpConstant %i32 1\n" \
- "%c_i32_2 = OpConstant %i32 2\n" \
- "%c_u32_0 = OpConstant %u32 0\n" \
- "%c_u32_1 = OpConstant %u32 1\n" \
- "%c_u32_2 = OpConstant %u32 2\n" \
- "%c_u32_3 = OpConstant %u32 3\n" \
- "%c_u32_32 = OpConstant %u32 32\n" \
- "%c_u32_4 = OpConstant %u32 4\n"
-
-#define SPIRV_ASSEMBLY_ARRAYS \
- "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \
- "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \
- "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \
- "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \
- "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \
- "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \
- "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \
- "%op_a2f32 = OpTypePointer Output %a2f32\n" \
- "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \
+#define SPIRV_ASSEMBLY_TYPES \
+ "%void = OpTypeVoid\n" \
+ "%bool = OpTypeBool\n" \
+ \
+ "%i32 = OpTypeInt 32 1\n" \
+ "%u32 = OpTypeInt 32 0\n" \
+ \
+ "%f32 = OpTypeFloat 32\n" \
+ "%v3f32 = OpTypeVector %f32 3\n" \
+ "%v4f32 = OpTypeVector %f32 4\n" \
+ \
+ "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \
+ "%fun = OpTypeFunction %void\n" \
+ \
+ "%ip_f32 = OpTypePointer Input %f32\n" \
+ "%ip_i32 = OpTypePointer Input %i32\n" \
+ "%ip_v3f32 = OpTypePointer Input %v3f32\n" \
+ "%ip_v4f32 = OpTypePointer Input %v4f32\n" \
+ \
+ "%op_f32 = OpTypePointer Output %f32\n" \
+ "%op_v4f32 = OpTypePointer Output %v4f32\n" \
+ \
+ "%fp_f32 = OpTypePointer Function %f32\n" \
+ "%fp_i32 = OpTypePointer Function %i32\n" \
+ "%fp_v4f32 = OpTypePointer Function %v4f32\n"
+
+
+#define SPIRV_ASSEMBLY_CONSTANTS \
+ "%c_f32_1 = OpConstant %f32 1.0\n" \
+ "%c_f32_0 = OpConstant %f32 0.0\n" \
+ "%c_f32_0_5 = OpConstant %f32 0.5\n" \
+ "%c_i32_0 = OpConstant %i32 0\n" \
+ "%c_i32_1 = OpConstant %i32 1\n" \
+ "%c_i32_2 = OpConstant %i32 2\n" \
+ "%c_i32_3 = OpConstant %i32 3\n" \
+ "%c_i32_4 = OpConstant %i32 4\n" \
+ "%c_u32_0 = OpConstant %u32 0\n" \
+ "%c_u32_1 = OpConstant %u32 1\n" \
+ "%c_u32_2 = OpConstant %u32 2\n" \
+ "%c_u32_3 = OpConstant %u32 3\n" \
+ "%c_u32_32 = OpConstant %u32 32\n" \
+ "%c_u32_4 = OpConstant %u32 4\n" \
+ "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \
+ "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n"
+
+#define SPIRV_ASSEMBLY_ARRAYS \
+ "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \
+ "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \
+ "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \
+ "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \
+ "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \
+ "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \
+ "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \
+ "%op_a2f32 = OpTypePointer Output %a2f32\n" \
+ "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \
"%op_a4f32 = OpTypePointer Output %a4f32\n"
// Creates vertex-shader assembly by specializing a boilerplate StringTemplate
static const char vertexShaderBoilerplate[] =
"OpCapability Shader\n"
"OpMemoryModel Logical GLSL450\n"
- "OpEntryPoint Vertex %4 \"main\" %BP_Position %BP_vtxColor %BP_color "
+ "OpEntryPoint Vertex %main \"main\" %BP_Position %BP_vtxColor %BP_color "
"%BP_vtxPosition %BP_vertex_id %BP_instance_id\n"
"${debug:opt}\n"
"OpName %main \"main\"\n"
"%BP_color = OpVariable %ip_v4f32 Input\n"
"%BP_vertex_id = OpVariable %ip_i32 Input\n"
"%BP_instance_id = OpVariable %ip_i32 Input\n"
+ "${pre_main:opt}\n"
"%main = OpFunction %void None %fun\n"
"%BP_label = OpLabel\n"
"%BP_tmp_position = OpLoad %v4f32 %BP_Position\n"
"%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
"%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
"%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
+ "${pre_main:opt}\n"
"%BP_main = OpFunction %void None %fun\n"
"%BP_label = OpLabel\n"
"%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
"%BP_out_color = OpVariable %op_v4f32 Output\n"
"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
+ "${pre_main:opt}\n"
"%BP_main = OpFunction %void None %fun\n"
"%BP_label = OpLabel\n"
"%BP_tc_0_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_0\n"
"%BP_out_color = OpVariable %op_v4f32 Output\n"
"%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
"%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
+ "${pre_main:opt}\n"
"%BP_main = OpFunction %void None %fun\n"
"%BP_label = OpLabel\n"
SPIRV_ASSEMBLY_ARRAYS
"%BP_fragColor = OpVariable %op_v4f32 Output\n"
"%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
+ "${pre_main:opt}\n"
"%BP_main = OpFunction %void None %fun\n"
"%BP_label_main = OpLabel\n"
"%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Vertex shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) {
+void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context)
+{
map<string, string> passthru = passthruFragments();
dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments);
dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Tessellation control shader gets custom code from context, the rest are
// pass-through.
-void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) {
+void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context)
+{
map<string, string> passthru = passthruFragments();
dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments);
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Tessellation evaluation shader gets custom code from context, the rest are
// pass-through.
-void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) {
+void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context)
+{
map<string, string> passthru = passthruFragments();
dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Geometry shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) {
+void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context)
+{
map<string, string> passthru = passthruFragments();
dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
// Fragment shader gets custom code from context, the rest are pass-through.
-void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) {
+void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context)
+{
map<string, string> passthru = passthruFragments();
dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments);
}
+void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
+{
+ // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional
+ // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemeberName at some point
+ dst.spirvAsmSources.add("module") <<
+ "OpCapability Shader\n"
+ "OpCapability Geometry\n"
+ "OpCapability Tessellation\n"
+ "OpMemoryModel Logical GLSL450\n"
+
+ "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n"
+ "OpEntryPoint Geometry %geom_main \"main\" %out_gl_position %gl_in %out_color %in_color\n"
+ "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n"
+ "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n"
+ "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n"
+
+ "OpExecutionMode %geom_main Triangles\n"
+ "OpExecutionMode %geom_main Invocations 0\n"
+ "OpExecutionMode %geom_main OutputTriangleStrip\n"
+ "OpExecutionMode %geom_main OutputVertices 3\n"
+
+ "OpExecutionMode %tessc_main OutputVertices 3\n"
+
+ "OpExecutionMode %tesse_main Triangles\n"
+
+ "OpExecutionMode %frag_main OriginUpperLeft\n"
+
+ "; Vertex decorations\n"
+ "OpName %vert_main \"main\"\n"
+ "OpName %vert_vtxPosition \"vtxPosition\"\n"
+ "OpName %vert_Position \"position\"\n"
+ "OpName %vert_vtxColor \"vtxColor\"\n"
+ "OpName %vert_color \"color\"\n"
+ "OpName %vert_vertex_id \"gl_VertexID\"\n"
+ "OpName %vert_instance_id \"gl_InstanceID\"\n"
+ "OpDecorate %vert_vtxPosition Location 2\n"
+ "OpDecorate %vert_Position Location 0\n"
+ "OpDecorate %vert_vtxColor Location 1\n"
+ "OpDecorate %vert_color Location 1\n"
+ "OpDecorate %vert_vertex_id BuiltIn VertexId\n"
+ "OpDecorate %vert_instance_id BuiltIn InstanceId\n"
+
+ "; Geometry decorations\n"
+ "OpName %geom_main \"main\"\n"
+ "OpName %per_vertex_in \"gl_PerVertex\"\n"
+ "OpMemberName %per_vertex_in 0 \"gl_Position\"\n"
+ "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n"
+ "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n"
+ "OpName %gl_in \"gl_in\"\n"
+ "OpName %out_color \"out_color\"\n"
+ "OpName %in_color \"in_color\"\n"
+ "OpDecorate %out_gl_position BuiltIn Position\n"
+ "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
+ "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
+ "OpDecorate %per_vertex_in Block\n"
+ "OpDecorate %out_color Location 1\n"
+ "OpDecorate %out_color Stream 0\n"
+ "OpDecorate %in_color Location 1\n"
+
+ "; Tessellation Control decorations\n"
+ "OpName %tessc_main \"main\"\n"
+ "OpName %tessc_out_color \"out_color\"\n"
+ "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n"
+ "OpName %tessc_in_color \"in_color\"\n"
+ "OpName %tessc_out_position \"out_position\"\n"
+ "OpName %tessc_in_position \"in_position\"\n"
+ "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
+ "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n"
+ "OpDecorate %tessc_out_color Location 1\n"
+ "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n"
+ "OpDecorate %tessc_in_color Location 1\n"
+ "OpDecorate %tessc_out_position Location 2\n"
+ "OpDecorate %tessc_in_position Location 2\n"
+ "OpDecorate %tessc_gl_TessLevelOuter Patch\n"
+ "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
+ "OpDecorate %tessc_gl_TessLevelInner Patch\n"
+ "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n"
+
+ "; Tessellation Evaluation decorations\n"
+ "OpName %tesse_main \"main\"\n"
+ "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n"
+ "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n"
+ "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n"
+ "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n"
+ "OpName %tesse_stream \"\"\n"
+ "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n"
+ "OpName %tesse_in_position \"in_position\"\n"
+ "OpName %tesse_out_color \"out_color\"\n"
+ "OpName %tesse_in_color \"in_color\"\n"
+ "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n"
+ "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n"
+ "OpDecorate %tesse_per_vertex_out Block\n"
+ "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n"
+ "OpDecorate %tesse_in_position Location 2\n"
+ "OpDecorate %tesse_out_color Location 1\n"
+ "OpDecorate %tesse_in_color Location 1\n"
+
+ "; Fragment decorations\n"
+ "OpName %frag_main \"main\"\n"
+ "OpName %frag_fragColor \"fragColor\"\n"
+ "OpName %frag_vtxColor \"vtxColor\"\n"
+ "OpDecorate %frag_fragColor Location 0\n"
+ "OpDecorate %frag_vtxColor Location 1\n"
+
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+
+ "; Vertex Variables\n"
+ "%vert_vtxPosition = OpVariable %op_v4f32 Output\n"
+ "%vert_Position = OpVariable %ip_v4f32 Input\n"
+ "%vert_vtxColor = OpVariable %op_v4f32 Output\n"
+ "%vert_color = OpVariable %ip_v4f32 Input\n"
+ "%vert_vertex_id = OpVariable %ip_i32 Input\n"
+ "%vert_instance_id = OpVariable %ip_i32 Input\n"
+
+ "; Geometry Variables\n"
+ "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n"
+ "%geom_ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
+ "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n"
+ "%geom_out_color = OpVariable %op_v4f32 Output\n"
+ "%geom_in_color = OpVariable %ip_a3v4f32 Input\n"
+ "%geom_out_gl_position = OpVariable %op_v4f32 Output\n"
+
+ "; Tessellation Control Variables\n"
+ "%tessc_out_color = OpVariable %op_a3v4f32 Output\n"
+ "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n"
+ "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n"
+ "%tessc_out_position = OpVariable %op_a3v4f32 Output\n"
+ "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
+ "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
+
+ "; Tessellation Evaluation Decorations\n"
+ "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n"
+ "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n"
+ "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
+ "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%tesse_out_color = OpVariable %op_v4f32 Output\n"
+ "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n"
+
+ "; Fragment Variables\n"
+ "%frag_fragColor = OpVariable %op_v4f32 Output\n"
+ "%frag_vtxColor = OpVariable %ip_v4f32 Input\n"
+
+ "; Vertex Entry\n"
+ "%vert_main = OpFunction %void None %fun\n"
+ "%vert_label = OpLabel\n"
+ "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n"
+ "OpStore %vert_vtxPosition %vert_tmp_position\n"
+ "%vert_tmp_color = OpLoad %v4f32 %vert_color\n"
+ "OpStore %vert_vtxColor %vert_tmp_color\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "; Geometry Entry\n"
+ "%geom_main = OpFunction %void None %fun\n"
+ "%geom_label = OpLabel\n"
+ "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n"
+ "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n"
+ "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n"
+ "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n"
+ "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n"
+ "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n"
+ "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n"
+ "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n"
+ "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n"
+ "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n"
+ "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n"
+ "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n"
+ "OpStore %geom_out_gl_position %geom_in_position_0\n"
+ "OpStore %geom_out_color %geom_in_color_0\n"
+ "OpEmitVertex\n"
+ "OpStore %geom_out_gl_position %geom_in_position_1\n"
+ "OpStore %geom_out_color %geom_in_color_1\n"
+ "OpEmitVertex\n"
+ "OpStore %geom_out_gl_position %geom_in_position_2\n"
+ "OpStore %geom_out_color %geom_in_color_2\n"
+ "OpEmitVertex\n"
+ "OpEndPrimitive\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "; Tessellation Control Entry\n"
+ "%tessc_main = OpFunction %void None %fun\n"
+ "%tessc_label = OpLabel\n"
+ "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n"
+ "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n"
+ "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n"
+ "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n"
+ "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n"
+ "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n"
+ "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n"
+ "OpStore %tessc_out_color_ptr %tessc_in_color_val\n"
+ "OpStore %tessc_out_position_ptr %tessc_in_position_val\n"
+ "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n"
+ "OpSelectionMerge %tessc_merge_label None\n"
+ "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n"
+ "%tessc_first_invocation = OpLabel\n"
+ "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n"
+ "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n"
+ "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n"
+ "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n"
+ "OpStore %tessc_tess_outer_0 %c_f32_1\n"
+ "OpStore %tessc_tess_outer_1 %c_f32_1\n"
+ "OpStore %tessc_tess_outer_2 %c_f32_1\n"
+ "OpStore %tessc_tess_inner %c_f32_1\n"
+ "OpBranch %tessc_merge_label\n"
+ "%tessc_merge_label = OpLabel\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "; Tessellation Evaluation Entry\n"
+ "%tesse_main = OpFunction %void None %fun\n"
+ "%tesse_label = OpLabel\n"
+ "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n"
+ "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n"
+ "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n"
+ "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n"
+ "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n"
+ "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n"
+ "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n"
+ "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n"
+ "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n"
+ "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
+ "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
+ "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
+ "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %tesse_in_pos_0\n"
+ "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %tesse_in_pos_1\n"
+ "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %tesse_in_pos_2\n"
+ "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
+ "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
+ "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
+ "OpStore %tesse_out_pos_ptr %tesse_computed_out\n"
+ "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n"
+ "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n"
+ "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n"
+ "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
+ "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
+ "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
+ "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_clr_0\n"
+ "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_clr_1\n"
+ "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_clr_2\n"
+ "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
+ "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
+ "OpStore %tesse_out_color %tesse_computed_clr\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "; Fragment Entry\n"
+ "%frag_main = OpFunction %void None %fun\n"
+ "%frag_label_main = OpLabel\n"
+ "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n"
+ "OpStore %frag_fragColor %frag_tmp1\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+}
+
+// This has two shaders of each stage. The first
+// is a passthrough, the second inverts the color.
+void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
+{
+ dst.spirvAsmSources.add("vert") <<
+ // This module contains 2 vertex shaders. One that is a passthrough
+ // and a second that inverts the color of the output (1.0 - color).
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
+ "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
+
+ "OpName %main \"frag1\"\n"
+ "OpName %main2 \"frag2\"\n"
+ "OpName %vtxPosition \"vtxPosition\"\n"
+ "OpName %Position \"position\"\n"
+ "OpName %vtxColor \"vtxColor\"\n"
+ "OpName %color \"color\"\n"
+ "OpName %vertex_id \"gl_VertexID\"\n"
+ "OpName %instance_id \"gl_InstanceID\"\n"
+ "OpName %test_code \"testfun(vf4;\"\n"
+
+ "OpDecorate %vtxPosition Location 2\n"
+ "OpDecorate %Position Location 0\n"
+ "OpDecorate %vtxColor Location 1\n"
+ "OpDecorate %color Location 1\n"
+ "OpDecorate %vertex_id BuiltIn VertexId\n"
+ "OpDecorate %instance_id BuiltIn InstanceId\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%vtxPosition = OpVariable %op_v4f32 Output\n"
+ "%Position = OpVariable %ip_v4f32 Input\n"
+ "%vtxColor = OpVariable %op_v4f32 Output\n"
+ "%color = OpVariable %ip_v4f32 Input\n"
+ "%vertex_id = OpVariable %ip_i32 Input\n"
+ "%instance_id = OpVariable %ip_i32 Input\n"
+
+ "%main = OpFunction %void None %fun\n"
+ "%label = OpLabel\n"
+ "%tmp_position = OpLoad %v4f32 %Position\n"
+ "OpStore %vtxPosition %tmp_position\n"
+ "%tmp_color = OpLoad %v4f32 %color\n"
+ "OpStore %vtxColor %tmp_color\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "%main2 = OpFunction %void None %fun\n"
+ "%label2 = OpLabel\n"
+ "%tmp_position2 = OpLoad %v4f32 %Position\n"
+ "OpStore %vtxPosition %tmp_position2\n"
+ "%tmp_color2 = OpLoad %v4f32 %color\n"
+ "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
+ "OpStore %vtxColor %tmp_color3\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+
+ dst.spirvAsmSources.add("frag") <<
+ // This is a single module that contains 2 fragment shaders.
+ // One that passes color through and the other that inverts the output
+ // color (1.0 - color).
+ "OpCapability Shader\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
+ "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
+ "OpExecutionMode %main OriginUpperLeft\n"
+ "OpExecutionMode %main2 OriginUpperLeft\n"
+
+ "OpName %main \"frag1\"\n"
+ "OpName %main2 \"frag2\"\n"
+ "OpName %fragColor \"fragColor\"\n"
+ "OpName %vtxColor \"vtxColor\"\n"
+ "OpDecorate %fragColor Location 0\n"
+ "OpDecorate %vtxColor Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%fragColor = OpVariable %op_v4f32 Output\n"
+ "%vtxColor = OpVariable %ip_v4f32 Input\n"
+
+ "%main = OpFunction %void None %fun\n"
+ "%label_main = OpLabel\n"
+ "%tmp1 = OpLoad %v4f32 %vtxColor\n"
+ "OpStore %fragColor %tmp1\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "%main2 = OpFunction %void None %fun\n"
+ "%label_main2 = OpLabel\n"
+ "%tmp2 = OpLoad %v4f32 %vtxColor\n"
+ "%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
+ "OpStore %fragColor %tmp3\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+
+ dst.spirvAsmSources.add("geom") <<
+ "OpCapability Geometry\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
+ "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
+ "OpExecutionMode %geom1_main Triangles\n"
+ "OpExecutionMode %geom2_main Triangles\n"
+ "OpExecutionMode %geom1_main Invocations 0\n"
+ "OpExecutionMode %geom2_main Invocations 0\n"
+ "OpExecutionMode %geom1_main OutputTriangleStrip\n"
+ "OpExecutionMode %geom2_main OutputTriangleStrip\n"
+ "OpExecutionMode %geom1_main OutputVertices 3\n"
+ "OpExecutionMode %geom2_main OutputVertices 3\n"
+ "OpName %geom1_main \"geom1\"\n"
+ "OpName %geom2_main \"geom2\"\n"
+ "OpName %per_vertex_in \"gl_PerVertex\"\n"
+ "OpMemberName %per_vertex_in 0 \"gl_Position\"\n"
+ "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n"
+ "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n"
+ "OpName %gl_in \"gl_in\"\n"
+ "OpName %out_color \"out_color\"\n"
+ "OpName %in_color \"in_color\"\n"
+ "OpDecorate %out_gl_position BuiltIn Position\n"
+ "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
+ "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
+ "OpDecorate %per_vertex_in Block\n"
+ "OpDecorate %out_color Location 1\n"
+ "OpDecorate %out_color Stream 0\n"
+ "OpDecorate %in_color Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
+ "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
+ "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
+ "%out_color = OpVariable %op_v4f32 Output\n"
+ "%in_color = OpVariable %ip_a3v4f32 Input\n"
+ "%out_gl_position = OpVariable %op_v4f32 Output\n"
+
+ "%geom1_main = OpFunction %void None %fun\n"
+ "%geom1_label = OpLabel\n"
+ "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
+ "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
+ "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
+ "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
+ "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
+ "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
+ "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
+ "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
+ "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
+ "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
+ "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
+ "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
+ "OpStore %out_gl_position %geom1_in_position_0\n"
+ "OpStore %out_color %geom1_in_color_0\n"
+ "OpEmitVertex\n"
+ "OpStore %out_gl_position %geom1_in_position_1\n"
+ "OpStore %out_color %geom1_in_color_1\n"
+ "OpEmitVertex\n"
+ "OpStore %out_gl_position %geom1_in_position_2\n"
+ "OpStore %out_color %geom1_in_color_2\n"
+ "OpEmitVertex\n"
+ "OpEndPrimitive\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "%geom2_main = OpFunction %void None %fun\n"
+ "%geom2_label = OpLabel\n"
+ "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
+ "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
+ "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
+ "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
+ "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
+ "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
+ "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
+ "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
+ "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
+ "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
+ "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
+ "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
+ "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
+ "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
+ "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
+ "OpStore %out_gl_position %geom2_in_position_0\n"
+ "OpStore %out_color %geom2_transformed_in_color_0\n"
+ "OpEmitVertex\n"
+ "OpStore %out_gl_position %geom2_in_position_1\n"
+ "OpStore %out_color %geom2_transformed_in_color_1\n"
+ "OpEmitVertex\n"
+ "OpStore %out_gl_position %geom2_in_position_2\n"
+ "OpStore %out_color %geom2_transformed_in_color_2\n"
+ "OpEmitVertex\n"
+ "OpEndPrimitive\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+
+ dst.spirvAsmSources.add("tessc") <<
+ "OpCapability Tessellation\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
+ "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
+ "OpExecutionMode %tessc1_main OutputVertices 3\n"
+ "OpExecutionMode %tessc2_main OutputVertices 3\n"
+ "OpName %tessc1_main \"tessc1\"\n"
+ "OpName %tessc2_main \"tessc2\"\n"
+ "OpName %out_color \"out_color\"\n"
+ "OpName %gl_InvocationID \"gl_InvocationID\"\n"
+ "OpName %in_color \"in_color\"\n"
+ "OpName %out_position \"out_position\"\n"
+ "OpName %in_position \"in_position\"\n"
+ "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
+ "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n"
+ "OpDecorate %out_color Location 1\n"
+ "OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
+ "OpDecorate %in_color Location 1\n"
+ "OpDecorate %out_position Location 2\n"
+ "OpDecorate %in_position Location 2\n"
+ "OpDecorate %gl_TessLevelOuter Patch\n"
+ "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
+ "OpDecorate %gl_TessLevelInner Patch\n"
+ "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%out_color = OpVariable %op_a3v4f32 Output\n"
+ "%gl_InvocationID = OpVariable %ip_i32 Input\n"
+ "%in_color = OpVariable %ip_a32v4f32 Input\n"
+ "%out_position = OpVariable %op_a3v4f32 Output\n"
+ "%in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
+ "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
+
+ "%tessc1_main = OpFunction %void None %fun\n"
+ "%tessc1_label = OpLabel\n"
+ "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
+ "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
+ "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
+ "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
+ "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
+ "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
+ "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
+ "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
+ "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
+ "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
+ "OpSelectionMerge %tessc1_merge_label None\n"
+ "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
+ "%tessc1_first_invocation = OpLabel\n"
+ "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
+ "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
+ "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
+ "%tessc1_tess_inner = OpAccessChain %op_f32 %tessc1_gl_TessLevelInner %c_i32_0\n"
+ "OpStore %tessc1_tess_outer_0 %c_f32_1\n"
+ "OpStore %tessc1_tess_outer_1 %c_f32_1\n"
+ "OpStore %tessc1_tess_outer_2 %c_f32_1\n"
+ "OpStore %tessc1_tess_inner %c_f32_1\n"
+ "OpBranch %tessc1_merge_label\n"
+ "%tessc1_merge_label = OpLabel\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "%tessc2_main = OpFunction %void None %fun\n"
+ "%tessc2_label = OpLabel\n"
+ "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
+ "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
+ "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
+ "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
+ "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
+ "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
+ "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
+ "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
+ "OpStore %tessc2_out_color_ptr %tessc2_transformed_color\n"
+ "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
+ "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
+ "OpSelectionMerge %tessc2_merge_label None\n"
+ "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
+ "%tessc2_first_invocation = OpLabel\n"
+ "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
+ "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
+ "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
+ "%tessc2_tess_inner = OpAccessChain %op_f32 %tessc2_gl_TessLevelInner %c_i32_0\n"
+ "OpStore %tessc2_tess_outer_0 %c_f32_1\n"
+ "OpStore %tessc2_tess_outer_1 %c_f32_1\n"
+ "OpStore %tessc2_tess_outer_2 %c_f32_1\n"
+ "OpStore %tessc2_tess_inner %c_f32_1\n"
+ "OpBranch %tessc2_merge_label\n"
+ "%tessc2_merge_label = OpLabel\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+
+ dst.spirvAsmSources.add("tesse") <<
+ "OpCapability Tessellation\n"
+ "OpMemoryModel Logical GLSL450\n"
+ "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
+ "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
+ "OpExecutionMode %tesse1_main Triangles\n"
+ "OpExecutionMode %tesse2_main Triangles\n"
+ "OpName %tesse1_main \"tesse1\"\n"
+ "OpName %tesse2_main \"tesse2\"\n"
+ "OpName %per_vertex_out \"gl_PerVertex\"\n"
+ "OpMemberName %per_vertex_out 0 \"gl_Position\"\n"
+ "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n"
+ "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n"
+ "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n"
+ "OpName %stream \"\"\n"
+ "OpName %gl_tessCoord \"gl_TessCoord\"\n"
+ "OpName %in_position \"in_position\"\n"
+ "OpName %out_color \"out_color\"\n"
+ "OpName %in_color \"in_color\"\n"
+ "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
+ "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
+ "OpDecorate %per_vertex_out Block\n"
+ "OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
+ "OpDecorate %in_position Location 2\n"
+ "OpDecorate %out_color Location 1\n"
+ "OpDecorate %in_color Location 1\n"
+ SPIRV_ASSEMBLY_TYPES
+ SPIRV_ASSEMBLY_CONSTANTS
+ SPIRV_ASSEMBLY_ARRAYS
+ "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
+ "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
+ "%stream = OpVariable %op_per_vertex_out Output\n"
+ "%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
+ "%in_position = OpVariable %ip_a32v4f32 Input\n"
+ "%out_color = OpVariable %op_v4f32 Output\n"
+ "%in_color = OpVariable %ip_a32v4f32 Input\n"
+
+ "%tesse1_main = OpFunction %void None %fun\n"
+ "%tesse1_label = OpLabel\n"
+ "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
+ "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
+ "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
+ "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
+ "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
+ "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
+ "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
+ "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
+ "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
+ "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
+ "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
+ "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
+ "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_pos_0\n"
+ "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_pos_1\n"
+ "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_pos_2\n"
+ "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
+ "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
+ "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
+ "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
+ "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
+ "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
+ "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
+ "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
+ "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
+ "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
+ "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %in_clr_0\n"
+ "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %in_clr_1\n"
+ "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %in_clr_2\n"
+ "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
+ "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
+ "OpStore %out_color %tesse1_computed_clr\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n"
+
+ "%tesse2_main = OpFunction %void None %fun\n"
+ "%tesse2_label = OpLabel\n"
+ "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
+ "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
+ "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
+ "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
+ "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
+ "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
+ "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
+ "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
+ "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
+ "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
+ "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
+ "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
+ "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_pos_0\n"
+ "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_pos_1\n"
+ "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_pos_2\n"
+ "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
+ "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
+ "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
+ "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
+ "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
+ "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
+ "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
+ "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
+ "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
+ "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
+ "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %in_clr_0\n"
+ "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %in_clr_1\n"
+ "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %in_clr_2\n"
+ "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
+ "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
+ "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
+ "OpStore %out_color %tesse2_clr_transformed\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+}
// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
// Feeds the pipeline a set of colored triangles, which then must occur in the
// rendered image. The surface is cleared before executing the pipeline, so
0.0f, // float slopeScaledDepthBias;
1.0f, // float lineWidth;
};
+
+ const VkPrimitiveTopology topology = instance.hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineInputAssemblyStateCreateFlags)0,
- VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // VkPrimitiveTopology topology;
+ topology, // VkPrimitiveTopology topology;
DE_FALSE, // deUint32 primitiveRestartEnable;
};
const VkVertexInputBindingDescription vertexBinding0 =
3u
};
+ const VkPipelineTessellationStateCreateInfo* tessellationInfo = instance.hasTessellation? &tessellationState: DE_NULL;
const VkGraphicsPipelineCreateInfo pipelineParams =
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
&shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages;
&vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
&inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
- &tessellationState, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
+ tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
&viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
&rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
&multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
}
} // anonymous
+tcu::TestCaseGroup* createOpSourceTests (tcu::TestContext& testCtx)
+{
+ struct NameCodePair { string name, code; };
+ RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsource", "OpSource instruction"));
+ const std::string opsourceGLSLWithFile = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile ";
+ map<string, string> fragments = passthruFragments();
+ const NameCodePair tests[] =
+ {
+ {"unknown", "OpSource Unknown 321"},
+ {"essl", "OpSource ESSL 310"},
+ {"glsl", "OpSource GLSL 450"},
+ {"opencl_cpp", "OpSource OpenCL_CPP 120"},
+ {"opencl_c", "OpSource OpenCL_C 120"},
+ {"multiple", "OpSource GLSL 450\nOpSource GLSL 450"},
+ {"file", opsourceGLSLWithFile},
+ {"source", opsourceGLSLWithFile + "\"void main(){}\""},
+ // Longest possible source string: SPIR-V limits instructions to 65535
+ // words, of which the first 4 are opsourceGLSLWithFile; the rest will
+ // contain 65530 UTF8 characters (one word each) plus one last word
+ // containing 3 ASCII characters and \0.
+ {"longsource", opsourceGLSLWithFile + '"' + makeLongUTF8String(65530) + "ccc" + '"'}
+ };
+
+ getDefaultColors(defaultColors);
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
+ {
+ fragments["debug"] = tests[testNdx].code;
+ createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
+ }
+
+ return opSourceTests.release();
+}
+
+tcu::TestCaseGroup* createOpSourceContinuedTests (tcu::TestContext& testCtx)
+{
+ struct NameCodePair { string name, code; };
+
+ RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsourcecontinued", "OpSourceContinued instruction"));
+ map<string, string> fragments = passthruFragments();
+ const std::string opsource = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile \"void main(){}\"\n";
+ const NameCodePair tests[] =
+ {
+ {"empty", opsource + "OpSourceContinued \"\""},
+ {"short", opsource + "OpSourceContinued \"abcde\""},
+ {"multiple", opsource + "OpSourceContinued \"abcde\"\nOpSourceContinued \"fghij\""},
+ // Longest possible source string: SPIR-V limits instructions to 65535
+ // words, of which the first one is OpSourceContinued/length; the rest
+ // will contain 65533 UTF8 characters (one word each) plus one last word
+ // containing 3 ASCII characters and \0.
+ {"long", opsource + "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\""}
+ };
+
+ getDefaultColors(defaultColors);
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
+ {
+ fragments["debug"] = tests[testNdx].code;
+ createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
+ }
+
+ return opSourceTests.release();
+}
+
+tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
+{
+ RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opNoLine", "OpNoLine instruction"));
+ map<string, string> fragments;
+
+ getDefaultColors(defaultColors);
+ fragments["debug"] =
+ "%name = OpString \"name\"\n";
+
+ fragments["pre_main"] =
+ "OpNoLine\n"
+ "OpNoLine\n"
+ "OpLine %name 1 1\n"
+ "OpNoLine\n"
+ "OpLine %name 1 1\n"
+ "OpLine %name 1 1\n"
+ "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+ "OpNoLine\n"
+ "OpLine %name 1 1\n"
+ "OpNoLine\n"
+ "OpLine %name 1 1\n"
+ "OpLine %name 1 1\n"
+ "%second_param1 = OpFunctionParameter %v4f32\n"
+ "OpNoLine\n"
+ "OpNoLine\n"
+ "%label_secondfunction = OpLabel\n"
+ "OpNoLine\n"
+ "OpReturnValue %second_param1\n"
+ "OpFunctionEnd\n"
+ "OpNoLine\n"
+ "OpNoLine\n";
+
+ fragments["testfun"] =
+ // A %test_code function that returns its argument unchanged.
+ "OpNoLine\n"
+ "OpNoLine\n"
+ "OpLine %name 1 1\n"
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "OpNoLine\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "OpNoLine\n"
+ "OpNoLine\n"
+ "%label_testfun = OpLabel\n"
+ "OpNoLine\n"
+ "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
+ "OpReturnValue %val1\n"
+ "OpFunctionEnd\n"
+ "OpLine %name 1 1\n"
+ "OpNoLine\n";
+
+ createTestsForAllStages("opNoLine", defaultColors, defaultColors, fragments, opLineTests.get());
+
+ return opLineTests.release();
+}
+
+tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
+{
+ RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opLine", "OpLine instruction"));
+ map<string, string> fragments;
+ std::vector<std::pair<std::string, std::string> > problemStrings;
+
+ problemStrings.push_back(std::make_pair<std::string, std::string>("empty_name", ""));
+ problemStrings.push_back(std::make_pair<std::string, std::string>("short_name", "short_name"));
+ problemStrings.push_back(std::make_pair<std::string, std::string>("long_name", makeLongUTF8String(65530) + "ccc"));
+ getDefaultColors(defaultColors);
+
+ fragments["debug"] =
+ "%other_name = OpString \"other_name\"\n";
+
+ fragments["pre_main"] =
+ "OpLine %file_name 32 0\n"
+ "OpLine %file_name 32 32\n"
+ "OpLine %file_name 32 40\n"
+ "OpLine %other_name 32 40\n"
+ "OpLine %other_name 0 100\n"
+ "OpLine %other_name 0 4294967295\n"
+ "OpLine %other_name 4294967295 0\n"
+ "OpLine %other_name 32 40\n"
+ "OpLine %file_name 0 0\n"
+ "%second_function = OpFunction %v4f32 None %v4f32_function\n"
+ "OpLine %file_name 1 0\n"
+ "%second_param1 = OpFunctionParameter %v4f32\n"
+ "OpLine %file_name 1 3\n"
+ "OpLine %file_name 1 2\n"
+ "%label_secondfunction = OpLabel\n"
+ "OpLine %file_name 0 2\n"
+ "OpReturnValue %second_param1\n"
+ "OpFunctionEnd\n"
+ "OpLine %file_name 0 2\n"
+ "OpLine %file_name 0 2\n";
+
+ fragments["testfun"] =
+ // A %test_code function that returns its argument unchanged.
+ "OpLine %file_name 1 0\n"
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "OpLine %file_name 16 330\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "OpLine %file_name 14 442\n"
+ "%label_testfun = OpLabel\n"
+ "OpLine %file_name 11 1024\n"
+ "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
+ "OpLine %file_name 2 97\n"
+ "OpReturnValue %val1\n"
+ "OpFunctionEnd\n"
+ "OpLine %file_name 5 32\n";
+
+ for (size_t i = 0; i < problemStrings.size(); ++i)
+ {
+ map<string, string> testFragments = fragments;
+ testFragments["debug"] += "%file_name = OpString \"" + problemStrings[i].second + "\"\n";
+ createTestsForAllStages(string("opLine") + "-" + problemStrings[i].first, defaultColors, defaultColors, testFragments, opLineTests.get());
+ }
+
+ return opLineTests.release();
+}
+
+tcu::TestCaseGroup* createOpConstantNullTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> opConstantNullTests (new tcu::TestCaseGroup(testCtx, "opConstantNull", "OpConstantNull instruction"));
+ RGBA colors[4];
+
+ const char functionStart[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n";
+
+ const char functionEnd[] =
+ "OpReturnValue %transformed_param\n"
+ "OpFunctionEnd\n";
+
+ struct NameConstantsCode
+ {
+ string name;
+ string constants;
+ string code;
+ };
+
+ NameConstantsCode tests[] =
+ {
+ {
+ "vec4",
+ "%cnull = OpConstantNull %v4f32\n",
+ "%transformed_param = OpFAdd %v4f32 %param1 %cnull\n"
+ },
+ {
+ "float",
+ "%cnull = OpConstantNull %f32\n",
+ "%vp = OpVariable %fp_v4f32 Function\n"
+ "%v = OpLoad %v4f32 %vp\n"
+ "%v0 = OpVectorInsertDynamic %v4f32 %v %cnull %c_i32_0\n"
+ "%v1 = OpVectorInsertDynamic %v4f32 %v0 %cnull %c_i32_1\n"
+ "%v2 = OpVectorInsertDynamic %v4f32 %v1 %cnull %c_i32_2\n"
+ "%v3 = OpVectorInsertDynamic %v4f32 %v2 %cnull %c_i32_3\n"
+ "%transformed_param = OpFAdd %v4f32 %param1 %v3\n"
+ },
+ {
+ "bool",
+ "%cnull = OpConstantNull %bool\n",
+ "%v = OpVariable %fp_v4f32 Function\n"
+ " OpStore %v %param1\n"
+ " OpSelectionMerge %false_label None\n"
+ " OpBranchConditional %cnull %true_label %false_label\n"
+ "%true_label = OpLabel\n"
+ " OpStore %v %c_v4f32_0_5_0_5_0_5_0_5\n"
+ " OpBranch %false_label\n"
+ "%false_label = OpLabel\n"
+ "%transformed_param = OpLoad %v4f32 %v\n"
+ },
+ {
+ "i32",
+ "%cnull = OpConstantNull %i32\n",
+ "%v = OpVariable %fp_v4f32 Function %c_v4f32_0_5_0_5_0_5_0_5\n"
+ "%b = OpIEqual %bool %cnull %c_i32_0\n"
+ " OpSelectionMerge %false_label None\n"
+ " OpBranchConditional %b %true_label %false_label\n"
+ "%true_label = OpLabel\n"
+ " OpStore %v %param1\n"
+ " OpBranch %false_label\n"
+ "%false_label = OpLabel\n"
+ "%transformed_param = OpLoad %v4f32 %v\n"
+ },
+ {
+ "struct",
+ "%stype = OpTypeStruct %f32 %v4f32\n"
+ "%fp_stype = OpTypePointer Function %stype\n"
+ "%cnull = OpConstantNull %stype\n",
+ "%v = OpVariable %fp_stype Function %cnull\n"
+ "%f = OpAccessChain %fp_v4f32 %v %c_i32_1\n"
+ "%f_val = OpLoad %v4f32 %f\n"
+ "%transformed_param = OpFAdd %v4f32 %param1 %f_val\n"
+ },
+ {
+ "array",
+ "%a4_v4f32 = OpTypeArray %v4f32 %c_u32_4\n"
+ "%fp_a4_v4f32 = OpTypePointer Function %a4_v4f32\n"
+ "%cnull = OpConstantNull %a4_v4f32\n",
+ "%v = OpVariable %fp_a4_v4f32 Function %cnull\n"
+ "%f = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
+ "%f1 = OpAccessChain %fp_v4f32 %v %c_u32_1\n"
+ "%f2 = OpAccessChain %fp_v4f32 %v %c_u32_2\n"
+ "%f3 = OpAccessChain %fp_v4f32 %v %c_u32_3\n"
+ "%f_val = OpLoad %v4f32 %f\n"
+ "%f1_val = OpLoad %v4f32 %f1\n"
+ "%f2_val = OpLoad %v4f32 %f2\n"
+ "%f3_val = OpLoad %v4f32 %f3\n"
+ "%t0 = OpFAdd %v4f32 %param1 %f_val\n"
+ "%t1 = OpFAdd %v4f32 %t0 %f1_val\n"
+ "%t2 = OpFAdd %v4f32 %t1 %f2_val\n"
+ "%transformed_param = OpFAdd %v4f32 %t2 %f3_val\n"
+ },
+ {
+ "matrix",
+ "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
+ "%cnull = OpConstantNull %mat4x4_f32\n",
+ // Our null matrix * any vector should result in a zero vector.
+ "%v = OpVectorTimesMatrix %v4f32 %param1 %cnull\n"
+ "%transformed_param = OpFAdd %v4f32 %param1 %v\n"
+ }
+ };
+
+ getHalfColorsFullAlpha(colors);
+
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
+ {
+ map<string, string> fragments;
+ fragments["pre_main"] = tests[testNdx].constants;
+ fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
+ createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, opConstantNullTests.get());
+ }
+ return opConstantNullTests.release();
+}
+tcu::TestCaseGroup* createOpConstantCompositeTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> opConstantCompositeTests (new tcu::TestCaseGroup(testCtx, "opConstantComposite", "OpConstantComposite instruction"));
+ RGBA inputColors[4];
+ RGBA outputColors[4];
+
+ const char functionStart[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n";
+
+ const char functionEnd[] =
+ "OpReturnValue %transformed_param\n"
+ "OpFunctionEnd\n";
+
+ struct NameConstantsCode
+ {
+ string name;
+ string constants;
+ string code;
+ };
+
+ NameConstantsCode tests[] =
+ {
+ {
+ "vec4",
+
+ "%cval = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0\n",
+ "%transformed_param = OpFAdd %v4f32 %param1 %cval\n"
+ },
+ {
+ "struct",
+
+ "%stype = OpTypeStruct %v4f32 %f32\n"
+ "%fp_stype = OpTypePointer Function %stype\n"
+ "%f32_n_1 = OpConstant %f32 -1.0\n"
+ "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
+ "%cvec = OpConstantComposite %v4f32 %f32_1_5 %f32_1_5 %f32_1_5 %c_f32_1\n"
+ "%cval = OpConstantComposite %stype %cvec %f32_n_1\n",
+
+ "%v = OpVariable %fp_stype Function %cval\n"
+ "%vec_ptr = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
+ "%f32_ptr = OpAccessChain %fp_v4f32 %v %c_u32_1\n"
+ "%vec_val = OpLoad %v4f32 %vec_ptr\n"
+ "%f32_val = OpLoad %v4f32 %f32_ptr\n"
+ "%tmp1 = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_1 %f32_val\n" // vec4(-1)
+ "%tmp2 = OpFAdd %v4f32 %tmp1 %param1\n" // param1 + vec4(-1)
+ "%transformed_param = OpFAdd %v4f32 %tmp2 %vec_val\n" // param1 + vec4(-1) + vec4(1.5, 1.5, 1.5, 1.0)
+ },
+ {
+ // [1|0|0|0.5] [x] = x + 0.5
+ // [0|1|0|0.5] [y] = y + 0.5
+ // [0|0|1|0.5] [z] = z + 0.5
+ // [0|0|0|1 ] [1] = 1
+ "matrix",
+
+ "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
+ "%v4f32_1_0_0_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_0\n"
+ "%v4f32_0_1_0_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_1 %c_f32_0 %c_f32_0\n"
+ "%v4f32_0_0_1_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_1 %c_f32_0\n"
+ "%v4f32_0_5_0_5_0_5_1 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_1\n"
+ "%cval = OpConstantComposite %mat4x4_f32 %v4f32_1_0_0_0 %v4f32_0_1_0_0 %v4f32_0_0_1_0 %v4f32_0_5_0_5_0_5_1\n",
+
+ "%transformed_param = OpMatrixTimesVector %v4f32 %cval %param1\n"
+ },
+ {
+ "array",
+
+ "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%fp_a4f32 = OpTypePointer Function %a4f32\n"
+ "%f32_n_1 = OpConstant %f32 -1.0\n"
+ "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
+ "%carr = OpConstantComposite %a4f32 %c_f32_0 %f32_n_1 %f32_1_5 %c_f32_0\n",
+
+ "%v = OpVariable %fp_a4f32 Function %carr\n"
+ "%f = OpAccessChain %fp_f32 %v %c_u32_0\n"
+ "%f1 = OpAccessChain %fp_f32 %v %c_u32_1\n"
+ "%f2 = OpAccessChain %fp_f32 %v %c_u32_2\n"
+ "%f3 = OpAccessChain %fp_f32 %v %c_u32_3\n"
+ "%f_val = OpLoad %f32 %f\n"
+ "%f1_val = OpLoad %f32 %f1\n"
+ "%f2_val = OpLoad %f32 %f2\n"
+ "%f3_val = OpLoad %f32 %f3\n"
+ "%ftot1 = OpFAdd %f32 %f_val %f1_val\n"
+ "%ftot2 = OpFAdd %f32 %ftot1 %f2_val\n"
+ "%ftot3 = OpFAdd %f32 %ftot2 %f3_val\n" // 0 - 1 + 1.5 + 0
+ "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %ftot3\n"
+ "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
+ },
+ {
+ //
+ // [
+ // {
+ // 0.0,
+ // [ 1.0, 1.0, 1.0, 1.0]
+ // },
+ // {
+ // 1.0,
+ // [ 0.0, 0.5, 0.0, 0.0]
+ // }, // ^^^
+ // {
+ // 0.0,
+ // [ 1.0, 1.0, 1.0, 1.0]
+ // }
+ // ]
+ "array_of_struct_of_array",
+
+ "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
+ "%fp_a4f32 = OpTypePointer Function %a4f32\n"
+ "%stype = OpTypeStruct %f32 %a4f32\n"
+ "%a3stype = OpTypeArray %stype %c_u32_3\n"
+ "%fp_a3stype = OpTypePointer Function %a3stype\n"
+ "%ca4f32_0 = OpConstantComposite %a4f32 %c_f32_0 %c_f32_0_5 %c_f32_0 %c_f32_0\n"
+ "%ca4f32_1 = OpConstantComposite %a4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
+ "%cstype1 = OpConstantComposite %stype %c_f32_0 %ca4f32_1\n"
+ "%cstype2 = OpConstantComposite %stype %c_f32_1 %ca4f32_0\n"
+ "%carr = OpConstantComposite %a3stype %cstype1 %cstype2 %cstype1",
+
+ "%v = OpVariable %fp_a3stype Function %carr\n"
+ "%f = OpAccessChain %fp_f32 %v %c_u32_1 %c_u32_1 %c_u32_1\n"
+ "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %f\n"
+ "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
+ }
+ };
+
+ getHalfColorsFullAlpha(inputColors);
+ outputColors[0] = RGBA(255, 255, 255, 255);
+ outputColors[1] = RGBA(255, 127, 127, 255);
+ outputColors[2] = RGBA(127, 255, 127, 255);
+ outputColors[3] = RGBA(127, 127, 255, 255);
+
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
+ {
+ map<string, string> fragments;
+ fragments["pre_main"] = tests[testNdx].constants;
+ fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
+ createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, opConstantCompositeTests.get());
+ }
+ return opConstantCompositeTests.release();
+}
+
+tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_block_order", "Out-of-order blocks for selection"));
+ RGBA inputColors[4];
+ RGBA outputColors[4];
+ map<string, string> fragments;
+
+ // vec4 test_code(vec4 param) {
+ // vec4 result = param;
+ // for (int i = 0; i < 4; ++i) {
+ // if (i == 0) result[i] = 0.;
+ // else result[i] = 1. - result[i];
+ // }
+ // return result;
+ // }
+ const char function[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n"
+ "%iptr = OpVariable %fp_i32 Function\n"
+ " OpStore %iptr %c_i32_0\n"
+ "%result = OpVariable %fp_v4f32 Function\n"
+ " OpStore %result %param1\n"
+ " OpBranch %loop\n"
+
+ // Loop entry block.
+ "%loop = OpLabel\n"
+ "%ival = OpLoad %i32 %iptr\n"
+ "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
+ " OpLoopMerge %exit %loop None\n"
+ " OpBranchConditional %lt_4 %if_entry %exit\n"
+
+ // Merge block for loop.
+ "%exit = OpLabel\n"
+ "%ret = OpLoad %v4f32 %result\n"
+ " OpReturnValue %ret\n"
+
+ // If-statement entry block.
+ "%if_entry = OpLabel\n"
+ "%loc = OpAccessChain %fp_f32 %result %ival\n"
+ "%eq_0 = OpIEqual %bool %ival %c_i32_0\n"
+ " OpSelectionMerge %if_exit None\n"
+ " OpBranchConditional %eq_0 %if_true %if_false\n"
+
+ // False branch for if-statement.
+ "%if_false = OpLabel\n"
+ "%val = OpLoad %f32 %loc\n"
+ "%sub = OpFSub %f32 %c_f32_1 %val\n"
+ " OpStore %loc %sub\n"
+ " OpBranch %if_exit\n"
+
+ // Merge block for if-statement.
+ "%if_exit = OpLabel\n"
+ "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
+ " OpStore %iptr %ival_next\n"
+ " OpBranch %loop\n"
+
+ // True branch for if-statement.
+ "%if_true = OpLabel\n"
+ " OpStore %loc %c_f32_0\n"
+ " OpBranch %if_exit\n"
+
+ " OpFunctionEnd\n";
+
+ fragments["testfun"] = function;
+
+ inputColors[0] = RGBA(127, 127, 127, 0);
+ inputColors[1] = RGBA(127, 0, 0, 0);
+ inputColors[2] = RGBA(0, 127, 0, 0);
+ inputColors[3] = RGBA(0, 0, 127, 0);
+
+ outputColors[0] = RGBA(0, 128, 128, 255);
+ outputColors[1] = RGBA(0, 255, 255, 255);
+ outputColors[2] = RGBA(0, 128, 255, 255);
+ outputColors[3] = RGBA(0, 255, 128, 255);
+
+ createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "switch_block_order", "Out-of-order blocks for switch"));
+ RGBA inputColors[4];
+ RGBA outputColors[4];
+ map<string, string> fragments;
+
+ const char typesAndConstants[] =
+ "%c_f32_p2 = OpConstant %f32 0.2\n"
+ "%c_f32_p4 = OpConstant %f32 0.4\n"
+ "%c_f32_p6 = OpConstant %f32 0.6\n"
+ "%c_f32_p8 = OpConstant %f32 0.8\n";
+
+ // vec4 test_code(vec4 param) {
+ // vec4 result = param;
+ // for (int i = 0; i < 4; ++i) {
+ // switch (i) {
+ // case 0: result[i] += .2; break;
+ // case 1: result[i] += .6; break;
+ // case 2: result[i] += .4; break;
+ // case 3: result[i] += .8; break;
+ // default: break; // unreachable
+ // }
+ // }
+ // return result;
+ // }
+ const char function[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n"
+ "%iptr = OpVariable %fp_i32 Function\n"
+ " OpStore %iptr %c_i32_0\n"
+ "%result = OpVariable %fp_v4f32 Function\n"
+ " OpStore %result %param1\n"
+ " OpBranch %loop\n"
+
+ // Loop entry block.
+ "%loop = OpLabel\n"
+ "%ival = OpLoad %i32 %iptr\n"
+ "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
+ " OpLoopMerge %exit %loop None\n"
+ " OpBranchConditional %lt_4 %switch_entry %exit\n"
+
+ // Merge block for loop.
+ "%exit = OpLabel\n"
+ "%ret = OpLoad %v4f32 %result\n"
+ " OpReturnValue %ret\n"
+
+ // Switch-statement entry block.
+ "%switch_entry = OpLabel\n"
+ "%loc = OpAccessChain %fp_f32 %result %ival\n"
+ "%val = OpLoad %f32 %loc\n"
+ " OpSelectionMerge %switch_exit None\n"
+ " OpSwitch %ival %switch_default 0 %case0 1 %case1 2 %case2 3 %case3\n"
+
+ "%case2 = OpLabel\n"
+ "%addp4 = OpFAdd %f32 %val %c_f32_p4\n"
+ " OpStore %loc %addp4\n"
+ " OpBranch %switch_exit\n"
+
+ "%switch_default = OpLabel\n"
+ " OpUnreachable\n"
+
+ "%case3 = OpLabel\n"
+ "%addp8 = OpFAdd %f32 %val %c_f32_p8\n"
+ " OpStore %loc %addp8\n"
+ " OpBranch %switch_exit\n"
+
+ "%case0 = OpLabel\n"
+ "%addp2 = OpFAdd %f32 %val %c_f32_p2\n"
+ " OpStore %loc %addp2\n"
+ " OpBranch %switch_exit\n"
+
+ // Merge block for switch-statement.
+ "%switch_exit = OpLabel\n"
+ "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
+ " OpStore %iptr %ival_next\n"
+ " OpBranch %loop\n"
+
+ "%case1 = OpLabel\n"
+ "%addp6 = OpFAdd %f32 %val %c_f32_p6\n"
+ " OpStore %loc %addp6\n"
+ " OpBranch %switch_exit\n"
+
+ " OpFunctionEnd\n";
+
+ fragments["pre_main"] = typesAndConstants;
+ fragments["testfun"] = function;
+
+ inputColors[0] = RGBA(127, 27, 127, 51);
+ inputColors[1] = RGBA(127, 0, 0, 51);
+ inputColors[2] = RGBA(0, 27, 0, 51);
+ inputColors[3] = RGBA(0, 0, 127, 51);
+
+ outputColors[0] = RGBA(178, 180, 229, 255);
+ outputColors[1] = RGBA(178, 153, 102, 255);
+ outputColors[2] = RGBA(51, 180, 102, 255);
+ outputColors[3] = RGBA(51, 153, 229, 255);
+
+ createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
+ RGBA inputColors[4];
+ RGBA outputColors1[4];
+ RGBA outputColors2[4];
+ RGBA outputColors3[4];
+ map<string, string> fragments1;
+ map<string, string> fragments2;
+ map<string, string> fragments3;
+
+ const char typesAndConstants1[] =
+ "%c_f32_p2 = OpConstant %f32 0.2\n"
+ "%c_f32_p4 = OpConstant %f32 0.4\n"
+ "%c_f32_p6 = OpConstant %f32 0.6\n"
+ "%c_f32_p8 = OpConstant %f32 0.8\n";
+
+ // vec4 test_code(vec4 param) {
+ // vec4 result = param;
+ // for (int i = 0; i < 4; ++i) {
+ // float operand;
+ // switch (i) {
+ // case 0: operand = .2; break;
+ // case 1: operand = .6; break;
+ // case 2: operand = .4; break;
+ // case 3: operand = .0; break;
+ // default: break; // unreachable
+ // }
+ // result[i] += operand;
+ // }
+ // return result;
+ // }
+ const char function1[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n"
+ "%iptr = OpVariable %fp_i32 Function\n"
+ " OpStore %iptr %c_i32_0\n"
+ "%result = OpVariable %fp_v4f32 Function\n"
+ " OpStore %result %param1\n"
+ " OpBranch %loop\n"
+
+ "%loop = OpLabel\n"
+ "%ival = OpLoad %i32 %iptr\n"
+ "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
+ " OpLoopMerge %exit %loop None\n"
+ " OpBranchConditional %lt_4 %entry %exit\n"
+
+ "%entry = OpLabel\n"
+ "%loc = OpAccessChain %fp_f32 %result %ival\n"
+ "%val = OpLoad %f32 %loc\n"
+ " OpSelectionMerge %phi None\n"
+ " OpSwitch %ival %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
+
+ "%case0 = OpLabel\n"
+ " OpBranch %phi\n"
+ "%case1 = OpLabel\n"
+ " OpBranch %phi\n"
+ "%case2 = OpLabel\n"
+ " OpBranch %phi\n"
+ "%case3 = OpLabel\n"
+ " OpBranch %phi\n"
+
+ "%default = OpLabel\n"
+ " OpUnreachable\n"
+
+ "%phi = OpLabel\n"
+ "%operand = OpPhi %f32 %c_f32_p4 %case2 %c_f32_p6 %case1 %c_f32_p2 %case0 %c_f32_0 %case3\n" // not in the order of blocks
+ "%add = OpFAdd %f32 %val %operand\n"
+ " OpStore %loc %add\n"
+ "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
+ " OpStore %iptr %ival_next\n"
+ " OpBranch %loop\n"
+
+ "%exit = OpLabel\n"
+ "%ret = OpLoad %v4f32 %result\n"
+ " OpReturnValue %ret\n"
+
+ " OpFunctionEnd\n";
+
+ fragments1["pre_main"] = typesAndConstants1;
+ fragments1["testfun"] = function1;
+
+ getHalfColorsFullAlpha(inputColors);
+
+ outputColors1[0] = RGBA(178, 180, 229, 255);
+ outputColors1[1] = RGBA(178, 153, 102, 255);
+ outputColors1[2] = RGBA(51, 180, 102, 255);
+ outputColors1[3] = RGBA(51, 153, 229, 255);
+
+ createTestsForAllStages("out_of_order", inputColors, outputColors1, fragments1, group.get());
+
+ const char typesAndConstants2[] =
+ "%c_f32_p2 = OpConstant %f32 0.2\n";
+
+ // Add .4 to the second element of the given parameter.
+ const char function2[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param = OpFunctionParameter %v4f32\n"
+ "%entry = OpLabel\n"
+ "%result = OpVariable %fp_v4f32 Function\n"
+ " OpStore %result %param\n"
+ "%loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
+ "%val = OpLoad %f32 %loc\n"
+ " OpBranch %phi\n"
+
+ "%phi = OpLabel\n"
+ "%step = OpPhi %i32 %c_i32_0 %entry %step_next %phi\n"
+ "%accum = OpPhi %f32 %val %entry %accum_next %phi\n"
+ "%step_next = OpIAdd %i32 %step %c_i32_1\n"
+ "%accum_next = OpFAdd %f32 %accum %c_f32_p2\n"
+ "%still_loop = OpSLessThan %bool %step %c_i32_2\n"
+ " OpLoopMerge %exit %phi None\n"
+ " OpBranchConditional %still_loop %phi %exit\n"
+
+ "%exit = OpLabel\n"
+ " OpStore %loc %accum\n"
+ "%ret = OpLoad %v4f32 %result\n"
+ " OpReturnValue %ret\n"
+
+ " OpFunctionEnd\n";
+
+ fragments2["pre_main"] = typesAndConstants2;
+ fragments2["testfun"] = function2;
+
+ outputColors2[0] = RGBA(127, 229, 127, 255);
+ outputColors2[1] = RGBA(127, 102, 0, 255);
+ outputColors2[2] = RGBA(0, 229, 0, 255);
+ outputColors2[3] = RGBA(0, 102, 127, 255);
+
+ createTestsForAllStages("induction", inputColors, outputColors2, fragments2, group.get());
+
+ const char typesAndConstants3[] =
+ "%true = OpConstantTrue %bool\n"
+ "%false = OpConstantFalse %bool\n"
+ "%c_f32_p2 = OpConstant %f32 0.2\n";
+
+ // Swap the second and the third element of the given parameter.
+ const char function3[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param = OpFunctionParameter %v4f32\n"
+ "%entry = OpLabel\n"
+ "%result = OpVariable %fp_v4f32 Function\n"
+ " OpStore %result %param\n"
+ "%a_loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
+ "%a_init = OpLoad %f32 %a_loc\n"
+ "%b_loc = OpAccessChain %fp_f32 %result %c_i32_2\n"
+ "%b_init = OpLoad %f32 %b_loc\n"
+ " OpBranch %phi\n"
+
+ "%phi = OpLabel\n"
+ "%still_loop = OpPhi %bool %true %entry %false %phi\n"
+ "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n"
+ "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n"
+ " OpLoopMerge %exit %phi None\n"
+ " OpBranchConditional %still_loop %phi %exit\n"
+
+ "%exit = OpLabel\n"
+ " OpStore %a_loc %a_next\n"
+ " OpStore %b_loc %b_next\n"
+ "%ret = OpLoad %v4f32 %result\n"
+ " OpReturnValue %ret\n"
+
+ " OpFunctionEnd\n";
+
+ fragments3["pre_main"] = typesAndConstants3;
+ fragments3["testfun"] = function3;
+
+ outputColors3[0] = RGBA(127, 127, 127, 255);
+ outputColors3[1] = RGBA(127, 0, 0, 255);
+ outputColors3[2] = RGBA(0, 0, 127, 255);
+ outputColors3[3] = RGBA(0, 127, 0, 255);
+
+ createTestsForAllStages("swap", inputColors, outputColors3, fragments3, group.get());
+
+ return group.release();
+}
+
+tcu::TestCaseGroup* createMemoryAccessTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> memoryAccessTests (new tcu::TestCaseGroup(testCtx, "opMemoryAccess", "Memory Semantics"));
+ RGBA colors[4];
+
+ const char constantsAndTypes[] =
+ "%c_a2f32_1 = OpConstantComposite %a2f32 %c_f32_1 %c_f32_1\n"
+ "%fp_a2f32 = OpTypePointer Function %a2f32\n"
+ "%stype = OpTypeStruct %v4f32 %a2f32 %f32\n"
+ "%fp_stype = OpTypePointer Function %stype\n";
+
+ const char function[] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%lbl = OpLabel\n"
+ "%v1 = OpVariable %fp_v4f32 Function\n"
+ " OpStore %v1 %c_v4f32_1_1_1_1\n"
+ "%v2 = OpVariable %fp_a2f32 Function\n"
+ " OpStore %v2 %c_a2f32_1\n"
+ "%v3 = OpVariable %fp_f32 Function\n"
+ " OpStore %v3 %c_f32_1\n"
+
+ "%v = OpVariable %fp_stype Function\n"
+
+ "%vv = OpVariable %fp_stype Function\n"
+ "%vvv = OpVariable %fp_f32 Function\n"
+
+ "%p_v4f32 = OpAccessChain %fp_v4_f32 %v %c_u32_0\n"
+ "%p_a2f32 = OpAccessChain %fp_a2f32 %v %c_u32_1\n"
+ "%p_f32 = OpAccessChain %fp_f32 %v %c_u32_2\n"
+ "%v1_v = OpLoad %v4f32 %v1 ${access_type}\n"
+ "%v2_v = OpLoad %a2f32 %v2 ${access_type}\n"
+ "%v3_v = OpLoad %f32 %v3 ${access_type}\n"
+
+ " OpStore %p_v4f32 %v1_v ${access_type}\n"
+ " OpStore %p_a2f32 %v2_v ${access_type}\n"
+ " OpStore %p_f32 %v3_v ${access_type}\n"
+
+ " OpCopyMemory %vv %v ${access_type}\n"
+ " OpCopyMemory %vvv %p_f32 ${access_type}\n"
+
+ "%p_f32_2 = OpAccessChain %fp_f32 %vv %c_u32_2\n"
+ "%v_f32_2 = OpLoad %f32 %p_f32_2\n"
+ "%v_f32_3 = OpLoad %f32 %vvv\n"
+
+ "%ret1 = OpVectorTimesScalar %v4f32 %param1 %v_f32_2\n"
+ "%ret2 = OpVectorTimesScalar %v4f32 %ret1 %v_f32_3\n"
+ " OpReturnValue %ret2\n"
+ " OpFunctionEnd\n";
+
+ struct NameMemoryAccess
+ {
+ string name;
+ string accessType;
+ };
+
+ NameMemoryAccess tests[] =
+ {
+ { "none", "" },
+ { "volatile", "Volatile" },
+ { "aligned", "Aligned 1" },
+ { "volatile-aligned", "Volatile|Aligned 1" },
+ { "nontemporal-aligned", "Nontemporal|Aligned 1" },
+ { "volatile-nontemporal", "Volatile|Nontemporal" },
+ { "volatile-nontermporal-aligned", "Volatile|NonTermporal|Aligned" },
+ };
+
+ getHalfColorsFullAlpha(colors);
+
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameMemoryAccess); ++testNdx)
+ {
+ map<string, string> fragments;
+ map<string, string> memoryAccess;
+ memoryAccess["access_type"] = tests[testNdx].accessType;
+
+ fragments["pre_main"] = constantsAndTypes;
+ fragments["testfun"] = tcu::StringTemplate(function).specialize(memoryAccess);
+ createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, memoryAccessTests.get());
+ }
+ return memoryAccessTests.release();
+}
+
+tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> opUndefTests (new tcu::TestCaseGroup(testCtx, "opundef", "Test OpUndef"));
+ RGBA defaultColors[4];
+ map<string, string> fragments;
+
+ getDefaultColors(defaultColors);
+ // First, simple cases that don't do anything with the OpUndef result.
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %type\n"
+ "OpReturnValue %param1\n"
+ "OpFunctionEnd\n"
+ ;
+ struct NameCodePair { string name, code; };
+ const NameCodePair tests[] =
+ {
+ {"bool", "%type = OpTypeBool"},
+ {"vec2uint32", "%type = OpTypeVector %u32 2"},
+ {"image", "%type = OpTypeImage %f32 2D 0 0 0 0 Unknown"},
+ {"sampler", "%type = OpTypeSampler"},
+ {"sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 0 Unknown\n" "%type = OpTypeSampledImage %img"},
+ {"function", "%type = OpTypeFunction %void %i32 %f32"},
+ {"pointer", "%type = OpTypePointer Function %i32"},
+ {"runtimearray", "%type = OpTypeRuntimeArray %f32"},
+ {"array", "%c_u32_100 = OpConstant %u32 100\n" "%type = OpTypeArray %i32 %c_u32_100"},
+ {"struct", "%type = OpTypeStruct %f32 %i32 %u32"}};
+ for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
+ {
+ fragments["pre_main"] = tests[testNdx].code;
+ createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opUndefTests.get());
+ }
+ fragments.clear();
+
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %f32\n"
+ "%zero = OpFMul %f32 %undef %c_f32_0\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %zero\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %b %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get());
+
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %i32\n"
+ "%zero = OpIMul %i32 %undef %c_i32_0\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get());
+
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %u32\n"
+ "%zero = OpIMul %u32 %undef %c_i32_0\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get());
+
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %v4f32\n"
+ "%vzero = OpVectorTimesScalar %v4f32 %undef %c_f32_0\n"
+ "%zero_0 = OpVectorExtractDynamic %f32 %vzero %c_i32_0\n"
+ "%zero_1 = OpVectorExtractDynamic %f32 %vzero %c_i32_1\n"
+ "%zero_2 = OpVectorExtractDynamic %f32 %vzero %c_i32_2\n"
+ "%zero_3 = OpVectorExtractDynamic %f32 %vzero %c_i32_3\n"
+ "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
+ "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
+ "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
+ "%sum_0 = OpFAdd %f32 %param1_0 %zero_0\n"
+ "%sum_1 = OpFAdd %f32 %param1_1 %zero_1\n"
+ "%sum_2 = OpFAdd %f32 %param1_2 %zero_2\n"
+ "%sum_3 = OpFAdd %f32 %param1_3 %zero_3\n"
+ "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
+ "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
+ "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get());
+
+ fragments["pre_main"] =
+ "%v2f32 = OpTypeVector %f32 2\n"
+ "%m2x2f32 = OpTypeMatrix %v2f32 2\n";
+ fragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "%undef = OpUndef %m2x2f32\n"
+ "%mzero = OpMatrixTimesScalar %m2x2f32 %undef %c_f32_0\n"
+ "%zero_0 = OpCompositeExtract %f32 %mzero 0 0\n"
+ "%zero_1 = OpCompositeExtract %f32 %mzero 0 1\n"
+ "%zero_2 = OpCompositeExtract %f32 %mzero 1 0\n"
+ "%zero_3 = OpCompositeExtract %f32 %mzero 1 1\n"
+ "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
+ "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
+ "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
+ "%sum_0 = OpFAdd %f32 %param1_0 %zero_0\n"
+ "%sum_1 = OpFAdd %f32 %param1_1 %zero_1\n"
+ "%sum_2 = OpFAdd %f32 %param1_2 %zero_2\n"
+ "%sum_3 = OpFAdd %f32 %param1_3 %zero_3\n"
+ "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
+ "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
+ "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, opUndefTests.get());
+
+ return opUndefTests.release();
+}
+
+struct ShaderPermutation
+{
+ deUint8 vertexPermutation;
+ deUint8 geometryPermutation;
+ deUint8 tesscPermutation;
+ deUint8 tessePermutation;
+ deUint8 fragmentPermutation;
+};
+
+ShaderPermutation getShaderPermutation(deUint8 inputValue)
+{
+ ShaderPermutation permutation =
+ {
+ static_cast<deUint8>(inputValue & 0x10? 1u: 0u),
+ static_cast<deUint8>(inputValue & 0x08? 1u: 0u),
+ static_cast<deUint8>(inputValue & 0x04? 1u: 0u),
+ static_cast<deUint8>(inputValue & 0x02? 1u: 0u),
+ static_cast<deUint8>(inputValue & 0x01? 1u: 0u)
+ };
+ return permutation;
+}
+
+tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx)
+{
+ RGBA defaultColors[4];
+ 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>()));
+
+ const char* numbers[] =
+ {
+ "1", "2"
+ };
+
+ for (deInt8 idx = 0; idx < 32; ++idx)
+ {
+ ShaderPermutation permutation = getShaderPermutation(idx);
+ string name = string("vert") + numbers[permutation.vertexPermutation] + "-geom" + numbers[permutation.geometryPermutation] + "-tessc" + numbers[permutation.tesscPermutation] + "-tesse" + numbers[permutation.tessePermutation] + "-frag" + numbers[permutation.fragmentPermutation];
+ const ShaderElement pipeline[] =
+ {
+ ShaderElement("vert", string("vert") + numbers[permutation.vertexPermutation], VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("geom", string("geom") + numbers[permutation.geometryPermutation], VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("tessc", string("tessc") + numbers[permutation.tesscPermutation], VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("tesse", string("tesse") + numbers[permutation.tessePermutation], VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("frag", string("frag") + numbers[permutation.fragmentPermutation], VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ // If there are an even number of swaps, then it should be no-op.
+ // If there are an odd number, the color should be flipped.
+ if ((permutation.vertexPermutation + permutation.geometryPermutation + permutation.tesscPermutation + permutation.tessePermutation + permutation.fragmentPermutation) % 2 == 0)
+ {
+ addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, defaultColors, map<string, string>()));
+ }
+ else
+ {
+ addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, invertedColors, map<string, string>()));
+ }
+ }
+ return moduleTests.release();
+}
tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
{
- de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
-
- instructionTests->addChild(createOpNopGroup(testCtx));
- instructionTests->addChild(createOpLineGroup(testCtx));
- instructionTests->addChild(createOpNoLineGroup(testCtx));
- instructionTests->addChild(createOpConstantNullGroup(testCtx));
- instructionTests->addChild(createOpConstantCompositeGroup(testCtx));
- instructionTests->addChild(createOpConstantUsageGroup(testCtx));
- instructionTests->addChild(createSpecConstantGroup(testCtx));
- instructionTests->addChild(createOpSourceGroup(testCtx));
- instructionTests->addChild(createOpSourceExtensionGroup(testCtx));
- instructionTests->addChild(createDecorationGroupGroup(testCtx));
- instructionTests->addChild(createOpPhiGroup(testCtx));
- instructionTests->addChild(createLoopControlGroup(testCtx));
- instructionTests->addChild(createFunctionControlGroup(testCtx));
- instructionTests->addChild(createSelectionControlGroup(testCtx));
- instructionTests->addChild(createBlockOrderGroup(testCtx));
- instructionTests->addChild(createMultipleShaderGroup(testCtx));
- instructionTests->addChild(createMemoryAccessGroup(testCtx));
- instructionTests->addChild(createOpCopyMemoryGroup(testCtx));
- instructionTests->addChild(createOpCopyObjectGroup(testCtx));
- instructionTests->addChild(createNoContractionGroup(testCtx));
- instructionTests->addChild(createOpUndefGroup(testCtx));
- instructionTests->addChild(createOpUnreachableGroup(testCtx));
- instructionTests->addChild(createOpQuantizeToF16Group(testCtx));
-
- RGBA defaultColors[4];
+ de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
+ de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Compute Instructions with special opcodes/operands"));
+ de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Graphics Instructions with special opcodes/operands"));
+
+ computeTests->addChild(createOpNopGroup(testCtx));
+ computeTests->addChild(createOpLineGroup(testCtx));
+ computeTests->addChild(createOpNoLineGroup(testCtx));
+ computeTests->addChild(createOpConstantNullGroup(testCtx));
+ computeTests->addChild(createOpConstantCompositeGroup(testCtx));
+ computeTests->addChild(createOpConstantUsageGroup(testCtx));
+ computeTests->addChild(createSpecConstantGroup(testCtx));
+ computeTests->addChild(createOpSourceGroup(testCtx));
+ computeTests->addChild(createOpSourceExtensionGroup(testCtx));
+ computeTests->addChild(createDecorationGroupGroup(testCtx));
+ computeTests->addChild(createOpPhiGroup(testCtx));
+ computeTests->addChild(createLoopControlGroup(testCtx));
+ computeTests->addChild(createFunctionControlGroup(testCtx));
+ computeTests->addChild(createSelectionControlGroup(testCtx));
+ computeTests->addChild(createBlockOrderGroup(testCtx));
+ computeTests->addChild(createMultipleShaderGroup(testCtx));
+ computeTests->addChild(createMemoryAccessGroup(testCtx));
+ computeTests->addChild(createOpCopyMemoryGroup(testCtx));
+ computeTests->addChild(createOpCopyObjectGroup(testCtx));
+ computeTests->addChild(createNoContractionGroup(testCtx));
+ computeTests->addChild(createOpUndefGroup(testCtx));
+ computeTests->addChild(createOpUnreachableGroup(testCtx));
+ computeTests ->addChild(createOpQuantizeToF16Group(testCtx));
+
+ RGBA defaultColors[4];
getDefaultColors(defaultColors);
- de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "graphics-assembly", "Test the graphics pipeline"));
- createTestsForAllStages("passthru", defaultColors, defaultColors, passthruFragments(), group.get());
- instructionTests->addChild(group.release());
+ de::MovePtr<tcu::TestCaseGroup> opnopTests (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop"));
+ map<string, string> opNopFragments;
+ opNopFragments["testfun"] =
+ "%test_code = OpFunction %v4f32 None %v4f32_function\n"
+ "%param1 = OpFunctionParameter %v4f32\n"
+ "%label_testfun = OpLabel\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpNop\n"
+ "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
+ "%b = OpFAdd %f32 %a %a\n"
+ "OpNop\n"
+ "%c = OpFSub %f32 %b %a\n"
+ "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
+ "OpNop\n"
+ "OpNop\n"
+ "OpReturnValue %ret\n"
+ "OpFunctionEnd\n"
+ ;
+ createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, opnopTests.get());
+
+ graphicsTests->addChild(opnopTests.release());
+ graphicsTests->addChild(createOpSourceTests(testCtx));
+ graphicsTests->addChild(createOpSourceContinuedTests(testCtx));
+ graphicsTests->addChild(createOpLineTests(testCtx));
+ graphicsTests->addChild(createOpNoLineTests(testCtx));
+ graphicsTests->addChild(createOpConstantNullTests(testCtx));
+ graphicsTests->addChild(createOpConstantCompositeTests(testCtx));
+ graphicsTests->addChild(createMemoryAccessTests(testCtx));
+ graphicsTests->addChild(createOpUndefTests(testCtx));
+ graphicsTests->addChild(createSelectionBlockOrderTests(testCtx));
+ graphicsTests->addChild(createModuleTests(testCtx));
+ graphicsTests->addChild(createSwitchBlockOrderTests(testCtx));
+ graphicsTests->addChild(createOpPhiTests(testCtx));
+
+ instructionTests->addChild(computeTests.release());
+ instructionTests->addChild(graphicsTests.release());
return instructionTests.release();
}