You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
10 KiB
297 lines
10 KiB
// Copyright (c) 2014-2020 The Khronos Group Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and/or associated documentation files (the "Materials"),
|
|
// to deal in the Materials without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Materials, and to permit persons to whom the
|
|
// Materials are furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Materials.
|
|
//
|
|
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
//
|
|
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
// IN THE MATERIALS.
|
|
|
|
#pragma once
|
|
#ifndef JSON_TO_SPIRV
|
|
#define JSON_TO_SPIRV
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <assert.h>
|
|
|
|
namespace spv {
|
|
|
|
// Reads the file in the given |path|. Returns true and the contents of the
|
|
// file on success; otherwise, returns false and an empty string.
|
|
std::pair<bool, std::string> ReadFile(const std::string& path);
|
|
|
|
// Fill in all the parameters
|
|
void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders);
|
|
|
|
// For parameterizing operands.
|
|
enum OperandClass {
|
|
OperandNone,
|
|
OperandId,
|
|
OperandVariableIds,
|
|
OperandOptionalLiteral,
|
|
OperandOptionalLiteralString,
|
|
OperandOptionalLiteralStrings,
|
|
OperandVariableLiterals,
|
|
OperandVariableIdLiteral,
|
|
OperandVariableLiteralId,
|
|
OperandAnySizeLiteralNumber,
|
|
OperandLiteralNumber,
|
|
OperandLiteralString,
|
|
OperandSource,
|
|
OperandExecutionModel,
|
|
OperandAddressing,
|
|
OperandMemory,
|
|
OperandExecutionMode,
|
|
OperandStorage,
|
|
OperandDimensionality,
|
|
OperandSamplerAddressingMode,
|
|
OperandSamplerFilterMode,
|
|
OperandSamplerImageFormat,
|
|
OperandImageChannelOrder,
|
|
OperandImageChannelDataType,
|
|
OperandImageOperands,
|
|
OperandFPFastMath,
|
|
OperandFPRoundingMode,
|
|
OperandFPDenormMode,
|
|
OperandFPOperationMode,
|
|
OperandLinkageType,
|
|
OperandAccessQualifier,
|
|
OperandFuncParamAttr,
|
|
OperandDecoration,
|
|
OperandBuiltIn,
|
|
OperandSelect,
|
|
OperandLoop,
|
|
OperandFunction,
|
|
OperandMemorySemantics,
|
|
OperandMemoryOperands,
|
|
OperandScope,
|
|
OperandGroupOperation,
|
|
OperandKernelEnqueueFlags,
|
|
OperandKernelProfilingInfo,
|
|
OperandCapability,
|
|
OperandRayFlags,
|
|
OperandRayQueryIntersection,
|
|
OperandRayQueryCommittedIntersectionType,
|
|
OperandRayQueryCandidateIntersectionType,
|
|
OperandFragmentShadingRate,
|
|
|
|
OperandOpcode,
|
|
|
|
OperandCount
|
|
};
|
|
|
|
// For direct representation of the JSON grammar "instruction_printing_class".
|
|
struct PrintingClass {
|
|
std::string tag;
|
|
std::string heading;
|
|
};
|
|
using PrintingClasses = std::vector<PrintingClass>;
|
|
|
|
// Any specific enum can have a set of capabilities that allow it:
|
|
typedef std::vector<std::string> EnumCaps;
|
|
|
|
// A set of extensions.
|
|
typedef std::vector<std::string> Extensions;
|
|
|
|
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
|
class OperandParameters {
|
|
public:
|
|
OperandParameters() { }
|
|
void push(OperandClass oc, const std::string& d, bool opt = false)
|
|
{
|
|
opClass.push_back(oc);
|
|
desc.push_back(d);
|
|
optional.push_back(opt);
|
|
}
|
|
void setOptional();
|
|
OperandClass getClass(int op) const { return opClass[op]; }
|
|
const char* getDesc(int op) const { return desc[op].c_str(); }
|
|
bool isOptional(int op) const { return optional[op]; }
|
|
int getNum() const { return (int)opClass.size(); }
|
|
|
|
protected:
|
|
std::vector<OperandClass> opClass;
|
|
std::vector<std::string> desc;
|
|
std::vector<bool> optional;
|
|
};
|
|
|
|
// An ordered sequence of EValue. We'll preserve the order found in the
|
|
// JSON file. You can look up a value by enum or by name. If there are
|
|
// duplicate values, then take the first. We assume names are unique.
|
|
// The EValue must have an unsigned |value| field and a string |name| field.
|
|
template <typename EValue>
|
|
class EnumValuesContainer {
|
|
public:
|
|
using ContainerType = std::vector<EValue>;
|
|
using iterator = typename ContainerType::iterator;
|
|
using const_iterator = typename ContainerType::const_iterator;
|
|
|
|
EnumValuesContainer() {}
|
|
|
|
// Constructs an EValue in place as a new element at the end of the
|
|
// sequence.
|
|
template <typename... Args>
|
|
void emplace_back(Args&&... args) {
|
|
values.emplace_back(std::forward<Args>(args)...);
|
|
}
|
|
|
|
// Returns the first EValue in the sequence with the given value.
|
|
// More than one EValue might have the same value.
|
|
EValue& operator[](unsigned value) {
|
|
auto where = std::find_if(begin(), end(), [&value](const EValue& e) {
|
|
return value == e.value;
|
|
});
|
|
assert((where != end()) && "Could not find enum in the enum list");
|
|
return *where;
|
|
}
|
|
// gets *all* entries for the value, including the first one
|
|
void gatherAliases(unsigned value, std::vector<EValue*>& aliases) {
|
|
std::for_each(begin(), end(), [&](EValue& e) {
|
|
if (value == e.value)
|
|
aliases.push_back(&e);});
|
|
}
|
|
// Returns the EValue with the given name. We assume uniqueness
|
|
// by name.
|
|
EValue& at(std::string name) {
|
|
auto where = std::find_if(begin(), end(), [&name](const EValue& e) {
|
|
return name == e.name;
|
|
});
|
|
assert((where != end()) && "Could not find name in the enum list");
|
|
return *where;
|
|
}
|
|
|
|
iterator begin() { return values.begin(); }
|
|
iterator end() { return values.end(); }
|
|
|
|
private:
|
|
ContainerType values;
|
|
};
|
|
|
|
// A single enumerant value. Corresponds to a row in an enumeration table
|
|
// in the spec.
|
|
class EnumValue {
|
|
public:
|
|
EnumValue() : value(0), desc(nullptr) {}
|
|
EnumValue(unsigned int the_value, const std::string& the_name, EnumCaps&& the_caps,
|
|
const std::string& the_firstVersion, const std::string& the_lastVersion,
|
|
Extensions&& the_extensions, OperandParameters&& the_operands) :
|
|
value(the_value), name(the_name), capabilities(std::move(the_caps)),
|
|
firstVersion(std::move(the_firstVersion)), lastVersion(std::move(the_lastVersion)),
|
|
extensions(std::move(the_extensions)), operands(std::move(the_operands)), desc(nullptr) { }
|
|
|
|
// For ValueEnum, the value from the JSON file.
|
|
// For BitEnum, the index of the bit position represented by this mask.
|
|
// (That is, what you shift 1 by to get the mask.)
|
|
unsigned value;
|
|
std::string name;
|
|
EnumCaps capabilities;
|
|
std::string firstVersion;
|
|
std::string lastVersion;
|
|
// A feature only be enabled by certain extensions.
|
|
// An empty list means the feature does not require an extension.
|
|
// Normally, only Capability enums are enabled by extension. In turn,
|
|
// other enums and instructions are enabled by those capabilities.
|
|
Extensions extensions;
|
|
OperandParameters operands;
|
|
const char* desc;
|
|
};
|
|
|
|
using EnumValues = EnumValuesContainer<EnumValue>;
|
|
|
|
// Parameterize a set of enumerants that form an enum
|
|
class EnumDefinition {
|
|
public:
|
|
EnumDefinition() :
|
|
desc(0), bitmask(false), enumValues(nullptr) { }
|
|
void set(const std::string& enumName, EnumValues* enumValuesArg, bool mask = false)
|
|
{
|
|
codeName = enumName;
|
|
bitmask = mask;
|
|
enumValues = enumValuesArg;
|
|
}
|
|
// Returns the first EnumValue in the sequence with the given value.
|
|
// More than one EnumValue might have the same value. Only valid
|
|
// if enumValues has been populated.
|
|
EnumValue& operator[](unsigned value) {
|
|
assert(enumValues != nullptr);
|
|
return (*enumValues)[value];
|
|
}
|
|
// Returns the name of the first EnumValue with the given value.
|
|
// Assumes enumValues has been populated.
|
|
const char* getName(unsigned value) {
|
|
return (*this)[value].name.c_str();
|
|
}
|
|
|
|
using iterator = EnumValues::iterator;
|
|
iterator begin() { return enumValues->begin(); }
|
|
iterator end() { return enumValues->end(); }
|
|
|
|
std::string codeName; // name to use when declaring headers for code
|
|
const char* desc;
|
|
bool bitmask; // true if these enumerants combine into a bitmask
|
|
EnumValues* enumValues; // parameters for each individual enumerant
|
|
};
|
|
|
|
// Parameterize an instruction's logical format, including its known set of operands,
|
|
// per OperandParameters above.
|
|
class InstructionValue : public EnumValue {
|
|
public:
|
|
InstructionValue(EnumValue&& e, const std::string& printClass, bool has_type, bool has_result)
|
|
: EnumValue(std::move(e)),
|
|
printingClass(printClass),
|
|
opDesc("TBD"),
|
|
typePresent(has_type),
|
|
resultPresent(has_result),
|
|
alias(this) { }
|
|
InstructionValue(const InstructionValue& v)
|
|
{
|
|
*this = v;
|
|
alias = this;
|
|
}
|
|
|
|
bool hasResult() const { return resultPresent != 0; }
|
|
bool hasType() const { return typePresent != 0; }
|
|
void setAlias(const InstructionValue& a) { alias = &a; }
|
|
const InstructionValue& getAlias() const { return *alias; }
|
|
bool isAlias() const { return alias != this; }
|
|
|
|
std::string printingClass;
|
|
const char* opDesc;
|
|
|
|
protected:
|
|
int typePresent : 1;
|
|
int resultPresent : 1;
|
|
const InstructionValue* alias; // correct only after discovering the aliases; otherwise points to this
|
|
};
|
|
|
|
using InstructionValues = EnumValuesContainer<InstructionValue>;
|
|
|
|
// Parameterization info for all instructions.
|
|
extern InstructionValues InstructionDesc;
|
|
extern PrintingClasses InstructionPrintingClasses;
|
|
|
|
// These hold definitions of the enumerants used for operands.
|
|
// This is indexed by OperandClass, but not including OperandOpcode.
|
|
extern EnumDefinition OperandClassParams[];
|
|
|
|
}; // end namespace spv
|
|
|
|
#endif // JSON_TO_SPIRV
|