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