addShaderCodeCustomFragment(dst, context, DE_NULL);
}
-void createCombinedModule (vk::SourceCollections& dst, InstanceContext)
+void createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx)
{
- // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional
- dst.spirvAsmSources.add("module") <<
- "OpCapability Shader\n"
- "OpCapability Geometry\n"
- "OpCapability Tessellation\n"
- "OpMemoryModel Logical GLSL450\n"
+ const bool useTessellation (ctx.requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
+ const bool useGeometry (ctx.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
+ std::stringstream combinedModule;
+ std::stringstream opCapabilities;
+ std::stringstream opEntryPoints;
- "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\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_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 OutputTriangleStrip\n"
- "OpExecutionMode %geom_main OutputVertices 3\n"
-
- "OpExecutionMode %tessc_main OutputVertices 3\n"
-
- "OpExecutionMode %tesse_main Triangles\n"
- "OpExecutionMode %tesse_main SpacingEqual\n"
- "OpExecutionMode %tesse_main VertexOrderCcw\n"
-
- "OpExecutionMode %frag_main OriginUpperLeft\n"
-
- "; Vertex decorations\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 VertexIndex\n"
- "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n"
-
- "; Geometry decorations\n"
- "OpDecorate %geom_out_gl_position BuiltIn Position\n"
- "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n"
- "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n"
- "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n"
- "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n"
- "OpDecorate %geom_per_vertex_in Block\n"
- "OpDecorate %geom_out_color Location 1\n"
- "OpDecorate %geom_in_color Location 1\n"
-
- "; Tessellation Control decorations\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"
- "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"
- "OpDecorate %frag_fragColor Location 0\n"
- "OpDecorate %frag_vtxColor Location 1\n"
+ // opCapabilities
+ {
+ opCapabilities << "OpCapability Shader\n";
- SPIRV_ASSEMBLY_TYPES
- SPIRV_ASSEMBLY_CONSTANTS
- SPIRV_ASSEMBLY_ARRAYS
+ if (useGeometry)
+ opCapabilities << "OpCapability Geometry\n";
- "; 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 %geom_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"
+ if (useTessellation)
+ opCapabilities << "OpCapability Tessellation\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"
+ // opEntryPoints
+ {
+ opEntryPoints << "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\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"
+ if (useGeometry)
+ opEntryPoints << "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\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 %tesse_in_pos_0 %tesse_tc_0\n"
- "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
- "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
- "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
- "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
- "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
- "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_in_clr_0 %tesse_tc_0\n"
- "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
- "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
- "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
- "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
- "OpStore %tesse_out_color %tesse_computed_clr\n"
- "OpReturn\n"
- "OpFunctionEnd\n"
+ if (useTessellation)
+ {
+ opEntryPoints << "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";
+ }
- "; 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";
+ opEntryPoints << "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n";
+ }
+
+ combinedModule << opCapabilities.str()
+ << "OpMemoryModel Logical GLSL450\n"
+ << opEntryPoints.str();
+
+ if (useGeometry)
+ {
+ combinedModule << "OpExecutionMode %geom_main Triangles\n"
+ "OpExecutionMode %geom_main OutputTriangleStrip\n"
+ "OpExecutionMode %geom_main OutputVertices 3\n";
+ }
+
+ if (useTessellation)
+ {
+ combinedModule << "OpExecutionMode %tessc_main OutputVertices 3\n"
+ "OpExecutionMode %tesse_main Triangles\n"
+ "OpExecutionMode %tesse_main SpacingEqual\n"
+ "OpExecutionMode %tesse_main VertexOrderCcw\n";
+ }
+
+ combinedModule << "OpExecutionMode %frag_main OriginUpperLeft\n"
+
+ "; Vertex decorations\n";
+
+ // If tessellation is used, vertex position is written by tessellation stage.
+ // Otherwise it will be written by vertex stage.
+ if (useTessellation)
+ combinedModule << "OpDecorate %vert_vtxPosition Location 2\n";
+ else
+ combinedModule << "OpDecorate %vert_vtxPosition BuiltIn Position\n";
+
+ combinedModule << "OpDecorate %vert_Position Location 0\n"
+ "OpDecorate %vert_vtxColor Location 1\n"
+ "OpDecorate %vert_color Location 1\n"
+ "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n"
+ "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n";
+
+ if (useGeometry)
+ {
+ combinedModule << "; Geometry decorations\n"
+ "OpDecorate %geom_out_gl_position BuiltIn Position\n"
+ "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n"
+ "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n"
+ "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n"
+ "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n"
+ "OpDecorate %geom_per_vertex_in Block\n"
+ "OpDecorate %geom_out_color Location 1\n"
+ "OpDecorate %geom_in_color Location 1\n";
+ }
+
+ if (useTessellation)
+ {
+ combinedModule << "; Tessellation Control decorations\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"
+ "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";
+ }
+
+ combinedModule << "; Fragment decorations\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";
+
+ if (useGeometry)
+ {
+ combinedModule << "; 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 %geom_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";
+ }
+
+ if (useTessellation)
+ {
+ combinedModule << "; 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";
+ }
+
+ combinedModule << "; 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";
+
+ if (useGeometry)
+ {
+ combinedModule << "; 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";
+ }
+
+ if (useTessellation)
+ {
+ combinedModule << "; 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 %tesse_in_pos_0 %tesse_tc_0\n"
+ "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
+ "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
+ "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
+ "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
+ "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
+ "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_in_clr_0 %tesse_tc_0\n"
+ "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
+ "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
+ "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
+ "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
+ "OpStore %tesse_out_color %tesse_computed_clr\n"
+ "OpReturn\n"
+ "OpFunctionEnd\n";
+ }
+
+ combinedModule << "; 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";
+
+ dst.spirvAsmSources.add("module") << combinedModule.str();
}
void createMultipleEntries (vk::SourceCollections& dst, InstanceContext)
const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
bool supportsGeometry = false;
bool supportsTessellation = false;
- bool hasTessellation = false;
+ bool hasGeometry = false;
+ bool hasTessellation = false;
const bool hasPushConstants = !instance.pushConstants.empty();
const deUint32 numResources = static_cast<deUint32>(instance.resources.inputs.size() + instance.resources.outputs.size());
const bool needInterface = !instance.interfaces.empty();
supportsGeometry = features.geometryShader == VK_TRUE;
supportsTessellation = features.tessellationShader == VK_TRUE;
+ hasGeometry = (instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
(instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
- if (hasTessellation && !supportsTessellation)
+ if (hasGeometry && !supportsGeometry)
{
- TCU_THROW(NotSupportedError, "Tessellation not supported");
+ TCU_THROW(NotSupportedError, "Geometry not supported");
}
- if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) &&
- !supportsGeometry)
+ if (hasTessellation && !supportsTessellation)
{
- TCU_THROW(NotSupportedError, "Geometry not supported");
+ TCU_THROW(NotSupportedError, "Tessellation not supported");
}
// Check all required extensions are supported
RGBA invertedColors[4];
de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders"));
- const ShaderElement combinedPipeline[] =
- {
- ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
- ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
- };
-
getDefaultColors(defaultColors);
getInvertedDefaultColors(invertedColors);
- addFunctionCaseWithPrograms<InstanceContext>(
- moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
- createInstanceContext(combinedPipeline, map<string, string>()));
+
+ // Combined module tests
+ {
+ // Shader stages: vertex and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, geometry and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, tessellation control, tessellation evaluation and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_tessc_tesse", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+
+ // Shader stages: vertex, tessellation control, tessellation evaluation, geometry and fragment
+ {
+ const ShaderElement combinedPipeline[] =
+ {
+ ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
+ ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
+ };
+
+ addFunctionCaseWithPrograms<InstanceContext>(
+ moduleTests.get(), "same_module_tessc_tesse_geom", "", createCombinedModule, runAndVerifyDefaultPipeline,
+ createInstanceContext(combinedPipeline, map<string, string>()));
+ }
+ }
const char* numbers[] =
{