1 #ifndef _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
2 #define _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2017 Google Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Graphics pipeline and helper functions for SPIR-V assembly tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuCommandLine.hpp"
27 #include "tcuRGBA.hpp"
28 
29 #include "vkPrograms.hpp"
30 #include "vktSpvAsmComputeShaderTestUtil.hpp"
31 #include "vktSpvAsmUtils.hpp"
32 #include "vktTestCaseUtil.hpp"
33 
34 #include "deRandom.hpp"
35 #include "deSharedPtr.hpp"
36 
37 #include <map>
38 #include <sstream>
39 #include <string>
40 #include <utility>
41 
42 namespace vkt
43 {
44 namespace SpirVAssembly
45 {
46 
47 typedef vk::Unique<VkBuffer>										BufferHandleUp;
48 typedef vk::Unique<VkImage>											ImageHandleUp;
49 typedef vk::Unique<VkImageView>										ImageViewHandleUp;
50 typedef vk::Unique<VkSampler>										SamplerHandleUp;
51 typedef de::SharedPtr<BufferHandleUp>								BufferHandleSp;
52 typedef de::SharedPtr<ImageHandleUp>								ImageHandleSp;
53 typedef de::SharedPtr<ImageViewHandleUp>							ImageViewHandleSp;
54 typedef de::SharedPtr<SamplerHandleUp>								SamplerHandleSp;
55 typedef vk::Unique<vk::VkShaderModule>								ModuleHandleUp;
56 typedef de::SharedPtr<ModuleHandleUp>								ModuleHandleSp;
57 typedef std::pair<std::string, vk::VkShaderStageFlagBits>			EntryToStage;
58 typedef std::map<std::string, std::vector<EntryToStage> >			ModuleMap;
59 typedef std::map<vk::VkShaderStageFlagBits, SpecConstants >			StageToSpecConstantMap;
60 
61 enum NumberType
62 {
63 	NUMBERTYPE_INT32,
64 	NUMBERTYPE_UINT32,
65 	NUMBERTYPE_FLOAT32,
66 	NUMBERTYPE_END32,		// Marks the end of 32-bit scalar types
67 	NUMBERTYPE_INT16,
68 	NUMBERTYPE_UINT16,
69 	NUMBERTYPE_FLOAT16,
70 	NUMBERTYPE_END16,		// Marks the end of 16-bit scalar types
71 	NUMBERTYPE_FLOAT64,
72 };
73 
74 typedef enum RoundingModeFlags_e
75 {
76 	ROUNDINGMODE_RTE = 0x1,	// Round to nearest even
77 	ROUNDINGMODE_RTZ = 0x2,	// Round to zero
78 } RoundingModeFlags;
79 
80 typedef bool (*GraphicsVerifyBinaryFunc) (const ProgramBinary&	binary);
81 
82 // Resources used by graphics-pipeline-based tests.
83 struct GraphicsResources
84 {
85 	// Resources used as inputs.
86 	std::vector<Resource>		inputs;
87 	// Input resource format if used
88 	VkFormat					inputFormat;
89 	// Resources used as outputs. The data supplied will be used as
90 	// the expected outputs for the corresponding bindings by default.
91 	// If other behaviors are needed, please provide a custom verifyIO.
92 	std::vector<Resource>		outputs;
93 	// If null, a default verification will be performed by comparing the
94 	// memory pointed to by outputAllocations  and the contents of
95 	// expectedOutputs. Otherwise the function pointed to by verifyIO will
96 	// be called. If true is returned, then the test case is assumed to
97 	// have passed, if false is returned, then the test case is assumed
98 	// to have failed.
99 	VerifyIOFunc				verifyIO;
100 	GraphicsVerifyBinaryFunc	verifyBinary;
101 	SpirvVersion				spirvVersion;
102 
GraphicsResourcesvkt::SpirVAssembly::GraphicsResources103 							GraphicsResources()
104 								: inputFormat		(VK_FORMAT_R32G32B32A32_SFLOAT)
105 								, verifyIO			(DE_NULL)
106 								, verifyBinary		(DE_NULL)
107 								, spirvVersion		(SPIRV_VERSION_1_0)
108 							{}
109 };
110 
111 // Interface data type.
112 struct IFDataType
113 {
IFDataTypevkt::SpirVAssembly::IFDataType114 						IFDataType			(deUint32 numE, NumberType elementT)
115 							: numElements	(numE)
116 							, elementType	(elementT)
117 						{
118 							DE_ASSERT(numE > 0 && numE < 5);
119 							DE_ASSERT(elementT != NUMBERTYPE_END32 && elementT != NUMBERTYPE_END16);
120 						}
121 
IFDataTypevkt::SpirVAssembly::IFDataType122 						IFDataType			(const IFDataType& that)
123 							: numElements	(that.numElements)
124 							, elementType	(that.elementType)
125 						{}
126 
127 	deUint32			getElementNumBytes	(void) const;
getNumBytesvkt::SpirVAssembly::IFDataType128 	deUint32			getNumBytes			(void) const { return numElements * getElementNumBytes(); }
129 
130 	vk::VkFormat		getVkFormat			(void) const;
131 
132 	tcu::TextureFormat	getTextureFormat	(void) const;
133 
134 	std::string			str					(void) const;
135 
elementIs32bitvkt::SpirVAssembly::IFDataType136 	bool				elementIs32bit		(void) const { return elementType < NUMBERTYPE_END32; }
elementIs64bitvkt::SpirVAssembly::IFDataType137 	bool				elementIs64bit		(void) const { return elementType > NUMBERTYPE_END16; }
138 
isVectorvkt::SpirVAssembly::IFDataType139 	bool				isVector			(void) const { return numElements > 1; }
140 
141 	deUint32			numElements;
142 	NumberType			elementType;
143 };
144 
145 typedef std::pair<IFDataType, BufferSp>			Interface;
146 
147 // Interface variables used by graphics-pipeline-based tests.
148 class GraphicsInterfaces
149 {
150 public:
GraphicsInterfaces()151 						GraphicsInterfaces	()
152 							: rndMode	(static_cast<RoundingModeFlags>(0))
153 						{}
154 
GraphicsInterfaces(const GraphicsInterfaces & that)155 						GraphicsInterfaces	(const GraphicsInterfaces& that)
156 							: inputs	(that.inputs)
157 							, outputs	(that.outputs)
158 							, rndMode	(that.rndMode)
159 						{}
160 
setInputOutput(const Interface & input,const Interface & output)161 	void				setInputOutput		(const Interface& input, const Interface&  output)
162 						{
163 							inputs.clear();
164 							outputs.clear();
165 							inputs.push_back(input);
166 							outputs.push_back(output);
167 						}
168 
getInputType(void) const169 	const IFDataType&	getInputType		(void) const
170 						{
171 							DE_ASSERT(inputs.size() == 1);
172 							return inputs.front().first;
173 						}
174 
getOutputType(void) const175 	const IFDataType&	getOutputType		(void) const
176 						{
177 							DE_ASSERT(outputs.size() == 1);
178 							return outputs.front().first;
179 						}
180 
getInputBuffer(void) const181 	const BufferSp&		getInputBuffer		(void) const
182 						{
183 							DE_ASSERT(inputs.size() == 1);
184 							return inputs.front().second;
185 						}
186 
getOutputBuffer(void) const187 	const BufferSp&		getOutputBuffer		(void) const
188 						{
189 							DE_ASSERT(outputs.size() == 1);
190 							return outputs.front().second;
191 						}
192 
empty(void) const193 	bool				empty				(void) const
194 						{
195 							return inputs.size() == 0;
196 						}
197 
setRoundingMode(RoundingModeFlags flag)198 	void				setRoundingMode		(RoundingModeFlags flag)
199 						{
200 							rndMode = flag;
201 						}
getRoundingMode(void) const202 	RoundingModeFlags	getRoundingMode		(void) const
203 						{
204 							return rndMode;
205 						}
206 private:
207 	// vector<Interface> acts as a null-able Interface here. Canonically we should use
208 	// std::unique_ptr, but sadly we cannot leverage C++11 in dEQP. dEQP has its own
209 	// de::UniquePtr, but still cumbersome to use in InstanceContext and do copies
210 	// at various places.
211 	// Public methods should make sure that there are less than two elements in both
212 	// members and both members have the same number of elements.
213 	std::vector<Interface>	inputs;
214 	std::vector<Interface>	outputs;
215 	RoundingModeFlags		rndMode;
216 
217 };
218 
219 struct PushConstants
220 {
221 public:
PushConstantsvkt::SpirVAssembly::PushConstants222 							PushConstants (void)
223 							{}
224 
PushConstantsvkt::SpirVAssembly::PushConstants225 							PushConstants (const PushConstants& that)
226 								: pcs	(that.pcs)
227 							{}
228 
setPushConstantvkt::SpirVAssembly::PushConstants229 	void					setPushConstant	(const BufferSp& pc)
230 							{
231 								pcs.clear();
232 								pcs.push_back(pc);
233 							}
234 
emptyvkt::SpirVAssembly::PushConstants235 	bool					empty (void) const
236 							{
237 								return pcs.empty();
238 							}
239 
getBuffervkt::SpirVAssembly::PushConstants240 	const BufferSp&			getBuffer(void) const
241 							{
242 								DE_ASSERT(pcs.size() == 1);
243 								return pcs[0];
244 							}
245 
246 private:
247 	// Right now we only support one field in the push constant block.
248 	std::vector<BufferSp>	pcs;
249 };
250 
251 // Returns the corresponding buffer usage flag bit for the given descriptor type.
252 VkBufferUsageFlagBits getMatchingBufferUsageFlagBit (VkDescriptorType dType);
253 
254 // Context for a specific test instantiation. For example, an instantiation
255 // may test colors yellow/magenta/cyan/mauve in a tesselation shader
256 // with an entry point named 'main_to_the_main'
257 struct InstanceContext
258 {
259 	// Map of modules to what entry_points we care to use from those modules.
260 	ModuleMap								moduleMap;
261 	tcu::RGBA								inputColors[4];
262 	tcu::RGBA								outputColors[4];
263 	// Concrete SPIR-V code to test via boilerplate specialization.
264 	std::map<std::string, std::string>		testCodeFragments;
265 	StageToSpecConstantMap					specConstants;
266 	bool									hasTessellation;
267 	vk::VkShaderStageFlagBits				requiredStages;
268 	std::vector<std::string>				requiredDeviceExtensions;
269 	VulkanFeatures							requestedFeatures;
270 	PushConstants							pushConstants;
271 	// Specifies the (one or more) stages that use a customized shader code.
272 	VkShaderStageFlags						customizedStages;
273 	// Possible resources used by the graphics pipeline.
274 	// If it is not empty, a single descriptor set (number 0) will be allocated
275 	// to point to all resources specified. Binding numbers are allocated in
276 	// accord with the resources' order in the vector; outputs are allocated
277 	// after inputs.
278 	GraphicsResources						resources;
279 	// Possible interface variables use by the graphics pipeline.
280 	// If it is not empty, input/output variables will be set up for shader stages
281 	// in the test. Both the input and output variable will take location #2 in the
282 	// pipeline for all stages, except that the output variable in the fragment
283 	// stage will take location #1.
284 	GraphicsInterfaces						interfaces;
285 	qpTestResult							failResult;
286 	std::string								failMessageTemplate;	//!< ${reason} in the template will be replaced with a detailed failure message
287 	bool									renderFullSquare;		// Forces to render whole render area, though with background color
288 	bool									splitRenderArea;		// Split render into multiple submissions.
289 
290 	InstanceContext (const tcu::RGBA							(&inputs)[4],
291 					 const tcu::RGBA							(&outputs)[4],
292 					 const std::map<std::string, std::string>&	testCodeFragments_,
293 					 const StageToSpecConstantMap&				specConstants_,
294 					 const PushConstants&						pushConsants_,
295 					 const GraphicsResources&					resources_,
296 					 const GraphicsInterfaces&					interfaces_,
297 					 const std::vector<std::string>&			extensions_,
298 					 VulkanFeatures								vulkanFeatures_,
299 					 VkShaderStageFlags							customizedStages_);
300 
301 	InstanceContext (const InstanceContext& other);
302 
303 	std::string getSpecializedFailMessage (const std::string& failureReason);
304 };
305 
306 enum ShaderTask
307 {
308 	SHADER_TASK_NONE = 0,
309 	SHADER_TASK_NORMAL,
310 	SHADER_TASK_UNUSED_VAR,
311 	SHADER_TASK_UNUSED_FUNC,
312 	SHADER_TASK_LAST
313 };
314 
315 enum ShaderTaskIndex
316 {
317 	SHADER_TASK_INDEX_VERTEX		= 0,
318 	SHADER_TASK_INDEX_GEOMETRY		= 1,
319 	SHADER_TASK_INDEX_TESS_CONTROL	= 2,
320 	SHADER_TASK_INDEX_TESS_EVAL		= 3,
321 	SHADER_TASK_INDEX_FRAGMENT		= 4,
322 	SHADER_TASK_INDEX_LAST			= 5
323 };
324 
325 typedef ShaderTask ShaderTaskArray[SHADER_TASK_INDEX_LAST];
326 
327 struct UnusedVariableContext
328 {
329 	InstanceContext		instanceContext;
330 	ShaderTaskArray		shaderTasks;
331 	VariableLocation	variableLocation;
332 
UnusedVariableContextvkt::SpirVAssembly::UnusedVariableContext333 	UnusedVariableContext(const InstanceContext& ctx, const ShaderTaskArray& tasks, const VariableLocation& location)
334 		: instanceContext(ctx), shaderTasks(), variableLocation(location)
335 	{
336 		deMemcpy(shaderTasks, tasks, sizeof(tasks));
337 	}
338 };
339 
340 // A description of a shader to be used for a single stage of the graphics pipeline.
341 struct ShaderElement
342 {
343 	// The module that contains this shader entrypoint.
344 	std::string					moduleName;
345 
346 	// The name of the entrypoint.
347 	std::string					entryName;
348 
349 	// Which shader stage this entry point represents.
350 	vk::VkShaderStageFlagBits	stage;
351 
352 	ShaderElement (const std::string& moduleName_, const std::string& entryPoint_, vk::VkShaderStageFlagBits shaderStage_);
353 };
354 
355 template <typename T>
numberToString(T number)356 const std::string numberToString (T number)
357 {
358 	std::stringstream ss;
359 	ss << number;
360 	return ss.str();
361 }
362 
363 void getDefaultColors (tcu::RGBA (&colors)[4]);
364 
365 void getHalfColorsFullAlpha (tcu::RGBA (&colors)[4]);
366 
367 void getInvertedDefaultColors (tcu::RGBA (&colors)[4]);
368 
369 // Creates fragments that specialize into a simple pass-through shader (of any kind).
370 std::map<std::string, std::string> passthruFragments (void);
371 
372 // Creates a combined shader module based on VkShaderStageFlagBits defined in InstanceContext.
373 void createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx);
374 
375 // Creates shaders with unused variables based on the UnusedVariableContext.
376 void createUnusedVariableModules (vk::SourceCollections& dst, UnusedVariableContext ctx);
377 
378 // This has two shaders of each stage. The first
379 // is a passthrough, the second inverts the color.
380 void createMultipleEntries (vk::SourceCollections& dst, InstanceContext);
381 
382 // Turns a vector of ShaderElements into an instance-context by setting up the mapping of modules
383 // to their contained shaders and stages. The inputs and expected outputs are given by inputColors
384 // and outputColors
385 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
386 									   const tcu::RGBA								(&inputColors)[4],
387 									   const tcu::RGBA								(&outputColors)[4],
388 									   const std::map<std::string, std::string>&	testCodeFragments,
389 									   const StageToSpecConstantMap&				specConstants,
390 									   const PushConstants&							pushConstants,
391 									   const GraphicsResources&						resources,
392 									   const GraphicsInterfaces&					interfaces,
393 									   const std::vector<std::string>&				extensions,
394 									   VulkanFeatures								vulkanFeatures,
395 									   VkShaderStageFlags							customizedStages,
396 									   const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
397 									   const std::string&							failMessageTemplate	= std::string());
398 
399 // Same as above but using a statically sized array.
400 template <size_t N>
createInstanceContext(const ShaderElement (& elements)[N],const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const StageToSpecConstantMap & specConstants,const PushConstants & pushConstants,const GraphicsResources & resources,const GraphicsInterfaces & interfaces,const std::vector<std::string> & extensions,VulkanFeatures vulkanFeatures,VkShaderStageFlags customizedStages,const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string ())401 inline InstanceContext createInstanceContext (const ShaderElement							(&elements)[N],
402 											  const tcu::RGBA								(&inputColors)[4],
403 											  const tcu::RGBA								(&outputColors)[4],
404 											  const std::map<std::string, std::string>&		testCodeFragments,
405 											  const StageToSpecConstantMap&					specConstants,
406 											  const PushConstants&							pushConstants,
407 											  const GraphicsResources&						resources,
408 											  const GraphicsInterfaces&						interfaces,
409 											  const std::vector<std::string>&				extensions,
410 											  VulkanFeatures								vulkanFeatures,
411 											  VkShaderStageFlags							customizedStages,
412 											  const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
413 											  const std::string&							failMessageTemplate	= std::string())
414 {
415 	std::vector<ShaderElement> elementsVector(elements, elements + N);
416 	return createInstanceContext(elementsVector, inputColors, outputColors, testCodeFragments, specConstants, pushConstants,
417 								 resources, interfaces, extensions, vulkanFeatures, customizedStages, failResult, failMessageTemplate);
418 }
419 
420 // The same as createInstanceContext above, without extensions, spec constants, and resources.
421 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
422 									   tcu::RGBA									(&inputColors)[4],
423 									   const tcu::RGBA								(&outputColors)[4],
424 									   const std::map<std::string, std::string>&	testCodeFragments);
425 
426 // Same as above, but using a statically sized array.
427 template <size_t N>
createInstanceContext(const ShaderElement (& elements)[N],tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments)428 inline InstanceContext createInstanceContext (const ShaderElement							(&elements)[N],
429 											  tcu::RGBA										(&inputColors)[4],
430 											  const tcu::RGBA								(&outputColors)[4],
431 											  const std::map<std::string, std::string>&		testCodeFragments)
432 {
433 	std::vector<ShaderElement> elementsVector(elements, elements + N);
434 	return createInstanceContext(elementsVector, inputColors, outputColors, testCodeFragments);
435 }
436 
437 // The same as createInstanceContext above, but with default colors.
438 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
439 									   const std::map<std::string, std::string>&	testCodeFragments);
440 
441 // Same as above, but using a statically sized array.
442 template<size_t N>
createInstanceContext(const ShaderElement (& elements)[N],const std::map<std::string,std::string> & testCodeFragments)443 inline InstanceContext createInstanceContext (const ShaderElement						(&elements)[N],
444 											  const std::map<std::string, std::string>&	testCodeFragments)
445 {
446 	std::vector<ShaderElement> elementsVector(elements, elements + N);
447 	return createInstanceContext(elementsVector, testCodeFragments);
448 }
449 
450 
451 // Create an unused variable context for the given combination.
452 UnusedVariableContext createUnusedVariableContext(const ShaderTaskArray& shaderTasks, const VariableLocation& location);
453 
454 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
455 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
456 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
457 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
458 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
459 
460 void createTestForStage (vk::VkShaderStageFlagBits					stage,
461 						 const std::string&							name,
462 						 const tcu::RGBA							(&inputColors)[4],
463 						 const tcu::RGBA							(&outputColors)[4],
464 						 const std::map<std::string, std::string>&	testCodeFragments,
465 						 const SpecConstants&						specConstants,
466 						 const PushConstants&						pushConstants,
467 						 const GraphicsResources&					resources,
468 						 const GraphicsInterfaces&					interfaces,
469 						 const std::vector<std::string>&			extensions,
470 						 VulkanFeatures								vulkanFeatures,
471 						 tcu::TestCaseGroup*						tests,
472 						 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
473 						 const std::string&							failMessageTemplate = std::string(),
474 						 const bool									renderFullSquare	= false,
475 						 const bool									splitRenderArea		= false);
476 
477 void createTestsForAllStages (const std::string&						name,
478 							  const tcu::RGBA							(&inputColors)[4],
479 							  const tcu::RGBA							(&outputColors)[4],
480 							  const std::map<std::string, std::string>&	testCodeFragments,
481 							  const SpecConstants&						specConstants,
482 							  const PushConstants&						pushConstants,
483 							  const GraphicsResources&					resources,
484 							  const GraphicsInterfaces&					interfaces,
485 							  const std::vector<std::string>&			extensions,
486 							  VulkanFeatures							vulkanFeatures,
487 							  tcu::TestCaseGroup*						tests,
488 							  const qpTestResult						failResult			= QP_TEST_RESULT_FAIL,
489 							  const std::string&						failMessageTemplate	= std::string(),
490 							  const bool								splitRenderArea		= false);
491 
createTestsForAllStages(const std::string & name,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,tcu::TestCaseGroup * tests,const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string ())492 inline void createTestsForAllStages (const std::string&							name,
493 									 const tcu::RGBA							(&inputColors)[4],
494 									 const tcu::RGBA							(&outputColors)[4],
495 									 const std::map<std::string, std::string>&	testCodeFragments,
496 									 tcu::TestCaseGroup*						tests,
497 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
498 									 const std::string&							failMessageTemplate	= std::string())
499 {
500 	SpecConstants				noSpecConstants;
501 	PushConstants				noPushConstants;
502 	GraphicsResources			noResources;
503 	GraphicsInterfaces			noInterfaces;
504 	std::vector<std::string>	noExtensions;
505 
506 	createTestsForAllStages(
507 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
508 			noResources, noInterfaces, noExtensions, VulkanFeatures(),
509 			tests, failResult, failMessageTemplate);
510 }
511 
createTestsForAllStages(const std::string & name,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const SpecConstants & specConstants,tcu::TestCaseGroup * tests,const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string ())512 inline void createTestsForAllStages (const std::string&							name,
513 									 const tcu::RGBA							(&inputColors)[4],
514 									 const tcu::RGBA							(&outputColors)[4],
515 									 const std::map<std::string, std::string>&	testCodeFragments,
516 									 const SpecConstants&						specConstants,
517 									 tcu::TestCaseGroup*						tests,
518 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
519 									 const std::string&							failMessageTemplate	= std::string())
520 {
521 	PushConstants					noPushConstants;
522 	GraphicsResources				noResources;
523 	GraphicsInterfaces				noInterfaces;
524 	std::vector<std::string>		noExtensions;
525 
526 	createTestsForAllStages(
527 			name, inputColors, outputColors, testCodeFragments, specConstants, noPushConstants,
528 			noResources, noInterfaces, noExtensions, VulkanFeatures(),
529 			tests, failResult, failMessageTemplate);
530 }
531 
createTestsForAllStages(const std::string & name,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const GraphicsResources & resources,const std::vector<std::string> & extensions,tcu::TestCaseGroup * tests,VulkanFeatures vulkanFeatures=VulkanFeatures (),const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string (),const bool splitRenderArea=false)532 inline void createTestsForAllStages (const std::string&							name,
533 									 const tcu::RGBA							(&inputColors)[4],
534 									 const tcu::RGBA							(&outputColors)[4],
535 									 const std::map<std::string, std::string>&	testCodeFragments,
536 									 const GraphicsResources&					resources,
537 									 const std::vector<std::string>&			extensions,
538 									 tcu::TestCaseGroup*						tests,
539 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
540 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
541 									 const std::string&							failMessageTemplate	= std::string(),
542 									 const bool									splitRenderArea = false)
543 {
544 	SpecConstants				noSpecConstants;
545 	PushConstants				noPushConstants;
546 	GraphicsInterfaces			noInterfaces;
547 
548 	createTestsForAllStages(
549 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
550 			resources, noInterfaces, extensions, vulkanFeatures,
551 			tests, failResult, failMessageTemplate, splitRenderArea );
552 }
553 
createTestsForAllStages(const std::string & name,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const GraphicsInterfaces interfaces,const std::vector<std::string> & extensions,tcu::TestCaseGroup * tests,VulkanFeatures vulkanFeatures=VulkanFeatures (),const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string ())554 inline void createTestsForAllStages (const std::string& name,
555 									 const tcu::RGBA							(&inputColors)[4],
556 									 const tcu::RGBA							(&outputColors)[4],
557 									 const std::map<std::string, std::string>&	testCodeFragments,
558 									 const GraphicsInterfaces					interfaces,
559 									 const std::vector<std::string>&			extensions,
560 									 tcu::TestCaseGroup*						tests,
561 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
562 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
563 									 const std::string&							failMessageTemplate	= std::string())
564 {
565 	GraphicsResources			noResources;
566 	SpecConstants				noSpecConstants;
567 	PushConstants				noPushConstants;
568 
569 	createTestsForAllStages(
570 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
571 			noResources, interfaces, extensions, vulkanFeatures,
572 			tests, failResult, failMessageTemplate);
573 }
574 
createTestsForAllStages(const std::string & name,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const PushConstants & pushConstants,const GraphicsResources & resources,const std::vector<std::string> & extensions,tcu::TestCaseGroup * tests,VulkanFeatures vulkanFeatures=VulkanFeatures (),const qpTestResult failResult=QP_TEST_RESULT_FAIL,const std::string & failMessageTemplate=std::string ())575 inline void createTestsForAllStages (const std::string& name,
576 									 const tcu::RGBA							(&inputColors)[4],
577 									 const tcu::RGBA							(&outputColors)[4],
578 									 const std::map<std::string, std::string>&	testCodeFragments,
579 									 const PushConstants&						pushConstants,
580 									 const GraphicsResources&					resources,
581 									 const std::vector<std::string>&			extensions,
582 									 tcu::TestCaseGroup*						tests,
583 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
584 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
585 									 const std::string&							failMessageTemplate	= std::string())
586 {
587 	SpecConstants					noSpecConstants;
588 	GraphicsInterfaces				noInterfaces;
589 
590 	createTestsForAllStages(
591 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, pushConstants,
592 			resources, noInterfaces, extensions, vulkanFeatures,
593 			tests, failResult, failMessageTemplate);
594 }
595 
596 // Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
597 // Feeds the pipeline a set of colored triangles, which then must occur in the
598 // rendered image.  The surface is cleared before executing the pipeline, so
599 // whatever the shaders draw can be directly spot-checked.
600 tcu::TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance);
601 
602 // Use the instance context in the UnusedVariableContext to run the function above.
603 tcu::TestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext);
604 
605 // Adds a new test to group using custom fragments for the tessellation-control
606 // stage and passthrough fragments for all other stages.  Uses default colors
607 // for input and expected output.
608 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const std::map<std::string, std::string>& fragments);
609 
610 // Given the original 32-bit float value, computes the corresponding 16-bit
611 // float value under the given rounding mode flags and compares with the
612 // returned 16-bit float value. Returns true if they are considered as equal.
613 //
614 // The following equivalence criteria are respected:
615 // * Positive and negative zeros are considered equivalent.
616 // * Denormalized floats are allowed to be flushed to zeros, including
617 //   * Inputted 32bit denormalized float
618 //   * Generated 16bit denormalized float
619 // * Different bit patterns of NaNs are allowed.
620 // * For the rest, require exactly the same bit pattern.
621 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
622 
623 // Given the original 16-bit float value, computes the corresponding 32-bit
624 // float value and compares with the returned 32-bit float value.
625 // Returns true if they are considered as equal.
626 //
627 // The following equivalence criteria are respected:
628 // * Positive and negative zeros are considered equivalent.
629 // * Denormalized floats are allowed to be flushed to zeros, including
630 //   * Inputted 16bit denormalized float
631 //   * Generated 32bit denormalized float
632 // * Different bit patterns of NaNs are allowed.
633 // * For the rest, require exactly the same bit pattern.
634 bool compare16BitFloat (deUint16 returned, float original, tcu::TestLog& log);
635 bool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error);
636 
637 // Given the original 64-bit float value, computes the corresponding 16-bit
638 // float value under the given rounding mode flags and compares with the
639 // returned 16-bit float value. Returns true if they are considered as equal.
640 //
641 // The following equivalence criteria are respected:
642 // * Positive and negative zeros are considered equivalent.
643 // * Denormalized floats are allowed to be flushed to zeros, including
644 //   * Inputted 64bit denormalized float
645 //   * Generated 16bit denormalized float
646 // * Different bit patterns of NaNs are allowed.
647 // * For the rest, require exactly the same bit pattern.
648 bool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
649 
650 // Compare the returned 32-bit float against its expected value.
651 //
652 // The following equivalence criteria are respected:
653 // * Denormalized floats are allowed to be flushed to zeros, including
654 //   * The expected value itself is a denormalized float
655 //   * The expected value is a denormalized float if converted to 16bit
656 // * Different bit patterns of NaNs/Infs are allowed.
657 // * For the rest, use C++ float equivalence check.
658 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log);
659 
660 // Compare the returned 64-bit float against its expected value.
661 //
662 // The following equivalence criteria are respected:
663 // * Denormalized floats are allowed to be flushed to zeros, including
664 //   * The expected value itself is a denormalized float
665 //   * The expected value is a denormalized float if converted to 16bit
666 // * Different bit patterns of NaNs/Infs are allowed.
667 // * For the rest, use C++ float equivalence check.
668 bool compare64BitFloat (double expected, double returned, tcu::TestLog& log);
669 
670 } // SpirVAssembly
671 } // vkt
672 
673 #endif // _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
674