Support SPIR-V 1.3 and Vulkan 1.1

The default target is SPIR-V 1.3.

For example, spirv-as will generate a SPIR-V 1.3 binary by default.
Use command line option "--target-env spv1.0" if you want to make a SPIR-V
1.0 binary or validate against SPIR-V 1.0 rules.

Example:
        # Generate a SPIR-V 1.0 binary instead of SPIR-V 1.3
	spirv-as --target-env spv1.0 a.spvasm -o a.spv
	spirv-as --target-env vulkan1.0 a.spvasm -o a.spv

        # Validate as SPIR-V 1.0.
	spirv-val --target-env spv1.0 a.spv
        # Validate as Vulkan 1.0
	spirv-val --target-env vulkan1.0 a.spv
This commit is contained in:
David Neto 2018-02-09 14:29:02 -05:00
parent 5f50e6209c
commit 00fa39318f
17 changed files with 228 additions and 81 deletions

View File

@ -126,6 +126,10 @@ SPVTOOLS_OPT_SRC_FILES := \
source/opt/workaround1209.cpp
# Locations of grammar files.
#
# TODO(dneto): Build a single set of tables that embeds versioning differences on
# a per-item basis. That must happen before SPIR-V 1.4, etc.
# https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
SPV_CORE10_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/spirv.core.grammar.json
SPV_CORE11_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.1/spirv.core.grammar.json
SPV_CORE12_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/spirv.core.grammar.json
@ -174,9 +178,26 @@ $(1)/core.insts-1.2.inc $(1)/operand.kinds-1.2.inc: \
--core-insts-output=$(1)/core.insts-1.2.inc \
--operand-kinds-output=$(1)/operand.kinds-1.2.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.2 : instructions & operands <= grammar JSON files"
$(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-1.0.inc $(1)/core.insts-1.1.inc $(1)/core.insts-1.2.inc
$(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-1.0.inc $(1)/operand.kinds-1.1.inc $(1)/operand.kinds-1.2.inc
$(LOCAL_PATH)/source/ext_inst.cpp: $(1)/glsl.std.450.insts.inc $(1)/opencl.std.insts.inc
$(1)/core.insts-unified1.inc $(1)/operand.kinds-unified1.inc: \
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
$(SPV_COREUNIFIED1_GRAMMAR) \
$(SPV_DEBUGINFO_GRAMMAR)
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
--spirv-core-grammar=$(SPV_COREUNIFIED1_GRAMMAR) \
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
--core-insts-output=$(1)/core.insts-unified1.inc \
--operand-kinds-output=$(1)/operand.kinds-unified1.inc
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.3 (from unified1) : instructions & operands <= grammar JSON files"
$(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-1.0.inc $(1)/core.insts-1.1.inc $(1)/core.insts-1.2.inc $(1)/core.insts-unified1.inc
$(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-1.0.inc $(1)/operand.kinds-1.1.inc $(1)/operand.kinds-1.2.inc $(1)/operand.kinds-unified1.inc
$(LOCAL_PATH)/source/ext_inst.cpp: \
$(1)/glsl.std.450.insts.inc \
$(1)/opencl.std.insts.inc \
$(1)/debuginfo.insts.inc \
$(1)/spv-amd-gcn-shader.insts.inc \
$(1)/spv-amd-shader-ballot.insts.inc \
$(1)/spv-amd-shader-explicit-vertex-parameter.insts.inc \
$(1)/spv-amd-shader-trinary-minmax.insts.inc
endef
$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))

View File

@ -409,6 +409,8 @@ typedef enum {
// cl_khr_il_program, latest revision.
SPV_ENV_OPENCL_EMBEDDED_2_1, // OpenCL Embedded Profile 2.1 latest revision.
SPV_ENV_OPENCL_EMBEDDED_2_2, // OpenCL Embedded Profile 2.2 latest revision.
SPV_ENV_UNIVERSAL_1_3, // SPIR-V 1.3 latest revision, no other restrictions.
SPV_ENV_VULKAN_1_1, // Vulkan 1.0 latest revision.
} spv_target_env;
// SPIR-V Validator can be parameterized with the following Universal Limits.

View File

@ -131,9 +131,15 @@ macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE)
endmacro(spvtools_extinst_lang_headers)
# SPIR-V 1.3 support is in SPIRV-Headers include/spirv/unified1
# Temporarily assume that's the last SPIR-V version in 'unified1'.
# TODO(dneto): Build a single set of tables that embeds versioning
# differences on a per-item basis. That must happen before SPIR-V 1.4, etc.
# https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
spvtools_core_tables("1.0")
spvtools_core_tables("1.1")
spvtools_core_tables("1.2")
spvtools_core_tables("unified1")
spvtools_enum_string_mapping("unified1")
spvtools_opencl_tables("unified1")
spvtools_glsl_tables("unified1")

View File

@ -79,6 +79,8 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
case SPV_ENV_OPENGL_4_2:
case SPV_ENV_OPENGL_4_3:
case SPV_ENV_OPENGL_4_5:
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_VULKAN_1_1:
*pExtInstTable = &kTable_1_0;
return SPV_SUCCESS;
default:

View File

@ -32,9 +32,15 @@ struct OpcodeDescPtrLen {
uint32_t len;
};
#include "core.insts-1.0.inc" // defines kOpcodeTableEntries_1_0
#include "core.insts-1.1.inc" // defines kOpcodeTableEntries_1_1
#include "core.insts-1.2.inc" // defines kOpcodeTableEntries_1_2
// For now, assume unified1 contains up to SPIR-V 1.3 and no later
// SPIR-V version.
// TODO(dneto): Make one set of tables, but with version tags on a
// per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
#include "core.insts-1.0.inc" // defines kOpcodeTableEntries_1_0
#include "core.insts-1.1.inc" // defines kOpcodeTableEntries_1_1
#include "core.insts-1.2.inc" // defines kOpcodeTableEntries_1_2
#include "core.insts-unified1.inc" // defines kOpcodeTableEntries_1_3
static const spv_opcode_table_t kTable_1_0 = {
ARRAY_SIZE(kOpcodeTableEntries_1_0), kOpcodeTableEntries_1_0};
@ -42,6 +48,8 @@ static const spv_opcode_table_t kTable_1_1 = {
ARRAY_SIZE(kOpcodeTableEntries_1_1), kOpcodeTableEntries_1_1};
static const spv_opcode_table_t kTable_1_2 = {
ARRAY_SIZE(kOpcodeTableEntries_1_2), kOpcodeTableEntries_1_2};
static const spv_opcode_table_t kTable_1_3 = {
ARRAY_SIZE(kOpcodeTableEntries_1_3), kOpcodeTableEntries_1_3};
// Represents a vendor tool entry in the SPIR-V XML Regsitry.
struct VendorTool {
@ -112,6 +120,10 @@ spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
case SPV_ENV_OPENCL_EMBEDDED_2_2:
*pInstTable = &kTable_1_2;
return SPV_SUCCESS;
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_VULKAN_1_1:
*pInstTable = &kTable_1_3;
return SPV_SUCCESS;
}
assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
return SPV_ERROR_INVALID_TABLE;
@ -182,9 +194,9 @@ const char* spvOpcodeString(const SpvOp opcode) {
// Use the latest SPIR-V version, which should be backward-compatible with all
// previous ones.
const auto beg = kOpcodeTableEntries_1_2;
const auto beg = kOpcodeTableEntries_1_3;
const auto end =
kOpcodeTableEntries_1_2 + ARRAY_SIZE(kOpcodeTableEntries_1_2);
kOpcodeTableEntries_1_3 + ARRAY_SIZE(kOpcodeTableEntries_1_3);
spv_opcode_desc_t value{"", opcode, 0, nullptr, 0, {}, 0, 0};
auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
return lhs.opcode < rhs.opcode;

View File

@ -20,9 +20,15 @@
#include "macro.h"
// For now, assume unified1 contains up to SPIR-V 1.3 and no later
// SPIR-V version.
// TODO(dneto): Make one set of tables, but with version tags on a
// per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
#include "operand.kinds-1.0.inc"
#include "operand.kinds-1.1.inc"
#include "operand.kinds-1.2.inc"
#include "operand.kinds-unified1.inc"
static const spv_operand_table_t kTable_1_0 = {
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_0),
@ -33,6 +39,9 @@ static const spv_operand_table_t kTable_1_1 = {
static const spv_operand_table_t kTable_1_2 = {
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_2),
pygen_variable_OperandInfoTable_1_2};
static const spv_operand_table_t kTable_1_3 = {
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_3),
pygen_variable_OperandInfoTable_1_3};
spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
spv_target_env env) {
@ -62,6 +71,10 @@ spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
case SPV_ENV_OPENCL_EMBEDDED_2_2:
*pOperandTable = &kTable_1_2;
return SPV_SUCCESS;
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_VULKAN_1_1:
*pOperandTable = &kTable_1_3;
return SPV_SUCCESS;
}
assert(0 && "Unknown spv_target_env in spvOperandTableGet()");
return SPV_ERROR_INVALID_TABLE;

