blob: 20adddcca51dfea390fedcbacb9816460b9a8119 [file] [log] [blame]
#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