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 	bool						spirvVersion14;
103 
GraphicsResourcesvkt::SpirVAssembly::GraphicsResources104 							GraphicsResources()
105 								: inputFormat		(VK_FORMAT_R32G32B32A32_SFLOAT)
106 								, verifyIO			(DE_NULL)
107 								, verifyBinary		(DE_NULL)
108 								, spirvVersion		(SPIRV_VERSION_1_0)
109 								, spirvVersion14	(false)
110 							{}
111 };
112 
113 // Interface data type.
114 struct IFDataType
115 {
IFDataTypevkt::SpirVAssembly::IFDataType116 						IFDataType			(deUint32 numE, NumberType elementT)
117 							: numElements	(numE)
118 							, elementType	(elementT)
119 						{
120 							DE_ASSERT(numE > 0 && numE < 5);
121 							DE_ASSERT(elementT != NUMBERTYPE_END32 && elementT != NUMBERTYPE_END16);
122 						}
123 
IFDataTypevkt::SpirVAssembly::IFDataType124 						IFDataType			(const IFDataType& that)
125 							: numElements	(that.numElements)
126 							, elementType	(that.elementType)
127 						{}
128 
129 	deUint32			getElementNumBytes	(void) const;
getNumBytesvkt::SpirVAssembly::IFDataType130 	deUint32			getNumBytes			(void) const { return numElements * getElementNumBytes(); }
131 
132 	vk::VkFormat		getVkFormat			(void) const;
133 
134 	tcu::TextureFormat	getTextureFormat	(void) const;
135 
136 	std::string			str					(void) const;
137 
elementIs32bitvkt::SpirVAssembly::IFDataType138 	bool				elementIs32bit		(void) const { return elementType < NUMBERTYPE_END32; }
elementIs64bitvkt::SpirVAssembly::IFDataType139 	bool				elementIs64bit		(void) const { return elementType > NUMBERTYPE_END16; }
140 
isVectorvkt::SpirVAssembly::IFDataType141 	bool				isVector			(void) const { return numElements > 1; }
142 
143 	deUint32			numElements;
144 	NumberType			elementType;
145 };
146 
147 typedef std::pair<IFDataType, BufferSp>			Interface;
148 
149 // Interface variables used by graphics-pipeline-based tests.
150 class GraphicsInterfaces
151 {
152 public:
GraphicsInterfaces()153 						GraphicsInterfaces	()
154 							: rndMode	(static_cast<RoundingModeFlags>(0))
155 						{}
156 
GraphicsInterfaces(const GraphicsInterfaces & that)157 						GraphicsInterfaces	(const GraphicsInterfaces& that)
158 							: inputs	(that.inputs)
159 							, outputs	(that.outputs)
160 							, rndMode	(that.rndMode)
161 						{}
162 
setInputOutput(const Interface & input,const Interface & output)163 	void				setInputOutput		(const Interface& input, const Interface&  output)
164 						{
165 							inputs.clear();
166 							outputs.clear();
167 							inputs.push_back(input);
168 							outputs.push_back(output);
169 						}
170 
getInputType(void) const171 	const IFDataType&	getInputType		(void) const
172 						{
173 							DE_ASSERT(inputs.size() == 1);
174 							return inputs.front().first;
175 						}
176 
getOutputType(void) const177 	const IFDataType&	getOutputType		(void) const
178 						{
179 							DE_ASSERT(outputs.size() == 1);
180 							return outputs.front().first;
181 						}
182 
getInputBuffer(void) const183 	const BufferSp&		getInputBuffer		(void) const
184 						{
185 							DE_ASSERT(inputs.size() == 1);
186 							return inputs.front().second;
187 						}
188 
getOutputBuffer(void) const189 	const BufferSp&		getOutputBuffer		(void) const
190 						{
191 							DE_ASSERT(outputs.size() == 1);
192 							return outputs.front().second;
193 						}
194 
empty(void) const195 	bool				empty				(void) const
196 						{
197 							return inputs.size() == 0;
198 						}
199 
setRoundingMode(RoundingModeFlags flag)200 	void				setRoundingMode		(RoundingModeFlags flag)
201 						{
202 							rndMode = flag;
203 						}
getRoundingMode(void) const204 	RoundingModeFlags	getRoundingMode		(void) const
205 						{
206 							return rndMode;
207 						}
208 private:
209 	// vector<Interface> acts as a null-able Interface here. Canonically we should use
210 	// std::unique_ptr, but sadly we cannot leverage C++11 in dEQP. dEQP has its own
211 	// de::UniquePtr, but still cumbersome to use in InstanceContext and do copies
212 	// at various places.
213 	// Public methods should make sure that there are less than two elements in both
214 	// members and both members have the same number of elements.
215 	std::vector<Interface>	inputs;
216 	std::vector<Interface>	outputs;
217 	RoundingModeFlags		rndMode;
218 
219 };
220 
221 struct PushConstants
222 {
223 public:
PushConstantsvkt::SpirVAssembly::PushConstants224 							PushConstants (void)
225 							{}
226 
PushConstantsvkt::SpirVAssembly::PushConstants227 							PushConstants (const PushConstants& that)
228 								: pcs	(that.pcs)
229 							{}
230 
setPushConstantvkt::SpirVAssembly::PushConstants231 	void					setPushConstant	(const BufferSp& pc)
232 							{
233 								pcs.clear();
234 								pcs.push_back(pc);
235 							}
236 
emptyvkt::SpirVAssembly::PushConstants237 	bool					empty (void) const
238 							{
239 								return pcs.empty();
240 							}
241 
getBuffervkt::SpirVAssembly::PushConstants242 	const BufferSp&			getBuffer(void) const
243 							{
244 								DE_ASSERT(pcs.size() == 1);
245 								return pcs[0];
246 							}
247 
248 private:
249 	// Right now we only support one field in the push constant block.
250 	std::vector<BufferSp>	pcs;
251 };
252 
253 // Returns the corresponding buffer usage flag bit for the given descriptor type.
254 VkBufferUsageFlagBits getMatchingBufferUsageFlagBit (VkDescriptorType dType);
255 
256 // Context for a specific test instantiation. For example, an instantiation
257 // may test colors yellow/magenta/cyan/mauve in a tesselation shader
258 // with an entry point named 'main_to_the_main'
259 struct InstanceContext
260 {
261 	// Map of modules to what entry_points we care to use from those modules.
262 	ModuleMap								moduleMap;
263 	tcu::RGBA								inputColors[4];
264 	tcu::RGBA								outputColors[4];
265 	// Concrete SPIR-V code to test via boilerplate specialization.
266 	std::map<std::string, std::string>		testCodeFragments;
267 	StageToSpecConstantMap					specConstants;
268 	bool									hasTessellation;
269 	vk::VkShaderStageFlagBits				requiredStages;
270 	std::vector<std::string>				requiredDeviceExtensions;
271 	VulkanFeatures							requestedFeatures;
272 	PushConstants							pushConstants;
273 	// Specifies the (one or more) stages that use a customized shader code.
274 	VkShaderStageFlags						customizedStages;
275 	// Possible resources used by the graphics pipeline.
276 	// If it is not empty, a single descriptor set (number 0) will be allocated
277 	// to point to all resources specified. Binding numbers are allocated in
278 	// accord with the resources' order in the vector; outputs are allocated
279 	// after inputs.
280 	GraphicsResources						resources;
281 	// Possible interface variables use by the graphics pipeline.
282 	// If it is not empty, input/output variables will be set up for shader stages
283 	// in the test. Both the input and output variable will take location #2 in the
284 	// pipeline for all stages, except that the output variable in the fragment
285 	// stage will take location #1.
286 	GraphicsInterfaces						interfaces;
287 	qpTestResult							failResult;
288 	std::string								failMessageTemplate;	//!< ${reason} in the template will be replaced with a detailed failure message
289 	bool									renderFullSquare;		// Forces to render whole render area, though with background color
290 	bool									splitRenderArea;		// Split render into multiple submissions.
291 
292 	InstanceContext (const tcu::RGBA							(&inputs)[4],
293 					 const tcu::RGBA							(&outputs)[4],
294 					 const std::map<std::string, std::string>&	testCodeFragments_,
295 					 const StageToSpecConstantMap&				specConstants_,
296 					 const PushConstants&						pushConsants_,
297 					 const GraphicsResources&					resources_,
298 					 const GraphicsInterfaces&					interfaces_,
299 					 const std::vector<std::string>&			extensions_,
300 					 VulkanFeatures								vulkanFeatures_,
301 					 VkShaderStageFlags							customizedStages_);
302 
303 	InstanceContext (const InstanceContext& other);
304 
305 	std::string getSpecializedFailMessage (const std::string& failureReason);
306 };
307 
308 enum ShaderTask
309 {
310 	SHADER_TASK_NONE = 0,
311 	SHADER_TASK_NORMAL,
312 	SHADER_TASK_UNUSED_VAR,
313 	SHADER_TASK_UNUSED_FUNC,
314 	SHADER_TASK_LAST
315 };
316 
317 enum ShaderTaskIndex
318 {
319 	SHADER_TASK_INDEX_VERTEX		= 0,
320 	SHADER_TASK_INDEX_GEOMETRY		= 1,
321 	SHADER_TASK_INDEX_TESS_CONTROL	= 2,
322 	SHADER_TASK_INDEX_TESS_EVAL		= 3,
323 	SHADER_TASK_INDEX_FRAGMENT		= 4,
324 	SHADER_TASK_INDEX_LAST			= 5
325 };
326 
327 typedef ShaderTask ShaderTaskArray[SHADER_TASK_INDEX_LAST];
328 
329 struct UnusedVariableContext
330 {
331 	InstanceContext		instanceContext;
332 	ShaderTaskArray		shaderTasks;
333 	VariableLocation	variableLocation;
334 
UnusedVariableContextvkt::SpirVAssembly::UnusedVariableContext335 	UnusedVariableContext(const InstanceContext& ctx, const ShaderTaskArray& tasks, const VariableLocation& location)
336 		: instanceContext(ctx), shaderTasks(), variableLocation(location)
337 	{
338 		deMemcpy(shaderTasks, tasks, sizeof(tasks));
339 	}
340 };
341 
342 // A description of a shader to be used for a single stage of the graphics pipeline.
343 struct ShaderElement
344 {
345 	// The module that contains this shader entrypoint.
346 	std::string					moduleName;
347 
348 	// The name of the entrypoint.
349 	std::string					entryName;
350 
351 	// Which shader stage this entry point represents.
352 	vk::VkShaderStageFlagBits	stage;
353 
354 	ShaderElement (const std::string& moduleName_, const std::string& entryPoint_, vk::VkShaderStageFlagBits shaderStage_);
355 };
356 
357 template <typename T>
numberToString(T number)358 const std::string numberToString (T number)
359 {
360 	std::stringstream ss;
361 	ss << number;
362 	return ss.str();
363 }
364 
365 void getDefaultColors (tcu::RGBA (&colors)[4]);
366 
367 void getHalfColorsFullAlpha (tcu::RGBA (&colors)[4]);
368 
369 void getInvertedDefaultColors (tcu::RGBA (&colors)[4]);
370 
371 // Creates fragments that specialize into a simple pass-through shader (of any kind).
372 std::map<std::string, std::string> passthruFragments (void);
373 
374 // Creates a combined shader module based on VkShaderStageFlagBits defined in InstanceContext.
375 void createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx);
376 
377 // Creates shaders with unused variables based on the UnusedVariableContext.
378 void createUnusedVariableModules (vk::SourceCollections& dst, UnusedVariableContext ctx);
379 
380 // This has two shaders of each stage. The first
381 // is a passthrough, the second inverts the color.
382 void createMultipleEntries (vk::SourceCollections& dst, InstanceContext);
383 
384 // Turns a vector of ShaderElements into an instance-context by setting up the mapping of modules
385 // to their contained shaders and stages. The inputs and expected outputs are given by inputColors
386 // and outputColors
387 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
388 									   const tcu::RGBA								(&inputColors)[4],
389 									   const tcu::RGBA								(&outputColors)[4],
390 									   const std::map<std::string, std::string>&	testCodeFragments,
391 									   const StageToSpecConstantMap&				specConstants,
392 									   const PushConstants&							pushConstants,
393 									   const GraphicsResources&						resources,
394 									   const GraphicsInterfaces&					interfaces,
395 									   const std::vector<std::string>&				extensions,
396 									   VulkanFeatures								vulkanFeatures,
397 									   VkShaderStageFlags							customizedStages,
398 									   const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
399 									   const std::string&							failMessageTemplate	= std::string());
400 
401 // Same as above but using a statically sized array.
402 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 ())403 inline InstanceContext createInstanceContext (const ShaderElement							(&elements)[N],
404 											  const tcu::RGBA								(&inputColors)[4],
405 											  const tcu::RGBA								(&outputColors)[4],
406 											  const std::map<std::string, std::string>&		testCodeFragments,
407 											  const StageToSpecConstantMap&					specConstants,
408 											  const PushConstants&							pushConstants,
409 											  const GraphicsResources&						resources,
410 											  const GraphicsInterfaces&						interfaces,
411 											  const std::vector<std::string>&				extensions,
412 											  VulkanFeatures								vulkanFeatures,
413 											  VkShaderStageFlags							customizedStages,
414 											  const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
415 											  const std::string&							failMessageTemplate	= std::string())
416 {
417 	std::vector<ShaderElement> elementsVector(elements, elements + N);
418 	return createInstanceContext(elementsVector, inputColors, outputColors, testCodeFragments, specConstants, pushConstants,
419 								 resources, interfaces, extensions, vulkanFeatures, customizedStages, failResult, failMessageTemplate);
420 }
421 
422 // The same as createInstanceContext above, without extensions, spec constants, and resources.
423 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
424 									   tcu::RGBA									(&inputColors)[4],
425 									   const tcu::RGBA								(&outputColors)[4],
426 									   const std::map<std::string, std::string>&	testCodeFragments);
427 
428 // Same as above, but using a statically sized array.
429 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)430 inline InstanceContext createInstanceContext (const ShaderElement							(&elements)[N],
431 											  tcu::RGBA										(&inputColors)[4],
432 											  const tcu::RGBA								(&outputColors)[4],
433 											  const std::map<std::string, std::string>&		testCodeFragments)
434 {
435 	std::vector<ShaderElement> elementsVector(elements, elements + N);
436 	return createInstanceContext(elementsVector, inputColors, outputColors, testCodeFragments);
437 }
438 
439 // The same as createInstanceContext above, but with default colors.
440 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
441 									   const std::map<std::string, std::string>&	testCodeFragments);
442 
443 // Same as above, but using a statically sized array.
444 template<size_t N>
createInstanceContext(const ShaderElement (& elements)[N],const std::map<std::string,std::string> & testCodeFragments)445 inline InstanceContext createInstanceContext (const ShaderElement						(&elements)[N],
446 											  const std::map<std::string, std::string>&	testCodeFragments)
447 {
448 	std::vector<ShaderElement> elementsVector(elements, elements + N);
449 	return createInstanceContext(elementsVector, testCodeFragments);
450 }
451 
452 
453 // Create an unused variable context for the given combination.
454 UnusedVariableContext createUnusedVariableContext(const ShaderTaskArray& shaderTasks, const VariableLocation& location);
455 
456 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
457 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
458 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
459 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
460 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
461 
462 void createTestForStage (vk::VkShaderStageFlagBits					stage,
463 						 const std::string&							name,
464 						 const tcu::RGBA							(&inputColors)[4],
465 						 const tcu::RGBA							(&outputColors)[4],
466 						 const std::map<std::string, std::string>&	testCodeFragments,
467 						 const SpecConstants&						specConstants,
468 						 const PushConstants&						pushConstants,
469 						 const GraphicsResources&					resources,
470 						 const GraphicsInterfaces&					interfaces,
471 						 const std::vector<std::string>&			extensions,
472 						 VulkanFeatures								vulkanFeatures,
473 						 tcu::TestCaseGroup*						tests,
474 						 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
475 						 const std::string&							failMessageTemplate = std::string(),
476 						 const bool									renderFullSquare	= false,
477 						 const bool									splitRenderArea		= false);
478 
479 void createTestsForAllStages (const std::string&						name,
480 							  const tcu::RGBA							(&inputColors)[4],
481 							  const tcu::RGBA							(&outputColors)[4],
482 							  const std::map<std::string, std::string>&	testCodeFragments,
483 							  const SpecConstants&						specConstants,
484 							  const PushConstants&						pushConstants,
485 							  const GraphicsResources&					resources,
486 							  const GraphicsInterfaces&					interfaces,
487 							  const std::vector<std::string>&			extensions,
488 							  VulkanFeatures							vulkanFeatures,
489 							  tcu::TestCaseGroup*						tests,
490 							  const qpTestResult						failResult			= QP_TEST_RESULT_FAIL,
491 							  const std::string&						failMessageTemplate	= std::string(),
492 							  const bool								splitRenderArea		= false);
493 
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 ())494 inline void createTestsForAllStages (const std::string&							name,
495 									 const tcu::RGBA							(&inputColors)[4],
496 									 const tcu::RGBA							(&outputColors)[4],
497 									 const std::map<std::string, std::string>&	testCodeFragments,
498 									 tcu::TestCaseGroup*						tests,
499 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
500 									 const std::string&							failMessageTemplate	= std::string())
501 {
502 	SpecConstants				noSpecConstants;
503 	PushConstants				noPushConstants;
504 	GraphicsResources			noResources;
505 	GraphicsInterfaces			noInterfaces;
506 	std::vector<std::string>	noExtensions;
507 
508 	createTestsForAllStages(
509 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
510 			noResources, noInterfaces, noExtensions, VulkanFeatures(),
511 			tests, failResult, failMessageTemplate);
512 }
513 
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 ())514 inline void createTestsForAllStages (const std::string&							name,
515 									 const tcu::RGBA							(&inputColors)[4],
516 									 const tcu::RGBA							(&outputColors)[4],
517 									 const std::map<std::string, std::string>&	testCodeFragments,
518 									 const SpecConstants&						specConstants,
519 									 tcu::TestCaseGroup*						tests,
520 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
521 									 const std::string&							failMessageTemplate	= std::string())
522 {
523 	PushConstants					noPushConstants;
524 	GraphicsResources				noResources;
525 	GraphicsInterfaces				noInterfaces;
526 	std::vector<std::string>		noExtensions;
527 
528 	createTestsForAllStages(
529 			name, inputColors, outputColors, testCodeFragments, specConstants, noPushConstants,
530 			noResources, noInterfaces, noExtensions, VulkanFeatures(),
531 			tests, failResult, failMessageTemplate);
532 }
533 
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)534 inline void createTestsForAllStages (const std::string&							name,
535 									 const tcu::RGBA							(&inputColors)[4],
536 									 const tcu::RGBA							(&outputColors)[4],
537 									 const std::map<std::string, std::string>&	testCodeFragments,
538 									 const GraphicsResources&					resources,
539 									 const std::vector<std::string>&			extensions,
540 									 tcu::TestCaseGroup*						tests,
541 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
542 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
543 									 const std::string&							failMessageTemplate	= std::string(),
544 									 const bool									splitRenderArea = false)
545 {
546 	SpecConstants				noSpecConstants;
547 	PushConstants				noPushConstants;
548 	GraphicsInterfaces			noInterfaces;
549 
550 	createTestsForAllStages(
551 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
552 			resources, noInterfaces, extensions, vulkanFeatures,
553 			tests, failResult, failMessageTemplate, splitRenderArea );
554 }
555 
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 ())556 inline void createTestsForAllStages (const std::string& name,
557 									 const tcu::RGBA							(&inputColors)[4],
558 									 const tcu::RGBA							(&outputColors)[4],
559 									 const std::map<std::string, std::string>&	testCodeFragments,
560 									 const GraphicsInterfaces					interfaces,
561 									 const std::vector<std::string>&			extensions,
562 									 tcu::TestCaseGroup*						tests,
563 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
564 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
565 									 const std::string&							failMessageTemplate	= std::string())
566 {
567 	GraphicsResources			noResources;
568 	SpecConstants				noSpecConstants;
569 	PushConstants				noPushConstants;
570 
571 	createTestsForAllStages(
572 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
573 			noResources, interfaces, extensions, vulkanFeatures,
574 			tests, failResult, failMessageTemplate);
575 }
576 
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 ())577 inline void createTestsForAllStages (const std::string& name,
578 									 const tcu::RGBA							(&inputColors)[4],
579 									 const tcu::RGBA							(&outputColors)[4],
580 									 const std::map<std::string, std::string>&	testCodeFragments,
581 									 const PushConstants&						pushConstants,
582 									 const GraphicsResources&					resources,
583 									 const std::vector<std::string>&			extensions,
584 									 tcu::TestCaseGroup*						tests,
585 									 VulkanFeatures								vulkanFeatures		= VulkanFeatures(),
586 									 const qpTestResult							failResult			= QP_TEST_RESULT_FAIL,
587 									 const std::string&							failMessageTemplate	= std::string())
588 {
589 	SpecConstants					noSpecConstants;
590 	GraphicsInterfaces				noInterfaces;
591 
592 	createTestsForAllStages(
593 			name, inputColors, outputColors, testCodeFragments, noSpecConstants, pushConstants,
594 			resources, noInterfaces, extensions, vulkanFeatures,
595 			tests, failResult, failMessageTemplate);
596 }
597 
598 // Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
599 // Feeds the pipeline a set of colored triangles, which then must occur in the
600 // rendered image.  The surface is cleared before executing the pipeline, so
601 // whatever the shaders draw can be directly spot-checked.
602 tcu::TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance);
603 
604 // Use the instance context in the UnusedVariableContext to run the function above.
605 tcu::TestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext);
606 
607 // Adds a new test to group using custom fragments for the tessellation-control
608 // stage and passthrough fragments for all other stages.  Uses default colors
609 // for input and expected output.
610 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const std::map<std::string, std::string>& fragments);
611 
612 // Given the original 32-bit float value, computes the corresponding 16-bit
613 // float value under the given rounding mode flags and compares with the
614 // returned 16-bit float value. Returns true if they are considered as equal.
615 //
616 // The following equivalence criteria are respected:
617 // * Positive and negative zeros are considered equivalent.
618 // * Denormalized floats are allowed to be flushed to zeros, including
619 //   * Inputted 32bit denormalized float
620 //   * Generated 16bit denormalized float
621 // * Different bit patterns of NaNs are allowed.
622 // * For the rest, require exactly the same bit pattern.
623 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
624 
625 // Given the original 16-bit float value, computes the corresponding 32-bit
626 // float value and compares with the returned 32-bit float value.
627 // Returns true if they are considered as equal.
628 //
629 // The following equivalence criteria are respected:
630 // * Positive and negative zeros are considered equivalent.
631 // * Denormalized floats are allowed to be flushed to zeros, including
632 //   * Inputted 16bit denormalized float
633 //   * Generated 32bit denormalized float
634 // * Different bit patterns of NaNs are allowed.
635 // * For the rest, require exactly the same bit pattern.
636 bool compare16BitFloat (deUint16 returned, float original, tcu::TestLog& log);
637 bool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error);
638 
639 // Given the original 64-bit float value, computes the corresponding 16-bit
640 // float value under the given rounding mode flags and compares with the
641 // returned 16-bit float value. Returns true if they are considered as equal.
642 //
643 // The following equivalence criteria are respected:
644 // * Positive and negative zeros are considered equivalent.
645 // * Denormalized floats are allowed to be flushed to zeros, including
646 //   * Inputted 64bit denormalized float
647 //   * Generated 16bit denormalized float
648 // * Different bit patterns of NaNs are allowed.
649 // * For the rest, require exactly the same bit pattern.
650 bool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
651 
652 // Compare the returned 32-bit float against its expected value.
653 //
654 // The following equivalence criteria are respected:
655 // * Denormalized floats are allowed to be flushed to zeros, including
656 //   * The expected value itself is a denormalized float
657 //   * The expected value is a denormalized float if converted to 16bit
658 // * Different bit patterns of NaNs/Infs are allowed.
659 // * For the rest, use C++ float equivalence check.
660 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log);
661 
662 // Compare the returned 64-bit float against its expected value.
663 //
664 // The following equivalence criteria are respected:
665 // * Denormalized floats are allowed to be flushed to zeros, including
666 //   * The expected value itself is a denormalized float
667 //   * The expected value is a denormalized float if converted to 16bit
668 // * Different bit patterns of NaNs/Infs are allowed.
669 // * For the rest, use C++ float equivalence check.
670 bool compare64BitFloat (double expected, double returned, tcu::TestLog& log);
671 
672 } // SpirVAssembly
673 } // vkt
674 
675 #endif // _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
676