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