Skip to content

Commit

Permalink
Support SPIR-V 1.3 and Vulkan 1.1
Browse files Browse the repository at this point in the history
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
  • Loading branch information
dneto0 committed Mar 6, 2018
1 parent 5f50e62 commit 00fa393
Show file tree
Hide file tree
Showing 17 changed files with 228 additions and 81 deletions.
27 changes: 24 additions & 3 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)))

Expand Down
2 changes: 2 additions & 0 deletions include/spirv-tools/libspirv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
2 changes: 2 additions & 0 deletions source/ext_inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 17 additions & 5 deletions source/opcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,24 @@ 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};
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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions source/operand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 15 additions & 0 deletions source/spirv_target_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions source/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion test/binary_header_get_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
81 changes: 42 additions & 39 deletions test/binary_to_text_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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.
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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
Loading

0 comments on commit 00fa393

Please sign in to comment.