1 #ifndef _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
2 #define _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP
3 /*-------------------------------------------------------------------------
4 * Vulkan Conformance Tests
5 * ------------------------
7 * Copyright (c) 2017 Google Inc.
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Graphics pipeline and helper functions for SPIR-V assembly tests
24 *//*--------------------------------------------------------------------*/
26 #include "tcuCommandLine.hpp"
27 #include "tcuRGBA.hpp"
29 #include "vkPrograms.hpp"
30 #include "vktSpvAsmComputeShaderTestUtil.hpp"
31 #include "vktSpvAsmUtils.hpp"
32 #include "vktTestCaseUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deSharedPtr.hpp"
44 namespace SpirVAssembly
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;
66 NUMBERTYPE_END32, // Marks the end of 32-bit scalar types
70 NUMBERTYPE_END16, // Marks the end of 16-bit scalar types
74 typedef enum RoundingModeFlags_e
76 ROUNDINGMODE_RTE = 0x1, // Round to nearest even
77 ROUNDINGMODE_RTZ = 0x2, // Round to zero
80 typedef bool (*GraphicsVerifyBinaryFunc) (const ProgramBinary& binary);
82 // Resources used by graphics-pipeline-based tests.
83 struct GraphicsResources
85 // Resources used as inputs.
86 std::vector<Resource> inputs;
87 // Input resource format if used
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
99 VerifyIOFunc verifyIO;
100 GraphicsVerifyBinaryFunc verifyBinary;
101 SpirvVersion spirvVersion;
104 : inputFormat (VK_FORMAT_R32G32B32A32_SFLOAT)
106 , verifyBinary (DE_NULL)
107 , spirvVersion (SPIRV_VERSION_1_0)
111 // Interface data type.
114 IFDataType (deUint32 numE, NumberType elementT)
116 , elementType (elementT)
118 DE_ASSERT(numE > 0 && numE < 5);
119 DE_ASSERT(elementT != NUMBERTYPE_END32 && elementT != NUMBERTYPE_END16);
122 IFDataType (const IFDataType& that)
123 : numElements (that.numElements)
124 , elementType (that.elementType)
127 deUint32 getElementNumBytes (void) const;
128 deUint32 getNumBytes (void) const { return numElements * getElementNumBytes(); }
130 vk::VkFormat getVkFormat (void) const;
132 tcu::TextureFormat getTextureFormat (void) const;
134 std::string str (void) const;
136 bool elementIs32bit (void) const { return elementType < NUMBERTYPE_END32; }
137 bool elementIs64bit (void) const { return elementType > NUMBERTYPE_END16; }
139 bool isVector (void) const { return numElements > 1; }
141 deUint32 numElements;
142 NumberType elementType;
145 typedef std::pair<IFDataType, BufferSp> Interface;
147 // Interface variables used by graphics-pipeline-based tests.
148 class GraphicsInterfaces
151 GraphicsInterfaces ()
152 : rndMode (static_cast<RoundingModeFlags>(0))
155 GraphicsInterfaces (const GraphicsInterfaces& that)
156 : inputs (that.inputs)
157 , outputs (that.outputs)
158 , rndMode (that.rndMode)
161 void setInputOutput (const Interface& input, const Interface& output)
165 inputs.push_back(input);
166 outputs.push_back(output);
169 const IFDataType& getInputType (void) const
171 DE_ASSERT(inputs.size() == 1);
172 return inputs.front().first;
175 const IFDataType& getOutputType (void) const
177 DE_ASSERT(outputs.size() == 1);
178 return outputs.front().first;
181 const BufferSp& getInputBuffer (void) const
183 DE_ASSERT(inputs.size() == 1);
184 return inputs.front().second;
187 const BufferSp& getOutputBuffer (void) const
189 DE_ASSERT(outputs.size() == 1);
190 return outputs.front().second;
193 bool empty (void) const
195 return inputs.size() == 0;
198 void setRoundingMode (RoundingModeFlags flag)
202 RoundingModeFlags getRoundingMode (void) const
207 // vector<Interface> acts as a null-able Interface here. Canonically we should use
208 // std::unique_ptr, but sadly we cannot leverage C++11 in dEQP. dEQP has its own
209 // de::UniquePtr, but still cumbersome to use in InstanceContext and do copies
210 // at various places.
211 // Public methods should make sure that there are less than two elements in both
212 // members and both members have the same number of elements.
213 std::vector<Interface> inputs;
214 std::vector<Interface> outputs;
215 RoundingModeFlags rndMode;
225 PushConstants (const PushConstants& that)
229 void setPushConstant (const BufferSp& pc)
235 bool empty (void) const
240 const BufferSp& getBuffer(void) const
242 DE_ASSERT(pcs.size() == 1);
247 // Right now we only support one field in the push constant block.
248 std::vector<BufferSp> pcs;
251 // Returns the corresponding buffer usage flag bit for the given descriptor type.
252 VkBufferUsageFlagBits getMatchingBufferUsageFlagBit (VkDescriptorType dType);
254 // Context for a specific test instantiation. For example, an instantiation
255 // may test colors yellow/magenta/cyan/mauve in a tesselation shader
256 // with an entry point named 'main_to_the_main'
257 struct InstanceContext
259 // Map of modules to what entry_points we care to use from those modules.
261 tcu::RGBA inputColors[4];
262 tcu::RGBA outputColors[4];
263 // Concrete SPIR-V code to test via boilerplate specialization.
264 std::map<std::string, std::string> testCodeFragments;
265 StageToSpecConstantMap specConstants;
266 bool hasTessellation;
267 vk::VkShaderStageFlagBits requiredStages;
268 std::vector<std::string> requiredDeviceExtensions;
269 std::vector<std::string> requiredDeviceFeatures;
270 VulkanFeatures requestedFeatures;
271 PushConstants pushConstants;
272 // Specifies the (one or more) stages that use a customized shader code.
273 VkShaderStageFlags customizedStages;
274 // Possible resources used by the graphics pipeline.
275 // If it is not empty, a single descriptor set (number 0) will be allocated
276 // to point to all resources specified. Binding numbers are allocated in
277 // accord with the resources' order in the vector; outputs are allocated
279 GraphicsResources resources;
280 // Possible interface variables use by the graphics pipeline.
281 // If it is not empty, input/output variables will be set up for shader stages
282 // in the test. Both the input and output variable will take location #2 in the
283 // pipeline for all stages, except that the output variable in the fragment
284 // stage will take location #1.
285 GraphicsInterfaces interfaces;
286 qpTestResult failResult;
287 std::string failMessageTemplate; //!< ${reason} in the template will be replaced with a detailed failure message
288 bool renderFullSquare; // Forces to render whole render area, though with background color
290 InstanceContext (const tcu::RGBA (&inputs)[4],
291 const tcu::RGBA (&outputs)[4],
292 const std::map<std::string, std::string>& testCodeFragments_,
293 const StageToSpecConstantMap& specConstants_,
294 const PushConstants& pushConsants_,
295 const GraphicsResources& resources_,
296 const GraphicsInterfaces& interfaces_,
297 const std::vector<std::string>& extensions_,
298 const std::vector<std::string>& features_,
299 VulkanFeatures vulkanFeatures_,
300 VkShaderStageFlags customizedStages_);
302 InstanceContext (const InstanceContext& other);
304 std::string getSpecializedFailMessage (const std::string& failureReason);
307 // A description of a shader to be used for a single stage of the graphics pipeline.
310 // The module that contains this shader entrypoint.
311 std::string moduleName;
313 // The name of the entrypoint.
314 std::string entryName;
316 // Which shader stage this entry point represents.
317 vk::VkShaderStageFlagBits stage;
319 ShaderElement (const std::string& moduleName_, const std::string& entryPoint_, vk::VkShaderStageFlagBits shaderStage_);
322 template <typename T>
323 const std::string numberToString (T number)
325 std::stringstream ss;
330 // Performs a bitwise copy of source to the destination type Dest.
331 template <typename Dest, typename Src>
332 Dest bitwiseCast (Src source)
335 DE_STATIC_ASSERT(sizeof(source) == sizeof(dest));
336 deMemcpy(&dest, &source, sizeof(dest));
340 template<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue);
341 template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); }
342 template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); }
345 void getDefaultColors (tcu::RGBA (&colors)[4]);
347 void getHalfColorsFullAlpha (tcu::RGBA (&colors)[4]);
349 void getInvertedDefaultColors (tcu::RGBA (&colors)[4]);
351 // Creates fragments that specialize into a simple pass-through shader (of any kind).
352 std::map<std::string, std::string> passthruFragments (void);
354 // Creates a combined shader module based on VkShaderStageFlagBits defined in InstanceContext
355 void createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx);
357 // This has two shaders of each stage. The first
358 // is a passthrough, the second inverts the color.
359 void createMultipleEntries (vk::SourceCollections& dst, InstanceContext);
361 // Turns a statically sized array of ShaderElements into an instance-context
362 // by setting up the mapping of modules to their contained shaders and stages.
363 // The inputs and expected outputs are given by inputColors and outputColors
365 InstanceContext createInstanceContext (const ShaderElement (&elements)[N],
366 const tcu::RGBA (&inputColors)[4],
367 const tcu::RGBA (&outputColors)[4],
368 const std::map<std::string, std::string>& testCodeFragments,
369 const StageToSpecConstantMap& specConstants,
370 const PushConstants& pushConstants,
371 const GraphicsResources& resources,
372 const GraphicsInterfaces& interfaces,
373 const std::vector<std::string>& extensions,
374 const std::vector<std::string>& features,
375 VulkanFeatures vulkanFeatures,
376 VkShaderStageFlags customizedStages,
377 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
378 const std::string& failMessageTemplate = std::string())
380 InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, customizedStages);
381 for (size_t i = 0; i < N; ++i)
383 ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
384 ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | elements[i].stage);
386 ctx.failResult = failResult;
387 if (!failMessageTemplate.empty())
388 ctx.failMessageTemplate = failMessageTemplate;
392 // The same as createInstanceContext above, without extensions, spec constants, and resources.
394 inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N],
395 tcu::RGBA (&inputColors)[4],
396 const tcu::RGBA (&outputColors)[4],
397 const std::map<std::string, std::string>& testCodeFragments)
399 return createInstanceContext(elements, inputColors, outputColors, testCodeFragments,
400 StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
401 GraphicsInterfaces(), std::vector<std::string>(), std::vector<std::string>(),
402 VulkanFeatures(), vk::VK_SHADER_STAGE_ALL);
405 // The same as createInstanceContext above, but with default colors.
407 InstanceContext createInstanceContext (const ShaderElement (&elements)[N],
408 const std::map<std::string, std::string>& testCodeFragments)
410 tcu::RGBA defaultColors[4];
411 getDefaultColors(defaultColors);
412 return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
415 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
416 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
417 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
418 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
419 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions);
421 void createTestForStage (vk::VkShaderStageFlagBits stage,
422 const std::string& name,
423 const tcu::RGBA (&inputColors)[4],
424 const tcu::RGBA (&outputColors)[4],
425 const std::map<std::string, std::string>& testCodeFragments,
426 const SpecConstants& specConstants,
427 const PushConstants& pushConstants,
428 const GraphicsResources& resources,
429 const GraphicsInterfaces& interfaces,
430 const std::vector<std::string>& extensions,
431 const std::vector<std::string>& features,
432 VulkanFeatures vulkanFeatures,
433 tcu::TestCaseGroup* tests,
434 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
435 const std::string& failMessageTemplate = std::string(),
436 const bool renderFullSquare = false);
438 void createTestsForAllStages (const std::string& name,
439 const tcu::RGBA (&inputColors)[4],
440 const tcu::RGBA (&outputColors)[4],
441 const std::map<std::string, std::string>& testCodeFragments,
442 const SpecConstants& specConstants,
443 const PushConstants& pushConstants,
444 const GraphicsResources& resources,
445 const GraphicsInterfaces& interfaces,
446 const std::vector<std::string>& extensions,
447 const std::vector<std::string>& features,
448 VulkanFeatures vulkanFeatures,
449 tcu::TestCaseGroup* tests,
450 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
451 const std::string& failMessageTemplate = std::string());
453 inline void createTestsForAllStages (const std::string& name,
454 const tcu::RGBA (&inputColors)[4],
455 const tcu::RGBA (&outputColors)[4],
456 const std::map<std::string, std::string>& testCodeFragments,
457 tcu::TestCaseGroup* tests,
458 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
459 const std::string& failMessageTemplate = std::string())
461 SpecConstants noSpecConstants;
462 PushConstants noPushConstants;
463 GraphicsResources noResources;
464 GraphicsInterfaces noInterfaces;
465 std::vector<std::string> noExtensions;
466 std::vector<std::string> noFeatures;
468 createTestsForAllStages(
469 name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
470 noResources, noInterfaces, noExtensions, noFeatures, VulkanFeatures(),
471 tests, failResult, failMessageTemplate);
474 inline void createTestsForAllStages (const std::string& name,
475 const tcu::RGBA (&inputColors)[4],
476 const tcu::RGBA (&outputColors)[4],
477 const std::map<std::string, std::string>& testCodeFragments,
478 const SpecConstants& specConstants,
479 tcu::TestCaseGroup* tests,
480 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
481 const std::string& failMessageTemplate = std::string())
483 PushConstants noPushConstants;
484 GraphicsResources noResources;
485 GraphicsInterfaces noInterfaces;
486 std::vector<std::string> noExtensions;
487 std::vector<std::string> noFeatures;
489 createTestsForAllStages(
490 name, inputColors, outputColors, testCodeFragments, specConstants, noPushConstants,
491 noResources, noInterfaces, noExtensions, noFeatures, VulkanFeatures(),
492 tests, failResult, failMessageTemplate);
495 inline void createTestsForAllStages (const std::string& name,
496 const tcu::RGBA (&inputColors)[4],
497 const tcu::RGBA (&outputColors)[4],
498 const std::map<std::string, std::string>& testCodeFragments,
499 const GraphicsResources& resources,
500 const std::vector<std::string>& extensions,
501 tcu::TestCaseGroup* tests,
502 VulkanFeatures vulkanFeatures = VulkanFeatures(),
503 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
504 const std::string& failMessageTemplate = std::string())
506 SpecConstants noSpecConstants;
507 PushConstants noPushConstants;
508 GraphicsInterfaces noInterfaces;
509 std::vector<std::string> noFeatures;
511 createTestsForAllStages(
512 name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
513 resources, noInterfaces, extensions, noFeatures, vulkanFeatures,
514 tests, failResult, failMessageTemplate);
517 inline void createTestsForAllStages (const std::string& name,
518 const tcu::RGBA (&inputColors)[4],
519 const tcu::RGBA (&outputColors)[4],
520 const std::map<std::string, std::string>& testCodeFragments,
521 const GraphicsResources& resources,
522 const std::vector<std::string>& extensions,
523 const std::vector<std::string>& features,
524 tcu::TestCaseGroup* tests,
525 VulkanFeatures vulkanFeatures = VulkanFeatures(),
526 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
527 const std::string& failMessageTemplate = std::string())
529 SpecConstants noSpecConstants;
530 PushConstants noPushConstants;
531 GraphicsInterfaces noInterfaces;
533 createTestsForAllStages(
534 name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
535 resources, noInterfaces, extensions, features, vulkanFeatures,
536 tests, failResult, failMessageTemplate);
539 inline void createTestsForAllStages (const std::string& name,
540 const tcu::RGBA (&inputColors)[4],
541 const tcu::RGBA (&outputColors)[4],
542 const std::map<std::string, std::string>& testCodeFragments,
543 const GraphicsInterfaces interfaces,
544 const std::vector<std::string>& extensions,
545 tcu::TestCaseGroup* tests,
546 VulkanFeatures vulkanFeatures = VulkanFeatures(),
547 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
548 const std::string& failMessageTemplate = std::string())
550 GraphicsResources noResources;
551 SpecConstants noSpecConstants;
552 std::vector<std::string> noFeatures;
553 PushConstants noPushConstants;
555 createTestsForAllStages(
556 name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
557 noResources, interfaces, extensions, noFeatures, vulkanFeatures,
558 tests, failResult, failMessageTemplate);
561 inline void createTestsForAllStages (const std::string& name,
562 const tcu::RGBA (&inputColors)[4],
563 const tcu::RGBA (&outputColors)[4],
564 const std::map<std::string, std::string>& testCodeFragments,
565 const PushConstants& pushConstants,
566 const GraphicsResources& resources,
567 const std::vector<std::string>& extensions,
568 tcu::TestCaseGroup* tests,
569 VulkanFeatures vulkanFeatures = VulkanFeatures(),
570 const qpTestResult failResult = QP_TEST_RESULT_FAIL,
571 const std::string& failMessageTemplate = std::string())
573 SpecConstants noSpecConstants;
574 GraphicsInterfaces noInterfaces;
575 std::vector<std::string> noFeatures;
577 createTestsForAllStages(
578 name, inputColors, outputColors, testCodeFragments, noSpecConstants, pushConstants,
579 resources, noInterfaces, extensions, noFeatures, vulkanFeatures,
580 tests, failResult, failMessageTemplate);
583 // Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
584 // Feeds the pipeline a set of colored triangles, which then must occur in the
585 // rendered image. The surface is cleared before executing the pipeline, so
586 // whatever the shaders draw can be directly spot-checked.
587 tcu::TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance);
589 // Adds a new test to group using custom fragments for the tessellation-control
590 // stage and passthrough fragments for all other stages. Uses default colors
591 // for input and expected output.
592 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const std::map<std::string, std::string>& fragments);
594 // Given the original 32-bit float value, computes the corresponding 16-bit
595 // float value under the given rounding mode flags and compares with the
596 // returned 16-bit float value. Returns true if they are considered as equal.
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 32bit denormalized float
602 // * Generated 16bit denormalized float
603 // * Different bit patterns of NaNs are allowed.
604 // * For the rest, require exactly the same bit pattern.
605 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
607 // Given the original 16-bit float value, computes the corresponding 32-bit
608 // float value and compares with the returned 32-bit float value.
609 // Returns true if they are considered as equal.
611 // The following equivalence criteria are respected:
612 // * Positive and negative zeros are considered equivalent.
613 // * Denormalized floats are allowed to be flushed to zeros, including
614 // * Inputted 16bit denormalized float
615 // * Generated 32bit denormalized float
616 // * Different bit patterns of NaNs are allowed.
617 // * For the rest, require exactly the same bit pattern.
618 bool compare16BitFloat (deUint16 returned, float original, tcu::TestLog& log);
619 bool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error);
621 // Given the original 64-bit float value, computes the corresponding 16-bit
622 // float value under the given rounding mode flags and compares with the
623 // returned 16-bit float value. Returns true if they are considered as equal.
625 // The following equivalence criteria are respected:
626 // * Positive and negative zeros are considered equivalent.
627 // * Denormalized floats are allowed to be flushed to zeros, including
628 // * Inputted 64bit denormalized float
629 // * Generated 16bit denormalized float
630 // * Different bit patterns of NaNs are allowed.
631 // * For the rest, require exactly the same bit pattern.
632 bool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log);
634 // Compare the returned 32-bit float against its expected value.
636 // The following equivalence criteria are respected:
637 // * Denormalized floats are allowed to be flushed to zeros, including
638 // * The expected value itself is a denormalized float
639 // * The expected value is a denormalized float if converted to 16bit
640 // * Different bit patterns of NaNs/Infs are allowed.
641 // * For the rest, use C++ float equivalence check.
642 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log);
644 // Compare the returned 64-bit float against its expected value.
646 // The following equivalence criteria are respected:
647 // * Denormalized floats are allowed to be flushed to zeros, including
648 // * The expected value itself is a denormalized float
649 // * The expected value is a denormalized float if converted to 16bit
650 // * Different bit patterns of NaNs/Infs are allowed.
651 // * For the rest, use C++ float equivalence check.
652 bool compare64BitFloat (double expected, double returned, tcu::TestLog& log);
657 #endif // _VKTSPVASMGRAPHICSSHADERTESTUTIL_HPP