| #ifndef _VKTSPVASMUTILS_HPP |
| #define _VKTSPVASMUTILS_HPP |
| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2017 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Utilities for Vulkan SPIR-V assembly tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vkDefs.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkRef.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vktTestCase.hpp" |
| |
| #include "deMemory.h" |
| #include "deUniquePtr.hpp" |
| #include "deSharedPtr.hpp" |
| #include "deRandom.hpp" |
| #include "deFloat16.h" |
| |
| #include <string> |
| #include <vector> |
| |
| namespace vkt |
| { |
| namespace SpirVAssembly |
| { |
| |
| #define SPIRV_ASSEMBLY_TYPES \ |
| "%void = OpTypeVoid\n" \ |
| "%bool = OpTypeBool\n" \ |
| \ |
| "%i32 = OpTypeInt 32 1\n" \ |
| "%u32 = OpTypeInt 32 0\n" \ |
| \ |
| "%f32 = OpTypeFloat 32\n" \ |
| "%v2i32 = OpTypeVector %i32 2\n" \ |
| "%v2u32 = OpTypeVector %u32 2\n" \ |
| "%v2f32 = OpTypeVector %f32 2\n" \ |
| "%v3i32 = OpTypeVector %i32 3\n" \ |
| "%v3u32 = OpTypeVector %u32 3\n" \ |
| "%v3f32 = OpTypeVector %f32 3\n" \ |
| "%v4i32 = OpTypeVector %i32 4\n" \ |
| "%v4u32 = OpTypeVector %u32 4\n" \ |
| "%v4f32 = OpTypeVector %f32 4\n" \ |
| "%v4bool = OpTypeVector %bool 4\n" \ |
| \ |
| "%v4f32_v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ |
| "%bool_function = OpTypeFunction %bool\n" \ |
| "%voidf = OpTypeFunction %void\n" \ |
| \ |
| "%ip_f32 = OpTypePointer Input %f32\n" \ |
| "%ip_i32 = OpTypePointer Input %i32\n" \ |
| "%ip_u32 = OpTypePointer Input %u32\n" \ |
| "%ip_v2f32 = OpTypePointer Input %v2f32\n" \ |
| "%ip_v2i32 = OpTypePointer Input %v2i32\n" \ |
| "%ip_v2u32 = OpTypePointer Input %v2u32\n" \ |
| "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ |
| "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ |
| "%ip_v4i32 = OpTypePointer Input %v4i32\n" \ |
| "%ip_v4u32 = OpTypePointer Input %v4u32\n" \ |
| \ |
| "%op_f32 = OpTypePointer Output %f32\n" \ |
| "%op_i32 = OpTypePointer Output %i32\n" \ |
| "%op_u32 = OpTypePointer Output %u32\n" \ |
| "%op_v2f32 = OpTypePointer Output %v2f32\n" \ |
| "%op_v2i32 = OpTypePointer Output %v2i32\n" \ |
| "%op_v2u32 = OpTypePointer Output %v2u32\n" \ |
| "%op_v4f32 = OpTypePointer Output %v4f32\n" \ |
| "%op_v4i32 = OpTypePointer Output %v4i32\n" \ |
| "%op_v4u32 = OpTypePointer Output %v4u32\n" \ |
| \ |
| "%fp_f32 = OpTypePointer Function %f32\n" \ |
| "%fp_i32 = OpTypePointer Function %i32\n" \ |
| "%fp_v4f32 = OpTypePointer Function %v4f32\n" \ |
| |
| #define SPIRV_ASSEMBLY_CONSTANTS \ |
| "%c_f32_1 = OpConstant %f32 1.0\n" \ |
| "%c_f32_0 = OpConstant %f32 0.0\n" \ |
| "%c_f32_0_5 = OpConstant %f32 0.5\n" \ |
| "%c_f32_n1 = OpConstant %f32 -1.\n" \ |
| "%c_f32_7 = OpConstant %f32 7.0\n" \ |
| "%c_f32_8 = OpConstant %f32 8.0\n" \ |
| "%c_i32_0 = OpConstant %i32 0\n" \ |
| "%c_i32_1 = OpConstant %i32 1\n" \ |
| "%c_i32_2 = OpConstant %i32 2\n" \ |
| "%c_i32_3 = OpConstant %i32 3\n" \ |
| "%c_i32_4 = OpConstant %i32 4\n" \ |
| "%c_u32_0 = OpConstant %u32 0\n" \ |
| "%c_u32_1 = OpConstant %u32 1\n" \ |
| "%c_u32_2 = OpConstant %u32 2\n" \ |
| "%c_u32_3 = OpConstant %u32 3\n" \ |
| "%c_u32_32 = OpConstant %u32 32\n" \ |
| "%c_u32_4 = OpConstant %u32 4\n" \ |
| "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ |
| "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ |
| "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ |
| "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" \ |
| |
| #define SPIRV_ASSEMBLY_ARRAYS \ |
| "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ |
| "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ |
| "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ |
| "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ |
| "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ |
| "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ |
| "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ |
| "%op_a2f32 = OpTypePointer Output %a2f32\n" \ |
| "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ |
| "%op_a4f32 = OpTypePointer Output %a4f32\n" \ |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Abstract class for an input/output storage buffer object |
| *//*--------------------------------------------------------------------*/ |
| class BufferInterface |
| { |
| public: |
| virtual ~BufferInterface (void) {} |
| |
| virtual void getBytes (std::vector<deUint8>& bytes) const = 0; |
| virtual void getPackedBytes (std::vector<deUint8>& bytes) const = 0; |
| virtual size_t getByteSize (void) const = 0; |
| }; |
| |
| typedef de::SharedPtr<BufferInterface> BufferSp; |
| typedef de::MovePtr<vk::Allocation> AllocationMp; |
| typedef de::SharedPtr<vk::Allocation> AllocationSp; |
| |
| class Resource |
| { |
| public: |
| Resource(const BufferSp& buffer_, vk::VkDescriptorType descriptorType_ = vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) |
| : buffer(buffer_) |
| , descriptorType(descriptorType_) |
| { |
| } |
| |
| virtual const BufferSp& getBuffer () const { return buffer; } |
| virtual void getBytes (std::vector<deUint8>& bytes) const { buffer->getBytes(bytes); } |
| virtual size_t getByteSize (void) const { return buffer->getByteSize(); } |
| |
| virtual void setDescriptorType (vk::VkDescriptorType type) { descriptorType = type; } |
| virtual vk::VkDescriptorType getDescriptorType () const { return descriptorType; } |
| |
| private: |
| BufferSp buffer; |
| vk::VkDescriptorType descriptorType; |
| }; |
| |
| typedef bool (*VerifyIOFunc) (const std::vector<Resource>& inputs, |
| const std::vector<AllocationSp>& outputAllocations, |
| const std::vector<Resource>& expectedOutputs, |
| tcu::TestLog& log); |
| |
| struct SpecConstants |
| { |
| public: |
| SpecConstants (void) |
| {} |
| |
| bool empty (void) const |
| { |
| return valuesBuffer.empty(); |
| } |
| |
| size_t getValuesCount (void) const |
| { |
| return sizesBuffer.size(); |
| } |
| |
| size_t getValueSize (const size_t valueIndex) const |
| { |
| return sizesBuffer[valueIndex]; |
| } |
| |
| const void* getValuesBuffer (void) const |
| { |
| if (valuesBuffer.size() == 0) |
| return DE_NULL; |
| else |
| return static_cast<const void*>(&valuesBuffer[0]); |
| } |
| |
| template<typename T> |
| void append (const T value) |
| { |
| append(&value, sizeof(value)); |
| } |
| |
| void append (const void* buf, const size_t byteSize) |
| { |
| DE_ASSERT(byteSize > 0); |
| |
| valuesBuffer.resize(valuesBuffer.size() + byteSize); |
| deMemcpy(&valuesBuffer[valuesBuffer.size() - byteSize], buf, byteSize); |
| |
| sizesBuffer.push_back(byteSize); |
| } |
| |
| private: |
| std::vector<deUint8> valuesBuffer; |
| std::vector<size_t> sizesBuffer; |
| }; |
| |
| enum Extension8BitStorageFeatureBits |
| { |
| EXT8BITSTORAGEFEATURES_STORAGE_BUFFER = (1u << 1), |
| EXT8BITSTORAGEFEATURES_UNIFORM_STORAGE_BUFFER = (1u << 2), |
| EXT8BITSTORAGEFEATURES_PUSH_CONSTANT = (1u << 3), |
| }; |
| typedef deUint32 Extension8BitStorageFeatures; |
| |
| enum Extension16BitStorageFeatureBits |
| { |
| EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK = (1u << 1), |
| EXT16BITSTORAGEFEATURES_UNIFORM = (1u << 2), |
| EXT16BITSTORAGEFEATURES_PUSH_CONSTANT = (1u << 3), |
| EXT16BITSTORAGEFEATURES_INPUT_OUTPUT = (1u << 4), |
| }; |
| typedef deUint32 Extension16BitStorageFeatures; |
| |
| enum ExtensionVariablePointersFeaturesBits |
| { |
| EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER = (1u << 1), |
| EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS = (1u << 2), |
| }; |
| typedef deUint32 ExtensionVariablePointersFeatures; |
| |
| enum ExtensionFloat16Int8FeaturesBits |
| { |
| EXTFLOAT16INT8FEATURES_FLOAT16 = (1u << 1), |
| EXTFLOAT16INT8FEATURES_INT8 = (1u << 2), |
| }; |
| typedef deUint32 ExtensionFloat16Int8Features; |
| typedef vk::VkPhysicalDeviceFloatControlsProperties ExtensionFloatControlsFeatures; |
| |
| enum ExtensionVulkanMemoryModelFeaturesBits |
| { |
| EXTVULKANMEMORYMODELFEATURES_ENABLE = (1u << 1), |
| EXTVULKANMEMORYMODELFEATURES_DEVICESCOPE = (1u << 2), |
| EXTVULKANMEMORYMODELFEATURES_AVAILABILITYVISIBILITYCHAINS = (1u << 3), |
| }; |
| typedef deUint32 ExtensionVulkanMemoryModelFeatures; |
| |
| struct VulkanFeatures |
| { |
| vk::VkPhysicalDeviceFeatures coreFeatures; |
| ExtensionFloat16Int8Features extFloat16Int8; |
| Extension8BitStorageFeatures ext8BitStorage; |
| Extension16BitStorageFeatures ext16BitStorage; |
| ExtensionVariablePointersFeatures extVariablePointers; |
| ExtensionVulkanMemoryModelFeatures extVulkanMemoryModel; |
| ExtensionFloatControlsFeatures floatControlsProperties; |
| |
| |
| VulkanFeatures (void) |
| : extFloat16Int8 (0) |
| , ext8BitStorage (0) |
| , ext16BitStorage (0) |
| , extVariablePointers (0) |
| , extVulkanMemoryModel (0) |
| { |
| deMemset(&coreFeatures, 0, sizeof(coreFeatures)); |
| deMemset(&floatControlsProperties, 0, sizeof(ExtensionFloatControlsFeatures)); |
| floatControlsProperties.denormBehaviorIndependence = vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR; |
| floatControlsProperties.roundingModeIndependence = vk::VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE_KHR; |
| } |
| }; |
| |
| struct VariableLocation |
| { |
| deUint32 set; |
| deUint32 binding; |
| |
| // Returns a string representation of the structure suitable for test names. |
| std::string toString() const ; |
| |
| // Returns a string representation of the structure suitable for test descriptions. |
| std::string toDescription() const; |
| }; |
| |
| // Returns true if the given 8bit storage extension features in `toCheck` are all supported. |
| bool is8BitStorageFeaturesSupported (const Context& context, |
| Extension8BitStorageFeatures toCheck); |
| |
| // Returns true if the given 16bit storage extension features in `toCheck` are all supported. |
| bool isCoreFeaturesSupported (const Context& context, |
| const vk::VkPhysicalDeviceFeatures& toCheck, |
| const char** missingFeature); |
| |
| // Returns true if the given 16bit storage extension features in `toCheck` are all supported. |
| bool is16BitStorageFeaturesSupported (const Context& context, |
| Extension16BitStorageFeatures toCheck); |
| |
| // Returns true if the given variable pointers extension features in `toCheck` are all supported. |
| bool isVariablePointersFeaturesSupported (const Context& context, |
| ExtensionVariablePointersFeatures toCheck); |
| |
| // Returns true if the given 16bit float/8bit int extension features in `toCheck` are all supported. |
| bool isFloat16Int8FeaturesSupported (const Context& context, |
| ExtensionFloat16Int8Features toCheck); |
| |
| // Returns true if the given Vulkan Memory Model extension features in `toCheck` are all supported. |
| bool isVulkanMemoryModelFeaturesSupported (const Context& context, |
| ExtensionVulkanMemoryModelFeatures toCheck); |
| |
| // Returns true if the given float controls features in `toCheck` are all supported. |
| bool isFloatControlsFeaturesSupported (const Context& context, |
| const ExtensionFloatControlsFeatures& toCheck); |
| |
| deUint32 getMinRequiredVulkanVersion (const vk::SpirvVersion version); |
| |
| std::string getVulkanName (const deUint32 version); |
| |
| // Performs a bitwise copy of source to the destination type Dest. |
| template <typename Dest, typename Src> |
| Dest bitwiseCast (Src source) |
| { |
| Dest dest; |
| DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); |
| deMemcpy(&dest, &source, sizeof(dest)); |
| return dest; |
| } |
| |
| // Generate and return 64-bit integers. |
| // |
| // Expected count to be at least 16. |
| std::vector<deInt64> getInt64s (de::Random& rnd, const deUint32 count); |
| |
| // Generate and return 32-bit integers. |
| // |
| // Expected count to be at least 16. |
| std::vector<deInt32> getInt32s (de::Random& rnd, const deUint32 count); |
| |
| // Generate and return 16-bit integers. |
| // |
| // Expected count to be at least 8. |
| std::vector<deInt16> getInt16s (de::Random& rnd, const deUint32 count); |
| |
| // Generate and return 8-bit integers. |
| // |
| // Expected count to be at least 8. |
| std::vector<deInt8> getInt8s (de::Random& rnd, const deUint32 count); |
| |
| // Generate and return 64-bit floats |
| // |
| // The first 24 number pairs are manually picked, while the rest are randomly generated. |
| // Expected count to be at least 24 (numPicks). |
| std::vector<double> getFloat64s (de::Random& rnd, deUint32 count); |
| |
| // Generate and return 32-bit floats |
| // |
| // The first 24 number pairs are manually picked, while the rest are randomly generated. |
| // Expected count to be at least 24 (numPicks). |
| std::vector<float> getFloat32s (de::Random& rnd, deUint32 count); |
| |
| // Generate and return 16-bit floats and their corresponding 32-bit values. |
| // |
| // The first 14 number pairs are manually picked, while the rest are randomly generated. |
| // Expected count to be at least 14 (numPicks). |
| std::vector<deFloat16> getFloat16s (de::Random& rnd, deUint32 count); |
| |
| // Generate an OpCapability Shader line. |
| std::string getOpCapabilityShader(); |
| |
| // Generate an unused Vertex entry point. |
| std::string getUnusedEntryPoint(); |
| |
| // Generate unused decorations for an input/output buffer. |
| std::string getUnusedDecorations(const VariableLocation& location); |
| |
| // Generate unused types and constants, including a buffer type. |
| std::string getUnusedTypesAndConstants(); |
| |
| // Generate the declaration of an unused buffer variable. |
| std::string getUnusedBuffer(); |
| |
| // Generate the body of an unused function that uses the previous buffer. |
| std::string getUnusedFunctionBody(); |
| |
| } // SpirVAssembly |
| } // vkt |
| |
| #endif // _VKTSPVASMUTILS_HPP |