• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief SPIR-V non semantic info tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vkApiVersion.hpp"
25 
26 #include "vktSpvAsmNonSemanticInfoTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktSpvAsmComputeShaderCase.hpp"
29 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
30 
31 #include <limits>
32 
33 namespace vkt
34 {
35 namespace SpirVAssembly
36 {
37 
38 using namespace vk;
39 
40 enum TestType
41 {
42 	TT_BASIC					= 0,
43 	TT_DUMMY_INSTRUCTION_SET,
44 	TT_LARGE_INSTRUCTION_NUMBER,
45 	TT_MANY_PARAMETERS,
46 	TT_ANY_CONSTANT_TYPE,
47 	TT_ANY_CONSTANT_TYPE_USED,
48 	TT_ANY_NON_CONSTANT_TYPE,
49 	TT_PLACEMENT
50 };
51 
getComputeShaderSpec()52 static ComputeShaderSpec getComputeShaderSpec ()
53 {
54 	deUint32 numElements = 10;
55 	std::vector<float>	inoutFloats	(10, 0);
56 	for (size_t ndx = 0; ndx < numElements; ++ndx)
57 		inoutFloats[ndx] = 1.0f * static_cast<float>(ndx);
58 
59 	// in one of tests we need to do imageLoad
60 	// we don't need any special values in here
61 	std::vector<int> inputInts(256, 0);
62 
63 	ComputeShaderSpec spec;
64 	spec.extensions.push_back("VK_KHR_shader_non_semantic_info");
65 	spec.inputs.push_back(BufferSp(new Float32Buffer(inoutFloats)));
66 	spec.inputs.push_back(Resource(BufferSp(new Int32Buffer(inputInts)), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE));
67 	spec.outputs.push_back(BufferSp(new Float32Buffer(inoutFloats)));
68 	spec.numWorkGroups = tcu::IVec3(numElements, 1, 1);
69 	return spec;
70 }
71 
72 class SpvAsmSpirvNonSemanticInfoBasicInstance : public ComputeShaderSpec, public SpvAsmComputeShaderInstance
73 {
74 public:
75 	SpvAsmSpirvNonSemanticInfoBasicInstance		(Context& ctx, TestType type);
76 
77 	tcu::TestStatus			iterate				(void);
78 
79 protected:
80 	TestType m_testType;
81 };
82 
SpvAsmSpirvNonSemanticInfoBasicInstance(Context & ctx,TestType type)83 SpvAsmSpirvNonSemanticInfoBasicInstance::SpvAsmSpirvNonSemanticInfoBasicInstance(Context& ctx, TestType type)
84 	: ComputeShaderSpec(getComputeShaderSpec())
85 	, SpvAsmComputeShaderInstance(ctx, *this)
86 	, m_testType(type)
87 {
88 }
89 
iterate(void)90 tcu::TestStatus SpvAsmSpirvNonSemanticInfoBasicInstance::iterate (void)
91 {
92 	return SpvAsmComputeShaderInstance::iterate();
93 }
94 
95 class SpvAsmSpirvNonSemanticInfoBasicCase : public TestCase
96 {
97 public:
98 	SpvAsmSpirvNonSemanticInfoBasicCase		(tcu::TestContext& testCtx, const char* name, TestType type);
99 
100 	void			checkSupport			(Context& context) const;
101 	void			initPrograms			(vk::SourceCollections& programCollection) const;
102 	TestInstance*	createInstance			(Context& context) const;
103 
104 protected:
105 	TestType m_testType;
106 };
107 
SpvAsmSpirvNonSemanticInfoBasicCase(tcu::TestContext & testCtx,const char * name,TestType type)108 SpvAsmSpirvNonSemanticInfoBasicCase::SpvAsmSpirvNonSemanticInfoBasicCase(tcu::TestContext& testCtx, const char* name, TestType type)
109 	: TestCase (testCtx, name, "")
110 	, m_testType(type)
111 {
112 }
113 
checkSupport(Context & context) const114 void SpvAsmSpirvNonSemanticInfoBasicCase::checkSupport(Context& context) const
115 {
116 	context.requireDeviceFunctionality("VK_KHR_shader_non_semantic_info");
117 }
118 
initPrograms(SourceCollections & programCollection) const119 void SpvAsmSpirvNonSemanticInfoBasicCase::initPrograms (SourceCollections& programCollection) const
120 {
121 	std::string extendedInstructions	= "%extInstSet = OpExtInstImport \"NonSemantic.KHR.DebugInfo\"\n";
122 	std::string additionalDecorations	= "";
123 	std::string additionalPreamble		= "";
124 	std::string additionalTypesAndConst = "";
125 	std::string beginningOfMain			= "";
126 	std::string middleOfMain			= "";
127 
128 	switch (m_testType)
129 	{
130 	case TT_BASIC:
131 		// Minimal test of basic functionality
132 
133 		additionalPreamble +=
134 			"%fileStr = OpString \"path\\to\\source.file\"\n"
135 			"OpSource GLSL 430 %fileStr\n";
136 		middleOfMain +=
137 			"%tmp = OpExtInst %void %extInstSet 1 %main %fileStr\n";
138 		break;
139 
140 	case TT_DUMMY_INSTRUCTION_SET:
141 		// Testing non existing instruction set
142 
143 		extendedInstructions =
144 			"%extInstSet = OpExtInstImport \"NonSemantic.P.B.DummySet\"\n";
145 		additionalPreamble +=
146 			"%testStrA = OpString \"this.is.test\"\n"
147 			"%testStrB = OpString \"yet another test\"\n";
148 		middleOfMain +=
149 			"%tmpA = OpExtInst %void %extInstSet 55 %id %testStrA %testStrB\n"
150 			"OpLine %testStrA 1 1\n"
151 			"%tmpB = OpExtInst %void %extInstSet 99 %testStrA %main %testStrA\n"
152 			"OpLine %testStrB 2 2\n"
153 			"OpNoLine\n";
154 		break;
155 
156 	case TT_LARGE_INSTRUCTION_NUMBER:
157 	{
158 		// Any instruction number should work - testing large values near uint::max
159 
160 		deUint32 instNr = std::numeric_limits<deUint32>::max() - 1;
161 		middleOfMain +=
162 			"%tmpA = OpExtInst %void %extInstSet " + std::to_string(instNr) + " %main\n" +
163 			"%tmpB = OpExtInst %void %extInstSet 4294967290 %main\n";
164 		break;
165 	}
166 
167 	case TT_MANY_PARAMETERS:
168 		// Many parameters should work - testing 100 parameters
169 
170 		middleOfMain +=
171 			"%tmp = OpExtInst %void %extInstSet 1234";
172 		for (deUint32 parameterIndex = 0; parameterIndex < 100; parameterIndex++)
173 		{
174 			std::string iStr = std::to_string(parameterIndex);
175 			std::string strVarName = std::string("%testStr") + iStr;
176 			additionalPreamble += strVarName + " = OpString \"" + iStr +"\"\n";
177 			middleOfMain += std::string(" ") + strVarName;
178 		}
179 		middleOfMain += "\n";
180 		break;
181 
182 	case TT_ANY_CONSTANT_TYPE:
183 	case TT_ANY_CONSTANT_TYPE_USED:
184 	{
185 		// Any type of constant parameter should work - testing undef,
186 		// int, uint, float, struct, vector, array, string, matrix
187 
188 		additionalDecorations =
189 			"OpMemberDecorate %struct 0 Offset 0\n"
190 			"OpMemberDecorate %struct 1 Offset 4\n"
191 			"OpMemberDecorate %struct 2 Offset 16\n";
192 
193 		std::string types =
194 			"%struct             = OpTypeStruct %f32 %fvec3 %i32\n"
195 			"%c_array_size       = OpConstant %u32 4\n"
196 			"%array4             = OpTypeArray %f32 %c_array_size\n"
197 			"%matrix3x3          = OpTypeMatrix %fvec3 3\n";
198 
199 		std::string constans =
200 			"%undef      = OpUndef %i32\n"
201 			"%c_i32      = OpConstant %i32 -45\n"
202 			"%c_u32      = OpConstant %u32 99\n"
203 			"%c_f32      = OpConstant %f32 0.0\n"
204 			"%c_fvec3    = OpConstantComposite %fvec3 %c_f32 %c_f32 %c_f32\n"
205 			"%c_struct   = OpConstantComposite %struct %c_f32 %c_fvec3 %undef\n"
206 			"%c_array    = OpConstantComposite %array4 %c_f32 %c_f32 %c_f32 %c_f32\n"
207 			"%c_matrix   = OpConstantComposite %matrix3x3 %c_fvec3 %c_fvec3 %c_fvec3\n";
208 
209 		additionalPreamble +=
210 			"%testStr = OpString \"\"\n";
211 		additionalTypesAndConst = types + constans;
212 		middleOfMain += "%tmp = OpExtInst %void %extInstSet 999 %main %undef %c_i32 %c_u32 %c_f32 %c_struct %c_fvec3 %c_array %testStr %c_matrix\n";
213 		if (m_testType == TT_ANY_CONSTANT_TYPE)
214 			break;
215 
216 		// use all constans outside of OpExtInst
217 		middleOfMain +=
218 			"%tmp01      = OpCompositeExtract %f32 %c_fvec3 2\n"
219 			"%tmp02      = OpFAdd %f32 %tmp01 %c_f32\n"
220 			"%tmp03      = OpCompositeExtract %f32 %c_struct 0\n"
221 			"%tmp04      = OpFAdd %f32 %tmp02 %tmp03\n"
222 			"%tmp05      = OpCompositeExtract %f32 %c_array 1\n"
223 			"%tmp06      = OpFAdd %f32 %tmp04 %tmp05\n"
224 			"%tmp07      = OpCompositeExtract %fvec3 %c_matrix 1\n"
225 			"%tmp08      = OpCompositeExtract %f32 %tmp07 1\n"
226 			"%tmp09      = OpFMul %f32 %tmp06 %tmp08\n"
227 			"%tmp10      = OpConvertSToF %f32 %c_i32\n"
228 			"%tmp11      = OpFMul %f32 %tmp09 %tmp10\n"
229 			"              OpStore %outloc %tmp11\n";
230 		break;
231 	}
232 
233 	case TT_ANY_NON_CONSTANT_TYPE:
234 	{
235 		// Any type of existing semantic result ID should be referencable. Testing
236 		// the result of a semantic OpExtInst, an entry point, variables of different types,
237 		// result IDs of buffer and texture loads, result IDs of arithmetic instructions,
238 		// result of an OpLoad, result of a comparison / logical instruction.
239 
240 		additionalDecorations =
241 			"OpMemberDecorate %struct 0 Offset 0\n"
242 			"OpMemberDecorate %struct 1 Offset 4\n"
243 			"OpMemberDecorate %struct 2 Offset 16\n";
244 		extendedInstructions +=
245 			"%std450 = OpExtInstImport \"GLSL.std.450\"\n";
246 		additionalTypesAndConst =
247 			"%struct             = OpTypeStruct %f32 %fvec3 %f32\n"
248 			"%struct_ptr         = OpTypePointer Function %struct\n"
249 			"%c_array_size       = OpConstant %u32 4\n"
250 			"%array4             = OpTypeArray %f32 %c_array_size\n"
251 			"%array4_ptr         = OpTypePointer Function %array4\n"
252 			"%matrix3x3          = OpTypeMatrix %fvec3 3\n"
253 			"%matrix3x3_ptr      = OpTypePointer Function %matrix3x3\n"
254 			"%uvec2              = OpTypeVector %u32 2\n"
255 			"%fvec4              = OpTypeVector %f32 4\n"
256 			"%uv                 = OpConstantComposite %uvec2 %zero %zero\n";
257 
258 		beginningOfMain =
259 			"%struct_var = OpVariable %struct_ptr Function\n"
260 			"%array_var  = OpVariable %array4_ptr Function\n"
261 			"%matrix_var = OpVariable %matrix3x3_ptr Function\n";
262 		middleOfMain =
263 			"%tmp01      = OpExtInst %void %extInstSet 486 %main %id %x %idval %struct_var %array_var %matrix_var %uvec3ptr %indata\n"
264 			"%arithmRes  = OpIAdd %u32 %x %x\n"
265 			"%extInstRes = OpExtInst %f32 %std450 FAbs %inval\n"
266 			"%logicRes   = OpIsNan %bool %inval\n"
267 			"%imgLoadRes = OpLoad %image_type %image\n"
268 			"%tmp02      = OpExtInst %void %extInstSet 963 %tmp01 %arithmRes %inloc %outloc %inval %extInstRes %logicRes %imgLoadRes %std450\n";
269 		break;
270 	}
271 
272 	case TT_PLACEMENT:
273 		// The instructions should be able to be placed at global scope,
274 		// in the types/constants section and between function definitions
275 
276 		additionalTypesAndConst =
277 			"%extInstA   = OpExtInst %void %extInstSet 1 %id\n"			// at global scope
278 			"%floatf     = OpTypeFunction %f32 %f32\n"
279 			"%funDefA    = OpFunction %f32 None %floatf\n"
280 			"%funApa     = OpFunctionParameter %f32\n"
281 			"%funA       = OpLabel\n"
282 			"              OpReturnValue %funApa\n"
283 			"              OpFunctionEnd\n"
284 			"%extInstB  = OpExtInst %void %extInstSet 3 %id\n";			// between definitions
285 		middleOfMain +=
286 			"%aRes       = OpFunctionCall %f32 %funDefA %inval\n"
287 			"%extInstC   = OpExtInst %void %extInstSet 4 %aRes\n"		// within a block
288 			"              OpStore %outloc %aRes\n";
289 		break;
290 	}
291 
292 	std::string source =
293 		getComputeAsmShaderPreamble("", "OpExtension \"SPV_KHR_non_semantic_info\"\n" + extendedInstructions) +
294 		additionalPreamble +
295 		"OpDecorate %id BuiltIn GlobalInvocationId\n" +
296 		"OpDecorate %buf BufferBlock\n"
297 		"OpDecorate %indata DescriptorSet 0\n"
298 		"OpDecorate %indata Binding 0\n"
299 		"OpDecorate %image DescriptorSet 0\n"
300 		"OpDecorate %image Binding 1\n"
301 		"OpDecorate %image NonWritable\n"
302 		"OpDecorate %outdata DescriptorSet 0\n"
303 		"OpDecorate %outdata Binding 2\n"
304 		"OpDecorate %f32arr ArrayStride 4\n"
305 		"OpMemberDecorate %buf 0 Offset 0\n" +
306 		additionalDecorations +
307 		std::string(getComputeAsmCommonTypes()) +
308 		std::string(getComputeAsmInputOutputBuffer()) +
309 		"%id         = OpVariable %uvec3ptr Input\n"
310 		"%image_type = OpTypeImage %f32 2D 0 0 0 2 Rgba8\n"
311 		"%image_ptr  = OpTypePointer UniformConstant %image_type\n"
312 		"%image      = OpVariable %image_ptr UniformConstant\n"
313 		"%zero       = OpConstant %i32 0\n" +
314 		additionalTypesAndConst +
315 		"%main       = OpFunction %void None %voidf\n"
316 		"%label      = OpLabel\n" +
317 		beginningOfMain +
318 		"%idval      = OpLoad %uvec3 %id\n"
319 		"%x          = OpCompositeExtract %u32 %idval 0\n"
320 		"%inloc      = OpAccessChain %f32ptr %indata %zero %x\n"
321 		"%outloc     = OpAccessChain %f32ptr %outdata %zero %x\n"
322 		"%inval      = OpLoad %f32 %inloc\n" +
323 		middleOfMain +
324 		"             OpStore %outloc %inval\n"
325 		"             OpReturn\n"
326 		"             OpFunctionEnd\n";
327 
328 	programCollection.spirvAsmSources.add("compute") << source;
329 }
330 
createInstance(Context & context) const331 TestInstance* SpvAsmSpirvNonSemanticInfoBasicCase::createInstance (Context& context) const
332 {
333 	return new SpvAsmSpirvNonSemanticInfoBasicInstance(context, m_testType);
334 }
335 
createNonSemanticInfoGroup(tcu::TestContext & testCtx)336 tcu::TestCaseGroup* createNonSemanticInfoGroup(tcu::TestContext& testCtx)
337 {
338 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "non_semantic_info", "Test for VK_KHR_shader_non_semantic_info"));
339 
340 	struct TestData
341 	{
342 		const char*	name;
343 		TestType	type;
344 	};
345 	std::vector<TestData> testList =
346 	{
347 		{ "basic",						TT_BASIC },
348 		{ "dummy_instruction_set",		TT_DUMMY_INSTRUCTION_SET },
349 		{ "large_instruction_number",	TT_LARGE_INSTRUCTION_NUMBER },
350 		{ "many_parameters",			TT_MANY_PARAMETERS },
351 		{ "any_constant_type",			TT_ANY_CONSTANT_TYPE },
352 		{ "any_constant_type_used",		TT_ANY_CONSTANT_TYPE_USED },
353 		{ "any_non_constant_type",		TT_ANY_NON_CONSTANT_TYPE },
354 		{ "placement",					TT_PLACEMENT },
355 	};
356 
357 	for (const auto& item : testList)
358 		group->addChild(new SpvAsmSpirvNonSemanticInfoBasicCase(testCtx, item.name, item.type));
359 
360 	return group.release();
361 }
362 
363 } // SpirVAssembly
364 } // vkt
365