View File

@ -54,6 +54,10 @@ const char* spvTargetEnvDescription(spv_target_env env) {
return "SPIR-V 1.0 (under OpenCL 4.5 semantics)";
case SPV_ENV_UNIVERSAL_1_2:
return "SPIR-V 1.2";
case SPV_ENV_UNIVERSAL_1_3:
return "SPIR-V 1.3";
case SPV_ENV_VULKAN_1_1:
return "SPIR-V 1.3 (under Vulkan 1.1 semantics)";
}
assert(0 && "Unhandled SPIR-V target environment");
return "";
@ -81,6 +85,9 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) {
case SPV_ENV_OPENCL_2_2:
case SPV_ENV_OPENCL_EMBEDDED_2_2:
return SPV_SPIRV_VERSION_WORD(1, 2);
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_VULKAN_1_1:
return SPV_SPIRV_VERSION_WORD(1, 3);
}
assert(0 && "Unhandled SPIR-V target environment");
return SPV_SPIRV_VERSION_WORD(0, 0);
@ -93,6 +100,9 @@ bool spvParseTargetEnv(const char* s, spv_target_env* env) {
if (match("vulkan1.0")) {
if (env) *env = SPV_ENV_VULKAN_1_0;
return true;
} else if (match("vulkan1.1")) {
if (env) *env = SPV_ENV_VULKAN_1_1;
return true;
} else if (match("spv1.0")) {
if (env) *env = SPV_ENV_UNIVERSAL_1_0;
return true;
@ -102,6 +112,9 @@ bool spvParseTargetEnv(const char* s, spv_target_env* env) {
} else if (match("spv1.2")) {
if (env) *env = SPV_ENV_UNIVERSAL_1_2;
return true;
} else if (match("spv1.3")) {
if (env) *env = SPV_ENV_UNIVERSAL_1_3;
return true;
} else if (match("opencl1.2embedded")) {
if (env) *env = SPV_ENV_OPENCL_EMBEDDED_1_2;
return true;
@ -165,8 +178,10 @@ bool spvIsVulkanEnv(spv_target_env env) {
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_OPENCL_2_2:
case SPV_ENV_OPENCL_EMBEDDED_2_2:
case SPV_ENV_UNIVERSAL_1_3:
return false;
case SPV_ENV_VULKAN_1_0:
case SPV_ENV_VULKAN_1_1:
return true;
}
return false;

View File

@ -35,6 +35,8 @@ spv_context spvContextCreate(spv_target_env env) {
case SPV_ENV_OPENGL_4_3:
case SPV_ENV_OPENGL_4_5:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
case SPV_ENV_VULKAN_1_1:
break;
default:
return nullptr;

View File

@ -50,7 +50,7 @@ TEST_F(BinaryHeaderGet, Default) {
ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&const_bin, endian, &header));
ASSERT_EQ(static_cast<uint32_t>(SpvMagicNumber), header.magic);
ASSERT_EQ(0x00010200u, header.version);
ASSERT_EQ(0x00010300u, header.version);
ASSERT_EQ(static_cast<uint32_t>(SPV_GENERATOR_CODEPLAY), header.generator);
ASSERT_EQ(1u, header.bound);
ASSERT_EQ(0u, header.schema);

View File

@ -240,7 +240,7 @@ INSTANTIATE_TEST_CASE_P(
NumericLiterals, RoundTripInstructionsTest,
// This test is independent of environment, so just test the one.
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"%1 = OpTypeInt 12 0\n%2 = OpConstant %1 1867\n",
"%1 = OpTypeInt 12 1\n%2 = OpConstant %1 1867\n",
@ -274,7 +274,7 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(
MemoryAccessMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"OpStore %1 %2\n", // 3 words long.
"OpStore %1 %2 None\n", // 4 words long, explicit final 0.
@ -291,7 +291,7 @@ INSTANTIATE_TEST_CASE_P(
FPFastMathModeMasks, RoundTripInstructionsTest,
Combine(
::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"OpDecorate %1 FPFastMathMode None\n",
"OpDecorate %1 FPFastMathMode NotNaN\n",
@ -305,54 +305,55 @@ INSTANTIATE_TEST_CASE_P(
"OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|Fast\n",
})), );
INSTANTIATE_TEST_CASE_P(LoopControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0,
SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
::testing::ValuesIn(std::vector<std::string>{
"OpLoopMerge %1 %2 None\n",
"OpLoopMerge %1 %2 Unroll\n",
"OpLoopMerge %1 %2 DontUnroll\n",
"OpLoopMerge %1 %2 Unroll|DontUnroll\n",
})), );
INSTANTIATE_TEST_CASE_P(
LoopControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2),
::testing::ValuesIn(std::vector<std::string>{
"OpLoopMerge %1 %2 None\n",
"OpLoopMerge %1 %2 Unroll\n",
"OpLoopMerge %1 %2 DontUnroll\n",
"OpLoopMerge %1 %2 Unroll|DontUnroll\n",
})), );
INSTANTIATE_TEST_CASE_P(LoopControlMasksV11, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
SPV_ENV_UNIVERSAL_1_2,
SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"OpLoopMerge %1 %2 DependencyInfinite\n",
"OpLoopMerge %1 %2 DependencyLength 8\n",
})), );
INSTANTIATE_TEST_CASE_P(SelectionControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0,
SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
::testing::ValuesIn(std::vector<std::string>{
"OpSelectionMerge %1 None\n",
"OpSelectionMerge %1 Flatten\n",
"OpSelectionMerge %1 DontFlatten\n",
"OpSelectionMerge %1 Flatten|DontFlatten\n",
})), );
INSTANTIATE_TEST_CASE_P(
SelectionControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2),
::testing::ValuesIn(std::vector<std::string>{
"OpSelectionMerge %1 None\n",
"OpSelectionMerge %1 Flatten\n",
"OpSelectionMerge %1 DontFlatten\n",
"OpSelectionMerge %1 Flatten|DontFlatten\n",
})), );
INSTANTIATE_TEST_CASE_P(FunctionControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0,
SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
::testing::ValuesIn(std::vector<std::string>{
"%2 = OpFunction %1 None %3\n",
"%2 = OpFunction %1 Inline %3\n",
"%2 = OpFunction %1 DontInline %3\n",
"%2 = OpFunction %1 Pure %3\n",
"%2 = OpFunction %1 Const %3\n",
"%2 = OpFunction %1 Inline|Pure|Const %3\n",
"%2 = OpFunction %1 DontInline|Const %3\n",
})), );
INSTANTIATE_TEST_CASE_P(
FunctionControlMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"%2 = OpFunction %1 None %3\n",
"%2 = OpFunction %1 Inline %3\n",
"%2 = OpFunction %1 DontInline %3\n",
"%2 = OpFunction %1 Pure %3\n",
"%2 = OpFunction %1 Const %3\n",
"%2 = OpFunction %1 Inline|Pure|Const %3\n",
"%2 = OpFunction %1 DontInline|Const %3\n",
})), );
INSTANTIATE_TEST_CASE_P(
ImageMasks, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_UNIVERSAL_1_2),
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"%2 = OpImageFetch %1 %3 %4\n",
"%2 = OpImageFetch %1 %3 %4 None\n",
@ -374,7 +375,7 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(
NewInstructionsInSPIRV1_2, RoundTripInstructionsTest,
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_2),
Combine(::testing::Values(SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
::testing::ValuesIn(std::vector<std::string>{
"OpExecutionModeId %1 SubgroupsPerWorkgroupId %2\n",
"OpExecutionModeId %1 LocalSizeId %2 %3 %4\n",
@ -547,4 +548,6 @@ INSTANTIATE_TEST_CASE_P(GeneratorStrings, GeneratorStringTest,
{65535, 32767, "Unknown(65535); 32767"},
}), );
// TODO(dneto): Test new instructions and enums in SPIR-V 1.3
} // anonymous namespace

View File

@ -41,7 +41,7 @@ TEST_P(TargetEnvTest, ValidDescription) {
TEST_P(TargetEnvTest, ValidSpirvVersion) {
auto spirv_version = spvVersionForTargetEnv(GetParam());
ASSERT_THAT(spirv_version, AnyOf(0x10000, 0x10100, 0x10200));
ASSERT_THAT(spirv_version, AnyOf(0x10000, 0x10100, 0x10200, 0x10300));
}
INSTANTIATE_TEST_CASE_P(AllTargetEnvs, TargetEnvTest,
@ -49,7 +49,7 @@ INSTANTIATE_TEST_CASE_P(AllTargetEnvs, TargetEnvTest,
TEST(GetContextTest, InvalidTargetEnvProducesNull) {
// Use a value beyond the last valid enum value.
spv_context context = spvContextCreate(static_cast<spv_target_env>(17));
spv_context context = spvContextCreate(static_cast<spv_target_env>(30));
EXPECT_EQ(context, nullptr);
}
@ -75,7 +75,9 @@ INSTANTIATE_TEST_CASE_P(
{"spv1.0", true, SPV_ENV_UNIVERSAL_1_0},
{"spv1.1", true, SPV_ENV_UNIVERSAL_1_1},
{"spv1.2", true, SPV_ENV_UNIVERSAL_1_2},
{"spv1.3", true, SPV_ENV_UNIVERSAL_1_3},
{"vulkan1.0", true, SPV_ENV_VULKAN_1_0},
{"vulkan1.1", true, SPV_ENV_VULKAN_1_1},
{"opencl2.1", true, SPV_ENV_OPENCL_2_1},
{"opencl2.2", true, SPV_ENV_OPENCL_2_2},
{"opengl4.0", true, SPV_ENV_OPENGL_4_0},
@ -89,6 +91,10 @@ INSTANTIATE_TEST_CASE_P(
{"opencl2.0embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_0},
{"opencl2.1embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_1},
{"opencl2.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_2},
{"opencl2.3", false, SPV_ENV_UNIVERSAL_1_0},
{"opencl3.0", false, SPV_ENV_UNIVERSAL_1_0},
{"vulkan1.2", false, SPV_ENV_UNIVERSAL_1_0},
{"vulkan2.0", false, SPV_ENV_UNIVERSAL_1_0},
{nullptr, false, SPV_ENV_UNIVERSAL_1_0},
{"", false, SPV_ENV_UNIVERSAL_1_0},
{"abc", false, SPV_ENV_UNIVERSAL_1_0},

View File

@ -33,6 +33,12 @@ using spvtest::MakeInstruction;
using spvtest::MakeVector;
using spvtest::TextToBinaryTest;
// Returns a generator of common Vulkan environment values to be tested.
std::vector<spv_target_env> CommonVulkanEnvs() {
return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1};
}
TEST_F(TextToBinaryTest, InvalidExtInstImportName) {
EXPECT_THAT(CompileFailure("%1 = OpExtInstImport \"Haskell.std\""),
Eq("Invalid extended instruction import 'Haskell.std'"));
@ -155,6 +161,61 @@ INSTANTIATE_TEST_CASE_P(
SpvBuiltInSubgroupLtMaskKHR})},
})), );
INSTANTIATE_TEST_CASE_P(
SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest,
// In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
// builtin enums.
Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability SubgroupBallotKHR\n",
MakeInstruction(SpvOpCapability,
{SpvCapabilitySubgroupBallotKHR})},
{"%2 = OpSubgroupBallotKHR %1 %3\n",
MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
{"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
{"OpDecorate %1 BuiltIn SubgroupEqMask\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupEqMask})},
{"OpDecorate %1 BuiltIn SubgroupGeMask\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupGeMask})},
{"OpDecorate %1 BuiltIn SubgroupGtMask\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupGtMask})},
{"OpDecorate %1 BuiltIn SubgroupLeMask\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupLeMask})},
{"OpDecorate %1 BuiltIn SubgroupLtMask\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupLtMask})},
})), );
// The old builtin names (with KHR suffix) still work in the assmebler, and
// map to the enums without the KHR.
INSTANTIATE_TEST_CASE_P(
SPV_KHR_shader_ballot_vulkan_1_1_alias_check, ExtensionAssemblyTest,
// In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
// builtin enums.
Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
ValuesIn(std::vector<AssemblyCase>{
{"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupEqMask})},
{"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupGeMask})},
{"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupGtMask})},
{"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupLeMask})},
{"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n",
MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
SpvBuiltInSubgroupLtMask})},
})), );
// SPV_KHR_shader_draw_parameters
INSTANTIATE_TEST_CASE_P(
@ -162,8 +223,7 @@ INSTANTIATE_TEST_CASE_P(
// We'll get coverage over operand tables by trying the universal
// environments, and at least one specific environment.
Combine(
Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_VULKAN_1_0),
ValuesIn(CommonVulkanEnvs()),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability DrawParameters\n",
MakeInstruction(SpvOpCapability, {SpvCapabilityDrawParameters})},
@ -184,8 +244,7 @@ INSTANTIATE_TEST_CASE_P(
SPV_KHR_subgroup_vote, ExtensionRoundTripTest,
// We'll get coverage over operand tables by trying the universal
// environments, and at least one specific environment.
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_VULKAN_1_0),
Combine(ValuesIn(CommonVulkanEnvs()),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability SubgroupVoteKHR\n",
MakeInstruction(SpvOpCapability,
@ -204,8 +263,7 @@ INSTANTIATE_TEST_CASE_P(
SPV_KHR_16bit_storage, ExtensionRoundTripTest,
// We'll get coverage over operand tables by trying the universal
// environments, and at least one specific environment.
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_VULKAN_1_0),
Combine(ValuesIn(CommonVulkanEnvs()),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability StorageBuffer16BitAccess\n",
MakeInstruction(SpvOpCapability,
@ -230,8 +288,7 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(
SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest,
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_VULKAN_1_0),
Combine(ValuesIn(CommonVulkanEnvs()),
ValuesIn(std::vector<AssemblyCase>{
// The old name maps to the new enum.
{"OpCapability StorageUniformBufferBlock16\n",
@ -250,8 +307,7 @@ INSTANTIATE_TEST_CASE_P(
SPV_KHR_device_group, ExtensionRoundTripTest,
// We'll get coverage over operand tables by trying the universal
// environments, and at least one specific environment.
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_VULKAN_1_0),
Combine(ValuesIn(CommonVulkanEnvs()),
ValuesIn(std::vector<AssemblyCase>{
{"OpCapability DeviceGroup\n",
MakeInstruction(SpvOpCapability, {SpvCapabilityDeviceGroup})},

View File

@ -208,15 +208,18 @@ inline std::string MakeLongUTF8String(size_t num_4_byte_chars) {
// Returns a vector of all valid target environment enums.
inline std::vector<spv_target_env> AllTargetEnvironments() {
return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_1_2,
SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0,
SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1,
SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2,
SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,
SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2,
SPV_ENV_OPENGL_4_3, SPV_ENV_OPENGL_4_5,
SPV_ENV_UNIVERSAL_1_2};
return {
SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_1_2,
SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0,
SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1,
SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2,
SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,
SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2,
SPV_ENV_OPENGL_4_3, SPV_ENV_OPENGL_4_5,
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3,
SPV_ENV_VULKAN_1_1,
};
}
// Returns the capabilities in a CapabilitySet as an ordered vector.

View File

@ -41,13 +41,14 @@ Options:
Numeric IDs in the binary will have the same values as in the
source. Non-numeric IDs are allocated by filling in the gaps,
starting with 1 and going up.
--target-env {vulkan1.0|spv1.0|spv1.1|spv1.2}
Use Vulkan1.0/SPIR-V1.0/SPIR-V1.1/SPIR-V1.2
--target-env {vulkan1.0|vulkan1.1|spv1.0|spv1.1|spv1.2|spv1.3}
Use Vulkan 1.0, Vulkan 1.1, SPIR-V 1.0, SPIR-V 1.1,
SPIR-V 1.2, or SPIR-V 1.3
)",
argv0, argv0);
}
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_2;
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_3;
int main(int argc, char** argv) {
const char* inFile = nullptr;

View File

@ -60,7 +60,7 @@ Options:
argv0, argv0);
}
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_2;
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_3;
int main(int argc, char** argv) {
const char* inFile = nullptr;

View File

@ -48,20 +48,22 @@ std::string GetListOfPassesAsString(const spvtools::Optimizer& optimizer) {
return ss.str();
}
const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_3;
std::string GetLegalizationPasses() {
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
spvtools::Optimizer optimizer(kDefaultEnvironment);
optimizer.RegisterLegalizationPasses();
return GetListOfPassesAsString(optimizer);
}
std::string GetOptimizationPasses() {
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
spvtools::Optimizer optimizer(kDefaultEnvironment);
optimizer.RegisterPerformancePasses();
return GetListOfPassesAsString(optimizer);
}
std::string GetSizePasses() {
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
spvtools::Optimizer optimizer(kDefaultEnvironment);
optimizer.RegisterSizePasses();
return GetListOfPassesAsString(optimizer);
}
@ -561,7 +563,7 @@ int main(int argc, const char** argv) {
const char* out_file = nullptr;
bool skip_validator = false;
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spv_target_env target_env = kDefaultEnvironment;
spv_validator_options options = spvValidatorOptionsCreate();
spvtools::Optimizer optimizer(target_env);

View File

@ -58,7 +58,7 @@ Options:
int main(int argc, char** argv) {
const char* inFile = nullptr;
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_3;
spvtools::ValidatorOptions options;
bool continue_processing = true;
int return_code = 0;
@ -90,11 +90,14 @@ int main(int argc, char** argv) {
}
} else if (0 == strcmp(cur_arg, "--version")) {
printf("%s\n", spvSoftwareVersionDetailsString());
// TODO(dneto): Add OpenCL 2.2 at least.
printf("Targets:\n %s\n %s\n %s\n",
printf("Targets:\n %s\n %s\n %s\n %s\n %s\n %s\n %s\n",
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0),
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_1),
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_2),
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_3),
spvTargetEnvDescription(SPV_ENV_OPENCL_2_2),
spvTargetEnvDescription(SPV_ENV_VULKAN_1_0),
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_2));
spvTargetEnvDescription(SPV_ENV_VULKAN_1_1));
continue_processing = false;
return_code = 0;
} else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {