@@ -28,15 +28,11 @@ using ValidatePrimitives = spvtest::ValidateBase<bool>;
2828
2929std::string GenerateShaderCode (
3030 const std::string& body,
31- const std::string& capabilities_and_extensions = " " ,
31+ const std::string& capabilities_and_extensions =
32+ " OpCapability GeometryStreams" ,
3233 const std::string& execution_model = " Geometry" ) {
3334 std::ostringstream ss;
34- ss << R"(
35- OpCapability Geometry
36- OpCapability GeometryStreams
37- )" ;
38-
39- ss << capabilities_and_extensions;
35+ ss << capabilities_and_extensions << " \n " ;
4036 ss << " OpMemoryModel Logical GLSL450\n " ;
4137 ss << " OpEntryPoint " << execution_model << " %main \" main\"\n " ;
4238
@@ -67,22 +63,146 @@ OpFunctionEnd)";
6763 return ss.str ();
6864}
6965
66+ // Returns SPIR-V assembly fragment representing a function call,
67+ // the end of the callee body, and the preamble and body of the called
68+ // function with the given body, but missing the final return and
69+ // function-end. The result is of the form where it can be used in the
70+ // |body| argument to GenerateShaderCode.
71+ std::string CallAndCallee (std::string body) {
72+ std::ostringstream ss;
73+ ss << R"(
74+ %dummy = OpFunctionCall %void %foo
75+ OpReturn
76+ OpFunctionEnd
77+
78+ %foo = OpFunction %void None %func
79+ %foo_entry = OpLabel
80+ )" ;
81+
82+ ss << body;
83+
84+ return ss.str ();
85+ }
86+
87+ // OpEmitVertex doesn't have any parameters, so other validation
88+ // is handled by the binary parser, and generic dominance checks.
89+ TEST_F (ValidatePrimitives, EmitVertexSuccess) {
90+ CompileSuccessfully (
91+ GenerateShaderCode (" OpEmitVertex" , " OpCapability Geometry" ));
92+ EXPECT_EQ (SPV_SUCCESS, ValidateInstructions ());
93+ }
94+
95+ TEST_F (ValidatePrimitives, EmitVertexFailMissingCapability) {
96+ CompileSuccessfully (
97+ GenerateShaderCode (" OpEmitVertex" , " OpCapability Shader" , " Vertex" ));
98+ EXPECT_EQ (SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions ());
99+ EXPECT_THAT (
100+ getDiagnosticString (),
101+ HasSubstr (
102+ " Opcode EmitVertex requires one of these capabilities: Geometry" ));
103+ }
104+
105+ TEST_F (ValidatePrimitives, EmitVertexFailWrongExecutionMode) {
106+ CompileSuccessfully (
107+ GenerateShaderCode (" OpEmitVertex" , " OpCapability Geometry" , " Vertex" ));
108+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
109+ EXPECT_THAT (
110+ getDiagnosticString (),
111+ HasSubstr (" EmitVertex instructions require Geometry execution model" ));
112+ }
113+
114+ TEST_F (ValidatePrimitives, EmitVertexFailWrongExecutionModeNestedFunction) {
115+ CompileSuccessfully (GenerateShaderCode (CallAndCallee (" OpEmitVertex" ),
116+ " OpCapability Geometry" , " Vertex" ));
117+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
118+ EXPECT_THAT (
119+ getDiagnosticString (),
120+ HasSubstr (" EmitVertex instructions require Geometry execution model" ));
121+ }
122+
123+ // OpEndPrimitive doesn't have any parameters, so other validation
124+ // is handled by the binary parser, and generic dominance checks.
125+ TEST_F (ValidatePrimitives, EndPrimitiveSuccess) {
126+ CompileSuccessfully (
127+ GenerateShaderCode (" OpEndPrimitive" , " OpCapability Geometry" ));
128+ EXPECT_EQ (SPV_SUCCESS, ValidateInstructions ());
129+ }
130+
131+ TEST_F (ValidatePrimitives, EndPrimitiveFailMissingCapability) {
132+ CompileSuccessfully (
133+ GenerateShaderCode (" OpEndPrimitive" , " OpCapability Shader" , " Vertex" ));
134+ EXPECT_EQ (SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions ());
135+ EXPECT_THAT (
136+ getDiagnosticString (),
137+ HasSubstr (
138+ " Opcode EndPrimitive requires one of these capabilities: Geometry" ));
139+ }
140+
141+ TEST_F (ValidatePrimitives, EndPrimitiveFailWrongExecutionMode) {
142+ CompileSuccessfully (
143+ GenerateShaderCode (" OpEndPrimitive" , " OpCapability Geometry" , " Vertex" ));
144+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
145+ EXPECT_THAT (
146+ getDiagnosticString (),
147+ HasSubstr (" EndPrimitive instructions require Geometry execution model" ));
148+ }
149+
150+ TEST_F (ValidatePrimitives, EndPrimitiveFailWrongExecutionModeNestedFunction) {
151+ CompileSuccessfully (GenerateShaderCode (CallAndCallee (" OpEndPrimitive" ),
152+ " OpCapability Geometry" , " Vertex" ));
153+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
154+ EXPECT_THAT (
155+ getDiagnosticString (),
156+ HasSubstr (" EndPrimitive instructions require Geometry execution model" ));
157+ }
158+
70159TEST_F (ValidatePrimitives, EmitStreamVertexSuccess) {
71160 const std::string body = R"(
72161OpEmitStreamVertex %u32_0
73162)" ;
74163
75- CompileSuccessfully (GenerateShaderCode (body).c_str ());
76- ASSERT_EQ (SPV_SUCCESS, ValidateInstructions ());
164+ CompileSuccessfully (GenerateShaderCode (body));
165+ EXPECT_EQ (SPV_SUCCESS, ValidateInstructions ());
166+ }
167+
168+ TEST_F (ValidatePrimitives, EmitStreamVertexFailMissingCapability) {
169+ CompileSuccessfully (GenerateShaderCode (" OpEmitStreamVertex %u32_0" ,
170+ " OpCapability Shader" , " Vertex" ));
171+ EXPECT_EQ (SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions ());
172+ EXPECT_THAT (getDiagnosticString (),
173+ HasSubstr (" Opcode EmitStreamVertex requires one of these "
174+ " capabilities: GeometryStreams" ));
175+ }
176+
177+ TEST_F (ValidatePrimitives, EmitStreamVertexFailWrongExecutionMode) {
178+ CompileSuccessfully (GenerateShaderCode (
179+ " OpEmitStreamVertex %u32_0" , " OpCapability GeometryStreams" , " Vertex" ));
180+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
181+ EXPECT_THAT (
182+ getDiagnosticString (),
183+ HasSubstr (
184+ " EmitStreamVertex instructions require Geometry execution model" ));
185+ }
186+
187+ TEST_F (ValidatePrimitives,
188+ EmitStreamVertexFailWrongExecutionModeNestedFunction) {
189+ CompileSuccessfully (
190+ GenerateShaderCode (CallAndCallee (" OpEmitStreamVertex %u32_0" ),
191+ " OpCapability GeometryStreams" , " Vertex" ));
192+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
193+ EXPECT_THAT (
194+ getDiagnosticString (),
195+ HasSubstr (
196+ " EmitStreamVertex instructions require Geometry execution model" ));
77197}
78198
79199TEST_F (ValidatePrimitives, EmitStreamVertexNonInt) {
80200 const std::string body = R"(
81201OpEmitStreamVertex %f32_0
82202)" ;
83203
84- CompileSuccessfully (GenerateShaderCode (body). c_str () );
85- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
204+ CompileSuccessfully (GenerateShaderCode (body));
205+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
86206 EXPECT_THAT (getDiagnosticString (),
87207 HasSubstr (" EmitStreamVertex: "
88208 " expected Stream to be int scalar" ));
@@ -93,8 +213,8 @@ TEST_F(ValidatePrimitives, EmitStreamVertexNonScalar) {
93213OpEmitStreamVertex %u32vec4_0123
94214)" ;
95215
96- CompileSuccessfully (GenerateShaderCode (body). c_str () );
97- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
216+ CompileSuccessfully (GenerateShaderCode (body));
217+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
98218 EXPECT_THAT (getDiagnosticString (),
99219 HasSubstr (" EmitStreamVertex: "
100220 " expected Stream to be int scalar" ));
@@ -106,8 +226,8 @@ TEST_F(ValidatePrimitives, EmitStreamVertexNonConstant) {
106226OpEmitStreamVertex %val1
107227)" ;
108228
109- CompileSuccessfully (GenerateShaderCode (body). c_str () );
110- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
229+ CompileSuccessfully (GenerateShaderCode (body));
230+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
111231 EXPECT_THAT (getDiagnosticString (),
112232 HasSubstr (" EmitStreamVertex: "
113233 " expected Stream to be constant instruction" ));
@@ -118,17 +238,48 @@ TEST_F(ValidatePrimitives, EndStreamPrimitiveSuccess) {
118238OpEndStreamPrimitive %u32_0
119239)" ;
120240
121- CompileSuccessfully (GenerateShaderCode (body).c_str ());
122- ASSERT_EQ (SPV_SUCCESS, ValidateInstructions ());
241+ CompileSuccessfully (GenerateShaderCode (body));
242+ EXPECT_EQ (SPV_SUCCESS, ValidateInstructions ());
243+ }
244+
245+ TEST_F (ValidatePrimitives, EndStreamPrimitiveFailMissingCapability) {
246+ CompileSuccessfully (GenerateShaderCode (" OpEndStreamPrimitive %u32_0" ,
247+ " OpCapability Shader" , " Vertex" ));
248+ EXPECT_EQ (SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions ());
249+ EXPECT_THAT (getDiagnosticString (),
250+ HasSubstr (" Opcode EndStreamPrimitive requires one of these "
251+ " capabilities: GeometryStreams" ));
252+ }
253+
254+ TEST_F (ValidatePrimitives, EndStreamPrimitiveFailWrongExecutionMode) {
255+ CompileSuccessfully (GenerateShaderCode (
256+ " OpEndStreamPrimitive %u32_0" , " OpCapability GeometryStreams" , " Vertex" ));
257+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
258+ EXPECT_THAT (
259+ getDiagnosticString (),
260+ HasSubstr (
261+ " EndStreamPrimitive instructions require Geometry execution model" ));
262+ }
263+
264+ TEST_F (ValidatePrimitives,
265+ EndStreamPrimitiveFailWrongExecutionModeNestedFunction) {
266+ CompileSuccessfully (
267+ GenerateShaderCode (CallAndCallee (" OpEndStreamPrimitive %u32_0" ),
268+ " OpCapability GeometryStreams" , " Vertex" ));
269+ EXPECT_EQ (SPV_ERROR_INVALID_ID, ValidateInstructions ());
270+ EXPECT_THAT (
271+ getDiagnosticString (),
272+ HasSubstr (
273+ " EndStreamPrimitive instructions require Geometry execution model" ));
123274}
124275
125276TEST_F (ValidatePrimitives, EndStreamPrimitiveNonInt) {
126277 const std::string body = R"(
127278OpEndStreamPrimitive %f32_0
128279)" ;
129280
130- CompileSuccessfully (GenerateShaderCode (body). c_str () );
131- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
281+ CompileSuccessfully (GenerateShaderCode (body));
282+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
132283 EXPECT_THAT (getDiagnosticString (),
133284 HasSubstr (" EndStreamPrimitive: "
134285 " expected Stream to be int scalar" ));
@@ -139,8 +290,8 @@ TEST_F(ValidatePrimitives, EndStreamPrimitiveNonScalar) {
139290OpEndStreamPrimitive %u32vec4_0123
140291)" ;
141292
142- CompileSuccessfully (GenerateShaderCode (body). c_str () );
143- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
293+ CompileSuccessfully (GenerateShaderCode (body));
294+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
144295 EXPECT_THAT (getDiagnosticString (),
145296 HasSubstr (" EndStreamPrimitive: "
146297 " expected Stream to be int scalar" ));
@@ -152,8 +303,8 @@ TEST_F(ValidatePrimitives, EndStreamPrimitiveNonConstant) {
152303OpEndStreamPrimitive %val1
153304)" ;
154305
155- CompileSuccessfully (GenerateShaderCode (body). c_str () );
156- ASSERT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
306+ CompileSuccessfully (GenerateShaderCode (body));
307+ EXPECT_EQ (SPV_ERROR_INVALID_DATA, ValidateInstructions ());
157308 EXPECT_THAT (getDiagnosticString (),
158309 HasSubstr (" EndStreamPrimitive: "
159310 " expected Stream to be constant instruction" ));
0 commit comments