mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-19 05:23:00 +01:00
Updated spirv-tools.
This commit is contained in:
1
3rdparty/spirv-tools/Android.mk
vendored
1
3rdparty/spirv-tools/Android.mk
vendored
@@ -154,6 +154,7 @@ SPVTOOLS_OPT_SRC_FILES := \
|
||||
source/opt/simplification_pass.cpp \
|
||||
source/opt/ssa_rewrite_pass.cpp \
|
||||
source/opt/strength_reduction_pass.cpp \
|
||||
source/opt/strip_atomic_counter_memory_pass.cpp \
|
||||
source/opt/strip_debug_info_pass.cpp \
|
||||
source/opt/strip_reflect_info_pass.cpp \
|
||||
source/opt/struct_cfg_analysis.cpp \
|
||||
|
||||
2
3rdparty/spirv-tools/BUILD.gn
vendored
2
3rdparty/spirv-tools/BUILD.gn
vendored
@@ -612,6 +612,8 @@ static_library("spvtools_opt") {
|
||||
"source/opt/ssa_rewrite_pass.h",
|
||||
"source/opt/strength_reduction_pass.cpp",
|
||||
"source/opt/strength_reduction_pass.h",
|
||||
"source/opt/strip_atomic_counter_memory_pass.cpp",
|
||||
"source/opt/strip_atomic_counter_memory_pass.h",
|
||||
"source/opt/strip_debug_info_pass.cpp",
|
||||
"source/opt/strip_debug_info_pass.h",
|
||||
"source/opt/strip_reflect_info_pass.cpp",
|
||||
|
||||
@@ -1 +1 @@
|
||||
"v2019.2", "SPIRV-Tools v2019.2 79f67a4905acf223f9e37a52e059a62c2bdbdc69"
|
||||
"v2019.2", "SPIRV-Tools v2019.2 45a64efab9d50ebcf9694a3297acc3223502610d"
|
||||
|
||||
@@ -8,7 +8,7 @@ static const SpvCapability pygen_variable_caps_FragmentMaskAMD[] = {SpvCapabilit
|
||||
static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
|
||||
static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered[] = {SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformClustered};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformClustered, SpvCapabilityGroupNonUniformPartitionedNV};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformBallot[] = {SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformQuad[] = {SpvCapabilityGroupNonUniformQuad};
|
||||
@@ -375,22 +375,22 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"GroupNonUniformShuffleXor", SpvOpGroupNonUniformShuffleXor, 1, pygen_variable_caps_GroupNonUniformShuffle, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleUp", SpvOpGroupNonUniformShuffleUp, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleDown", SpvOpGroupNonUniformShuffleDown, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIAdd", SpvOpGroupNonUniformIAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFAdd", SpvOpGroupNonUniformFAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIMul", SpvOpGroupNonUniformIMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMul", SpvOpGroupNonUniformFMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMin", SpvOpGroupNonUniformSMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMin", SpvOpGroupNonUniformUMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMin", SpvOpGroupNonUniformFMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMax", SpvOpGroupNonUniformSMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMax", SpvOpGroupNonUniformUMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMax", SpvOpGroupNonUniformFMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseAnd", SpvOpGroupNonUniformBitwiseAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseOr", SpvOpGroupNonUniformBitwiseOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseXor", SpvOpGroupNonUniformBitwiseXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalAnd", SpvOpGroupNonUniformLogicalAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalOr", SpvOpGroupNonUniformLogicalOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalXor", SpvOpGroupNonUniformLogicalXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIAdd", SpvOpGroupNonUniformIAdd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFAdd", SpvOpGroupNonUniformFAdd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIMul", SpvOpGroupNonUniformIMul, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMul", SpvOpGroupNonUniformFMul, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMin", SpvOpGroupNonUniformSMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMin", SpvOpGroupNonUniformUMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMin", SpvOpGroupNonUniformFMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMax", SpvOpGroupNonUniformSMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMax", SpvOpGroupNonUniformUMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMax", SpvOpGroupNonUniformFMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseAnd", SpvOpGroupNonUniformBitwiseAnd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseOr", SpvOpGroupNonUniformBitwiseOr, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseXor", SpvOpGroupNonUniformBitwiseXor, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalAnd", SpvOpGroupNonUniformLogicalAnd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalOr", SpvOpGroupNonUniformLogicalOr, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalXor", SpvOpGroupNonUniformLogicalXor, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformQuadBroadcast", SpvOpGroupNonUniformQuadBroadcast, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformQuadSwap", SpvOpGroupNonUniformQuadSwap, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupBallotKHR", SpvOpSubgroupBallotKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu},
|
||||
|
||||
@@ -208,6 +208,13 @@ class Optimizer {
|
||||
// A null pass does nothing to the SPIR-V module to be optimized.
|
||||
Optimizer::PassToken CreateNullPass();
|
||||
|
||||
// Creates a strip-atomic-counter-memory pass.
|
||||
// A strip-atomic-counter-memory pass removes all usages of the
|
||||
// AtomicCounterMemory bit in Memory Semantics bitmasks. This bit is a no-op in
|
||||
// Vulkan, so isn't needed in that env. And the related capability is not
|
||||
// allowed in WebGPU, so it is not allowed in that env.
|
||||
Optimizer::PassToken CreateStripAtomicCounterMemoryPass();
|
||||
|
||||
// Creates a strip-debug-info pass.
|
||||
// A strip-debug-info pass removes all debug instructions (as documented in
|
||||
// Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
|
||||
|
||||
32
3rdparty/spirv-tools/source/opcode.cpp
vendored
32
3rdparty/spirv-tools/source/opcode.cpp
vendored
@@ -605,3 +605,35 @@ bool spvOpcodeIsDebug(SpvOp opcode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpMemoryBarrier:
|
||||
return {1};
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpControlBarrier:
|
||||
case SpvOpAtomicFlagClear:
|
||||
case SpvOpMemoryNamedBarrier:
|
||||
return {2};
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMax:
|
||||
case SpvOpAtomicAnd:
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicFlagTestAndSet:
|
||||
return {4};
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
return {4, 5};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
4
3rdparty/spirv-tools/source/opcode.h
vendored
4
3rdparty/spirv-tools/source/opcode.h
vendored
@@ -133,4 +133,8 @@ bool spvOpcodeIsScalarizable(SpvOp opcode);
|
||||
// Returns true if the given opcode is a debug instruction.
|
||||
bool spvOpcodeIsDebug(SpvOp opcode);
|
||||
|
||||
// Returns a vector containing the indices of the memory semantics <id>
|
||||
// operands for |opcode|.
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
|
||||
|
||||
#endif // SOURCE_OPCODE_H_
|
||||
|
||||
@@ -96,6 +96,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
|
||||
simplification_pass.h
|
||||
ssa_rewrite_pass.h
|
||||
strength_reduction_pass.h
|
||||
strip_atomic_counter_memory_pass.h
|
||||
strip_debug_info_pass.h
|
||||
strip_reflect_info_pass.h
|
||||
struct_cfg_analysis.h
|
||||
@@ -189,6 +190,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
|
||||
simplification_pass.cpp
|
||||
ssa_rewrite_pass.cpp
|
||||
strength_reduction_pass.cpp
|
||||
strip_atomic_counter_memory_pass.cpp
|
||||
strip_debug_info_pass.cpp
|
||||
strip_reflect_info_pass.cpp
|
||||
struct_cfg_analysis.cpp
|
||||
|
||||
1
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
1
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
@@ -271,6 +271,7 @@ bool CCPPass::ReplaceValues() {
|
||||
uint32_t id = it.first;
|
||||
uint32_t cst_id = it.second;
|
||||
if (!IsVaryingValue(cst_id) && id != cst_id) {
|
||||
context()->KillNamesAndDecorates(id);
|
||||
retval |= context()->ReplaceAllUsesWith(id, cst_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2167,6 +2167,37 @@ FoldingRule VectorShuffleFeedingShuffle() {
|
||||
};
|
||||
}
|
||||
|
||||
// Removes duplicate ids from the interface list of an OpEntryPoint
|
||||
// instruction.
|
||||
FoldingRule RemoveRedundantOperands() {
|
||||
return [](IRContext*, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>&) {
|
||||
assert(inst->opcode() == SpvOpEntryPoint &&
|
||||
"Wrong opcode. Should be OpEntryPoint.");
|
||||
bool has_redundant_operand = false;
|
||||
std::unordered_set<uint32_t> seen_operands;
|
||||
std::vector<Operand> new_operands;
|
||||
|
||||
new_operands.emplace_back(inst->GetOperand(0));
|
||||
new_operands.emplace_back(inst->GetOperand(1));
|
||||
new_operands.emplace_back(inst->GetOperand(2));
|
||||
for (uint32_t i = 3; i < inst->NumOperands(); ++i) {
|
||||
if (seen_operands.insert(inst->GetSingleWordOperand(i)).second) {
|
||||
new_operands.emplace_back(inst->GetOperand(i));
|
||||
} else {
|
||||
has_redundant_operand = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_redundant_operand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inst->SetInOperands(std::move(new_operands));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FoldingRules::FoldingRules() {
|
||||
@@ -2183,6 +2214,8 @@ FoldingRules::FoldingRules() {
|
||||
|
||||
rules_[SpvOpDot].push_back(DotProductDoingExtract());
|
||||
|
||||
rules_[SpvOpEntryPoint].push_back(RemoveRedundantOperands());
|
||||
|
||||
rules_[SpvOpExtInst].push_back(RedundantFMix());
|
||||
|
||||
rules_[SpvOpFAdd].push_back(RedundantFAdd());
|
||||
|
||||
11
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
11
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
@@ -219,6 +219,8 @@ Optimizer& Optimizer::RegisterSizePasses() {
|
||||
|
||||
Optimizer& Optimizer::RegisterWebGPUPasses() {
|
||||
return RegisterPass(CreateStripDebugInfoPass())
|
||||
.RegisterPass(CreateStripAtomicCounterMemoryPass())
|
||||
.RegisterPass(CreateEliminateDeadConstantPass())
|
||||
.RegisterPass(CreateFlattenDecorationPass())
|
||||
.RegisterPass(CreateAggressiveDCEPass())
|
||||
.RegisterPass(CreateDeadBranchElimPass());
|
||||
@@ -266,7 +268,9 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
|
||||
//
|
||||
// Both Pass::name() and Pass::desc() should be static class members so they
|
||||
// can be invoked without creating a pass instance.
|
||||
if (pass_name == "strip-debug") {
|
||||
if (pass_name == "strip-atomic-counter-memory") {
|
||||
RegisterPass(CreateStripAtomicCounterMemoryPass());
|
||||
} else if (pass_name == "strip-debug") {
|
||||
RegisterPass(CreateStripDebugInfoPass());
|
||||
} else if (pass_name == "strip-reflect") {
|
||||
RegisterPass(CreateStripReflectInfoPass());
|
||||
@@ -529,6 +533,11 @@ Optimizer::PassToken CreateNullPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateStripAtomicCounterMemoryPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::StripAtomicCounterMemoryPass>());
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateStripDebugInfoPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::StripDebugInfoPass>());
|
||||
|
||||
1
3rdparty/spirv-tools/source/opt/passes.h
vendored
1
3rdparty/spirv-tools/source/opt/passes.h
vendored
@@ -63,6 +63,7 @@
|
||||
#include "source/opt/simplification_pass.h"
|
||||
#include "source/opt/ssa_rewrite_pass.h"
|
||||
#include "source/opt/strength_reduction_pass.h"
|
||||
#include "source/opt/strip_atomic_counter_memory_pass.h"
|
||||
#include "source/opt/strip_debug_info_pass.h"
|
||||
#include "source/opt/strip_reflect_info_pass.h"
|
||||
#include "source/opt/unify_const_pass.h"
|
||||
|
||||
57
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp
vendored
Normal file
57
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2019 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.
|
||||
|
||||
#include "source/opt/strip_atomic_counter_memory_pass.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status StripAtomicCounterMemoryPass::Process() {
|
||||
bool changed = false;
|
||||
context()->module()->ForEachInst([this, &changed](Instruction* inst) {
|
||||
auto indices = spvOpcodeMemorySemanticsOperandIndices(inst->opcode());
|
||||
if (indices.empty()) return;
|
||||
|
||||
for (auto idx : indices) {
|
||||
auto mem_sem_id = inst->GetSingleWordOperand(idx);
|
||||
const auto& mem_sem_inst =
|
||||
context()->get_def_use_mgr()->GetDef(mem_sem_id);
|
||||
// The spec explicitly says that this id must be an OpConstant
|
||||
auto mem_sem_val = mem_sem_inst->GetSingleWordOperand(2);
|
||||
if (!(mem_sem_val & SpvMemorySemanticsAtomicCounterMemoryMask)) {
|
||||
continue;
|
||||
}
|
||||
mem_sem_val &= ~SpvMemorySemanticsAtomicCounterMemoryMask;
|
||||
|
||||
analysis::Integer int_type(32, false);
|
||||
const analysis::Type* uint32_type =
|
||||
context()->get_type_mgr()->GetRegisteredType(&int_type);
|
||||
auto* new_const = context()->get_constant_mgr()->GetConstant(
|
||||
uint32_type, {mem_sem_val});
|
||||
auto* new_const_inst =
|
||||
context()->get_constant_mgr()->GetDefiningInstruction(new_const);
|
||||
auto new_const_id = new_const_inst->result_id();
|
||||
|
||||
inst->SetOperand(idx, {new_const_id});
|
||||
context()->UpdateDefUse(inst);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
51
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h
vendored
Normal file
51
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2019 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.
|
||||
|
||||
#ifndef SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
|
||||
#define SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/opt/module.h"
|
||||
#include "source/opt/pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// Removes the AtomicCounterMemory bit from the value being passed into memory
|
||||
// semantics. This bit being set is ignored in Vulkan environments and
|
||||
// forbidden WebGPU ones.
|
||||
class StripAtomicCounterMemoryPass : public Pass {
|
||||
public:
|
||||
const char* name() const override { return "strip-atomic-counter-memory"; }
|
||||
Status Process() override;
|
||||
|
||||
IRContext::Analysis GetPreservedAnalyses() override {
|
||||
return IRContext::kAnalysisInstrToBlockMapping |
|
||||
IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
|
||||
IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
|
||||
IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
|
||||
IRContext::kAnalysisScalarEvolution |
|
||||
IRContext::kAnalysisRegisterPressure |
|
||||
IRContext::kAnalysisValueNumberTable |
|
||||
IRContext::kAnalysisStructuredCFG |
|
||||
IRContext::kAnalysisBuiltinVarId |
|
||||
IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
|
||||
@@ -24,6 +24,17 @@ namespace spvtools {
|
||||
namespace val {
|
||||
namespace {
|
||||
|
||||
// Returns true if |a| and |b| are instruction defining pointers that point to
|
||||
// the same type.
|
||||
bool ArePointersToSameType(val::Instruction* a, val::Instruction* b) {
|
||||
if (a->opcode() != SpvOpTypePointer || b->opcode() != SpvOpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t a_type = a->GetOperandAs<uint32_t>(2);
|
||||
return a_type && (a_type == b->GetOperandAs<uint32_t>(2));
|
||||
}
|
||||
|
||||
spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
|
||||
const auto function_type_id = inst->GetOperandAs<uint32_t>(3);
|
||||
const auto function_type = _.FindDef(function_type_id);
|
||||
@@ -245,7 +256,10 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
|
||||
const auto parameter_type_id =
|
||||
function_type->GetOperandAs<uint32_t>(param_index);
|
||||
const auto parameter_type = _.FindDef(parameter_type_id);
|
||||
if (!parameter_type || argument_type->id() != parameter_type->id()) {
|
||||
if (!parameter_type ||
|
||||
(argument_type->id() != parameter_type->id() &&
|
||||
!(_.options()->relax_logical_pointer &&
|
||||
ArePointersToSameType(argument_type, parameter_type)))) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "OpFunctionCall Argument <id> '" << _.getIdName(argument_id)
|
||||
<< "'s type does not match Function <id> '"
|
||||
@@ -287,7 +301,8 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
|
||||
sc == SpvStorageClassStorageBuffer;
|
||||
const bool wg_vptr =
|
||||
_.features().variable_pointers && sc == SpvStorageClassWorkgroup;
|
||||
if (!ssbo_vptr && !wg_vptr) {
|
||||
const bool uc_ptr = sc == SpvStorageClassUniformConstant;
|
||||
if (!ssbo_vptr && !wg_vptr && !uc_ptr) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Pointer operand " << _.getIdName(argument_id)
|
||||
<< " must be a memory object declaration";
|
||||
|
||||
@@ -55,6 +55,18 @@ std::string ToString(const CapabilitySet& capabilities,
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool IsValidWebGPUStorageClass(SpvStorageClass storage_class) {
|
||||
return storage_class == SpvStorageClassUniformConstant ||
|
||||
storage_class == SpvStorageClassUniform ||
|
||||
storage_class == SpvStorageClassStorageBuffer ||
|
||||
storage_class == SpvStorageClassInput ||
|
||||
storage_class == SpvStorageClassOutput ||
|
||||
storage_class == SpvStorageClassImage ||
|
||||
storage_class == SpvStorageClassWorkgroup ||
|
||||
storage_class == SpvStorageClassPrivate ||
|
||||
storage_class == SpvStorageClassFunction;
|
||||
}
|
||||
|
||||
// Returns capabilities that enable an opcode. An empty result is interpreted
|
||||
// as no prohibition of use of the opcode. If the result is non-empty, then
|
||||
// the opcode may only be used if at least one of the capabilities is specified
|
||||
@@ -483,6 +495,15 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
|
||||
if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (spvIsWebGPUEnv(_.context()->target_env) &&
|
||||
!IsValidWebGPUStorageClass(storage_class)) {
|
||||
return _.diag(SPV_ERROR_INVALID_BINARY, inst)
|
||||
<< "For WebGPU, OpVariable storage class must be one of "
|
||||
"UniformConstant, Uniform, StorageBuffer, Input, Output, "
|
||||
"Image, Workgroup, Private, Function for WebGPU";
|
||||
}
|
||||
|
||||
if (storage_class == SpvStorageClassGeneric)
|
||||
return _.diag(SPV_ERROR_INVALID_BINARY, inst)
|
||||
<< "OpVariable storage class cannot be Generic";
|
||||
@@ -506,6 +527,15 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
|
||||
"outside of a function";
|
||||
}
|
||||
}
|
||||
} else if (opcode == SpvOpTypePointer) {
|
||||
const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
|
||||
if (spvIsWebGPUEnv(_.context()->target_env) &&
|
||||
!IsValidWebGPUStorageClass(storage_class)) {
|
||||
return _.diag(SPV_ERROR_INVALID_BINARY, inst)
|
||||
<< "For WebGPU, OpTypePointer storage class must be one of "
|
||||
"UniformConstant, Uniform, StorageBuffer, Input, Output, "
|
||||
"Image, Workgroup, Private, Function";
|
||||
}
|
||||
}
|
||||
|
||||
// SPIR-V Spec 2.16.3: Validation Rules for Kernel Capabilities: The
|
||||
|
||||
@@ -344,6 +344,7 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
|
||||
case SpvExecutionModeOriginLowerLeft:
|
||||
case SpvExecutionModeEarlyFragmentTests:
|
||||
case SpvExecutionModeDepthReplacing:
|
||||
case SpvExecutionModeDepthGreater:
|
||||
case SpvExecutionModeDepthLess:
|
||||
case SpvExecutionModeDepthUnchanged:
|
||||
if (!std::all_of(models->begin(), models->end(),
|
||||
@@ -411,6 +412,21 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
|
||||
}
|
||||
}
|
||||
|
||||
if (spvIsWebGPUEnv(_.context()->target_env)) {
|
||||
if (mode != SpvExecutionModeOriginUpperLeft &&
|
||||
mode != SpvExecutionModeDepthReplacing &&
|
||||
mode != SpvExecutionModeDepthGreater &&
|
||||
mode != SpvExecutionModeDepthLess &&
|
||||
mode != SpvExecutionModeDepthUnchanged &&
|
||||
mode != SpvExecutionModeLocalSize &&
|
||||
mode != SpvExecutionModeLocalSizeHint) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Execution mode must be one of OriginUpperLeft, "
|
||||
"DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
|
||||
"LocalSize, or LocalSizeHint for WebGPU environment.";
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
1
3rdparty/spirv-tools/test/opt/CMakeLists.txt
vendored
1
3rdparty/spirv-tools/test/opt/CMakeLists.txt
vendored
@@ -77,6 +77,7 @@ add_spvtools_unittest(TARGET opt
|
||||
set_spec_const_default_value_test.cpp
|
||||
simplification_test.cpp
|
||||
strength_reduction_test.cpp
|
||||
strip_atomic_counter_memory_test.cpp
|
||||
strip_debug_info_test.cpp
|
||||
strip_reflect_info_test.cpp
|
||||
struct_cfg_analysis_test.cpp
|
||||
|
||||
29
3rdparty/spirv-tools/test/opt/ccp_test.cpp
vendored
29
3rdparty/spirv-tools/test/opt/ccp_test.cpp
vendored
@@ -896,6 +896,35 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<CCPPass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(CCPTest, FoldWithDecoration) {
|
||||
const std::string text = R"(
|
||||
; CHECK: OpCapability
|
||||
; CHECK-NOT: OpDecorate
|
||||
; CHECK: OpFunctionEnd
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %2 "main"
|
||||
OpExecutionMode %2 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpDecorate %3 RelaxedPrecision
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v3float = OpTypeVector %float 3
|
||||
%float_0 = OpConstant %float 0
|
||||
%v4float = OpTypeVector %float 4
|
||||
%10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%2 = OpFunction %void None %5
|
||||
%11 = OpLabel
|
||||
%3 = OpVectorShuffle %v3float %10 %10 0 1 2
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndMatch<CCPPass>(text, true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
100
3rdparty/spirv-tools/test/opt/fold_test.cpp
vendored
100
3rdparty/spirv-tools/test/opt/fold_test.cpp
vendored
@@ -6211,6 +6211,106 @@ INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoRes
|
||||
9, true)
|
||||
));
|
||||
|
||||
using EntryPointFoldingTest =
|
||||
::testing::TestWithParam<InstructionFoldingCase<bool>>;
|
||||
|
||||
TEST_P(EntryPointFoldingTest, Case) {
|
||||
const auto& tc = GetParam();
|
||||
|
||||
// Build module.
|
||||
std::unique_ptr<IRContext> context =
|
||||
BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
|
||||
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
ASSERT_NE(nullptr, context);
|
||||
|
||||
// Fold the instruction to test.
|
||||
Instruction* inst = nullptr;
|
||||
inst = &*context->module()->entry_points().begin();
|
||||
assert(inst && "Invalid test. Could not find entry point instruction to fold.");
|
||||
std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
|
||||
bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
|
||||
EXPECT_EQ(succeeded, tc.expected_result);
|
||||
if (succeeded) {
|
||||
Match(tc.test_body, context.get());
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
|
||||
::testing::Values(
|
||||
// Test case 0: Basic test 1
|
||||
InstructionFoldingCase<bool>(std::string() +
|
||||
"; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
|
||||
"OpCapability Shader\n" +
|
||||
"%1 = OpExtInstImport \"GLSL.std.450\"\n" +
|
||||
"OpMemoryModel Logical GLSL450\n" +
|
||||
"OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
|
||||
"OpExecutionMode %2 OriginUpperLeft\n" +
|
||||
"OpSource GLSL 430\n" +
|
||||
"OpDecorate %3 Location 0\n" +
|
||||
"%void = OpTypeVoid\n" +
|
||||
"%5 = OpTypeFunction %void\n" +
|
||||
"%float = OpTypeFloat 32\n" +
|
||||
"%v4float = OpTypeVector %float 4\n" +
|
||||
"%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
|
||||
"%3 = OpVariable %_ptr_Output_v4float Output\n" +
|
||||
"%int = OpTypeInt 32 1\n" +
|
||||
"%int_0 = OpConstant %int 0\n" +
|
||||
"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
|
||||
"%2 = OpFunction %void None %5\n" +
|
||||
"%12 = OpLabel\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true),
|
||||
InstructionFoldingCase<bool>(std::string() +
|
||||
"; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
|
||||
"OpCapability Shader\n" +
|
||||
"%1 = OpExtInstImport \"GLSL.std.450\"\n" +
|
||||
"OpMemoryModel Logical GLSL450\n" +
|
||||
"OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
|
||||
"OpExecutionMode %2 OriginUpperLeft\n" +
|
||||
"OpSource GLSL 430\n" +
|
||||
"OpDecorate %3 Location 0\n" +
|
||||
"%void = OpTypeVoid\n" +
|
||||
"%5 = OpTypeFunction %void\n" +
|
||||
"%float = OpTypeFloat 32\n" +
|
||||
"%v4float = OpTypeVector %float 4\n" +
|
||||
"%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
|
||||
"%3 = OpVariable %_ptr_Output_v4float Output\n" +
|
||||
"%4 = OpVariable %_ptr_Output_v4float Output\n" +
|
||||
"%int = OpTypeInt 32 1\n" +
|
||||
"%int_0 = OpConstant %int 0\n" +
|
||||
"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
|
||||
"%2 = OpFunction %void None %5\n" +
|
||||
"%12 = OpLabel\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true),
|
||||
InstructionFoldingCase<bool>(std::string() +
|
||||
"; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
|
||||
"OpCapability Shader\n" +
|
||||
"%1 = OpExtInstImport \"GLSL.std.450\"\n" +
|
||||
"OpMemoryModel Logical GLSL450\n" +
|
||||
"OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
|
||||
"OpExecutionMode %2 OriginUpperLeft\n" +
|
||||
"OpSource GLSL 430\n" +
|
||||
"OpDecorate %3 Location 0\n" +
|
||||
"%void = OpTypeVoid\n" +
|
||||
"%5 = OpTypeFunction %void\n" +
|
||||
"%float = OpTypeFloat 32\n" +
|
||||
"%v4float = OpTypeVector %float 4\n" +
|
||||
"%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
|
||||
"%3 = OpVariable %_ptr_Output_v4float Output\n" +
|
||||
"%4 = OpVariable %_ptr_Output_v4float Output\n" +
|
||||
"%int = OpTypeInt 32 1\n" +
|
||||
"%int_0 = OpConstant %int 0\n" +
|
||||
"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
|
||||
"%2 = OpFunction %void None %5\n" +
|
||||
"%12 = OpLabel\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true)
|
||||
));
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
102
3rdparty/spirv-tools/test/opt/optimizer_test.cpp
vendored
102
3rdparty/spirv-tools/test/opt/optimizer_test.cpp
vendored
@@ -231,9 +231,12 @@ TEST(Optimizer, WebGPUModeSetsCorrectPasses) {
|
||||
for (auto name = pass_names.begin(); name != pass_names.end(); ++name)
|
||||
registered_passes.push_back(*name);
|
||||
|
||||
std::vector<std::string> expected_passes = {
|
||||
"eliminate-dead-branches", "eliminate-dead-code-aggressive",
|
||||
"flatten-decorations", "strip-debug"};
|
||||
std::vector<std::string> expected_passes = {"eliminate-dead-branches",
|
||||
"eliminate-dead-code-aggressive",
|
||||
"eliminate-dead-const",
|
||||
"flatten-decorations",
|
||||
"strip-debug",
|
||||
"strip-atomic-counter-memory"};
|
||||
std::sort(registered_passes.begin(), registered_passes.end());
|
||||
std::sort(expected_passes.begin(), expected_passes.end());
|
||||
|
||||
@@ -265,7 +268,6 @@ TEST_P(WebGPUPassTest, Ran) {
|
||||
class ValidatorOptions validator_options;
|
||||
ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
|
||||
validator_options, true));
|
||||
|
||||
std::string disassembly;
|
||||
tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
|
||||
|
||||
@@ -274,7 +276,7 @@ TEST_P(WebGPUPassTest, Ran) {
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
WebGPU, WebGPUPassTest,
|
||||
Optimizer, WebGPUPassTest,
|
||||
::testing::ValuesIn(std::vector<WebGPUPassCase>{
|
||||
// FlattenDecorations
|
||||
{// input
|
||||
@@ -346,7 +348,95 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
"OpReturn\n"
|
||||
"OpFunctionEnd\n",
|
||||
// pass
|
||||
"strip-debug"}}));
|
||||
"strip-debug"},
|
||||
// Eliminate Dead Constants
|
||||
{// input
|
||||
"OpCapability Shader\n"
|
||||
"OpCapability VulkanMemoryModelKHR\n"
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
|
||||
"OpMemoryModel Logical VulkanKHR\n"
|
||||
"OpEntryPoint Vertex %func \"shader\"\n"
|
||||
"%u32 = OpTypeInt 32 0\n"
|
||||
"%u32_ptr = OpTypePointer Workgroup %u32\n"
|
||||
"%u32_var = OpVariable %u32_ptr Workgroup\n"
|
||||
"%u32_1 = OpConstant %u32 1\n"
|
||||
"%cross_device = OpConstant %u32 0\n"
|
||||
"%relaxed = OpConstant %u32 0\n"
|
||||
"%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
|
||||
"%void = OpTypeVoid\n"
|
||||
"%void_f = OpTypeFunction %void\n"
|
||||
"%func = OpFunction %void None %void_f\n"
|
||||
"%label = OpLabel\n"
|
||||
"OpReturn\n"
|
||||
"OpFunctionEnd\n",
|
||||
// expected
|
||||
"OpCapability Shader\n"
|
||||
"OpCapability VulkanMemoryModelKHR\n"
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
|
||||
"OpMemoryModel Logical VulkanKHR\n"
|
||||
"OpEntryPoint Vertex %1 \"shader\"\n"
|
||||
"%uint = OpTypeInt 32 0\n"
|
||||
"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
|
||||
"%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
|
||||
"%void = OpTypeVoid\n"
|
||||
"%10 = OpTypeFunction %void\n"
|
||||
"%1 = OpFunction %void None %10\n"
|
||||
"%11 = OpLabel\n"
|
||||
"OpReturn\n"
|
||||
"OpFunctionEnd\n",
|
||||
"eliminate-dead-const"},
|
||||
// Strip Atomic Counter Memory
|
||||
{// input
|
||||
"OpCapability Shader\n"
|
||||
"OpCapability VulkanMemoryModelKHR\n"
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
|
||||
"OpMemoryModel Logical VulkanKHR\n"
|
||||
"OpEntryPoint Vertex %func \"shader\"\n"
|
||||
"%u32 = OpTypeInt 32 0\n"
|
||||
"%u32_ptr = OpTypePointer Workgroup %u32\n"
|
||||
"%u32_var = OpVariable %u32_ptr Workgroup\n"
|
||||
"%u32_0 = OpConstant %u32 0\n"
|
||||
"%u32_1 = OpConstant %u32 1\n"
|
||||
"%cross_device = OpConstant %u32 0\n"
|
||||
"%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
|
||||
"%void = OpTypeVoid\n"
|
||||
"%void_f = OpTypeFunction %void\n"
|
||||
"%func = OpFunction %void None %void_f\n"
|
||||
"%label = OpLabel\n"
|
||||
"%val0 = OpAtomicStore %u32_var %cross_device "
|
||||
"%acquire_release_atomic_counter_workgroup %u32_1\n"
|
||||
"%val1 = OpAtomicIIncrement %u32 %u32_var %cross_device "
|
||||
"%acquire_release_atomic_counter_workgroup\n"
|
||||
"%val2 = OpAtomicCompareExchange %u32 %u32_var %cross_device "
|
||||
"%acquire_release_atomic_counter_workgroup "
|
||||
"%acquire_release_atomic_counter_workgroup %u32_0 %u32_0\n"
|
||||
"OpReturn\n"
|
||||
"OpFunctionEnd\n",
|
||||
// expected
|
||||
"OpCapability Shader\n"
|
||||
"OpCapability VulkanMemoryModelKHR\n"
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
|
||||
"OpMemoryModel Logical VulkanKHR\n"
|
||||
"OpEntryPoint Vertex %1 \"shader\"\n"
|
||||
"%uint = OpTypeInt 32 0\n"
|
||||
"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
|
||||
"%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
|
||||
"%uint_0 = OpConstant %uint 0\n"
|
||||
"%uint_1 = OpConstant %uint 1\n"
|
||||
"%uint_0_0 = OpConstant %uint 0\n"
|
||||
"%void = OpTypeVoid\n"
|
||||
"%10 = OpTypeFunction %void\n"
|
||||
"%uint_264 = OpConstant %uint 264\n"
|
||||
"%1 = OpFunction %void None %10\n"
|
||||
"%11 = OpLabel\n"
|
||||
"OpAtomicStore %4 %uint_0_0 %uint_264 %uint_1\n"
|
||||
"%12 = OpAtomicIIncrement %uint %4 %uint_0_0 %uint_264\n"
|
||||
"%13 = OpAtomicCompareExchange %uint %4 %uint_0_0 %uint_264 %uint_264 "
|
||||
"%uint_0 %uint_0\n"
|
||||
"OpReturn\n"
|
||||
"OpFunctionEnd\n",
|
||||
// pass
|
||||
"strip-atomic-counter-memory"}}));
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
|
||||
406
3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp
vendored
Normal file
406
3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
// Copyright (c) 2019 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.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "test/opt/pass_fixture.h"
|
||||
#include "test/opt/pass_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
typedef std::tuple<std::string, std::string> StripAtomicCounterMemoryParam;
|
||||
|
||||
using MemorySemanticsModified =
|
||||
PassTest<::testing::TestWithParam<StripAtomicCounterMemoryParam>>;
|
||||
using NonMemorySemanticsUnmodifiedTest = PassTest<::testing::Test>;
|
||||
|
||||
void operator+=(std::vector<const char*>& lhs, const char* rhs) {
|
||||
lhs.push_back(rhs);
|
||||
}
|
||||
|
||||
std::string GetConstDecl(std::string val) {
|
||||
std::string decl;
|
||||
decl += "%uint_" + val + " = OpConstant %uint " + val;
|
||||
return decl;
|
||||
}
|
||||
|
||||
std::string GetUnchangedString(std::string(generate_inst)(std::string),
|
||||
std::string val) {
|
||||
std::string decl = GetConstDecl(val);
|
||||
std::string inst = generate_inst(val);
|
||||
|
||||
std::vector<const char*> result = {
|
||||
// clang-format off
|
||||
"OpCapability Shader",
|
||||
"OpCapability VulkanMemoryModelKHR",
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"",
|
||||
"OpMemoryModel Logical VulkanKHR",
|
||||
"OpEntryPoint Vertex %1 \"shader\"",
|
||||
"%uint = OpTypeInt 32 0",
|
||||
"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
|
||||
"%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
|
||||
"%uint_0 = OpConstant %uint 0",
|
||||
"%uint_1 = OpConstant %uint 1",
|
||||
"%void = OpTypeVoid",
|
||||
"%8 = OpTypeFunction %void",
|
||||
decl.c_str(),
|
||||
"%1 = OpFunction %void None %8",
|
||||
"%10 = OpLabel",
|
||||
inst.c_str(),
|
||||
"OpReturn",
|
||||
"OpFunctionEnd"
|
||||
// clang-format on
|
||||
};
|
||||
return JoinAllInsts(result);
|
||||
}
|
||||
|
||||
std::string GetChangedString(std::string(generate_inst)(std::string),
|
||||
std::string orig, std::string changed) {
|
||||
std::string orig_decl = GetConstDecl(orig);
|
||||
std::string changed_decl = GetConstDecl(changed);
|
||||
std::string inst = generate_inst(changed);
|
||||
|
||||
std::vector<const char*> result = {
|
||||
// clang-format off
|
||||
"OpCapability Shader",
|
||||
"OpCapability VulkanMemoryModelKHR",
|
||||
"OpExtension \"SPV_KHR_vulkan_memory_model\"",
|
||||
"OpMemoryModel Logical VulkanKHR",
|
||||
"OpEntryPoint Vertex %1 \"shader\"",
|
||||
"%uint = OpTypeInt 32 0",
|
||||
"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
|
||||
"%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
|
||||
"%uint_0 = OpConstant %uint 0",
|
||||
"%uint_1 = OpConstant %uint 1",
|
||||
"%void = OpTypeVoid",
|
||||
"%8 = OpTypeFunction %void",
|
||||
orig_decl.c_str() };
|
||||
// clang-format on
|
||||
if (changed != "0") result += changed_decl.c_str();
|
||||
result += "%1 = OpFunction %void None %8";
|
||||
result += "%10 = OpLabel";
|
||||
result += inst.c_str();
|
||||
result += "OpReturn";
|
||||
result += "OpFunctionEnd";
|
||||
return JoinAllInsts(result);
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string> GetInputAndExpected(
|
||||
std::string(generate_inst)(std::string),
|
||||
StripAtomicCounterMemoryParam param) {
|
||||
std::string orig = std::get<0>(param);
|
||||
std::string changed = std::get<1>(param);
|
||||
std::string input = GetUnchangedString(generate_inst, orig);
|
||||
std::string expected = orig == changed
|
||||
? GetUnchangedString(generate_inst, changed)
|
||||
: GetChangedString(generate_inst, orig, changed);
|
||||
return std::make_tuple(input, expected);
|
||||
}
|
||||
|
||||
std::string GetOpControlBarrierInst(std::string val) {
|
||||
return "OpControlBarrier %uint_1 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpControlBarrier) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpControlBarrierInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpMemoryBarrierInst(std::string val) {
|
||||
return "OpMemoryBarrier %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpMemoryBarrier) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpMemoryBarrierInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicLoadInst(std::string val) {
|
||||
return "%11 = OpAtomicLoad %uint %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicLoad) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicLoadInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicStoreInst(std::string val) {
|
||||
return "OpAtomicStore %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicStore) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicStoreInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicExchangeInst(std::string val) {
|
||||
return "%11 = OpAtomicExchange %uint %4 %uint_1 %uint_" + val + " %uint_0";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicExchange) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicExchangeInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicCompareExchangeInst(std::string val) {
|
||||
return "%11 = OpAtomicCompareExchange %uint %4 %uint_1 %uint_" + val +
|
||||
" %uint_" + val + " %uint_0 %uint_0";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicCompareExchange) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicCompareExchangeInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicCompareExchangeWeakInst(std::string val) {
|
||||
return "%11 = OpAtomicCompareExchangeWeak %uint %4 %uint_1 %uint_" + val +
|
||||
" %uint_" + val + " %uint_0 %uint_0";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicCompareExchangeWeak) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicCompareExchangeWeakInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicIIncrementInst(std::string val) {
|
||||
return "%11 = OpAtomicIIncrement %uint %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicIIncrement) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicIIncrementInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicIDecrementInst(std::string val) {
|
||||
return "%11 = OpAtomicIDecrement %uint %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicIDecrement) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicIDecrementInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicIAddInst(std::string val) {
|
||||
return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicIAdd) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicIAddInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicISubInst(std::string val) {
|
||||
return "%11 = OpAtomicISub %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicISub) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicISubInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicSMinInst(std::string val) {
|
||||
return "%11 = OpAtomicSMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicSMin) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicSMinInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicUMinInst(std::string val) {
|
||||
return "%11 = OpAtomicUMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicUMin) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicUMinInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicSMaxInst(std::string val) {
|
||||
return "%11 = OpAtomicSMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicSMax) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicSMaxInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicUMaxInst(std::string val) {
|
||||
return "%11 = OpAtomicUMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicUMax) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicUMaxInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicAndInst(std::string val) {
|
||||
return "%11 = OpAtomicAnd %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicAnd) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicAndInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicOrInst(std::string val) {
|
||||
return "%11 = OpAtomicOr %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicOr) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicOrInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicXorInst(std::string val) {
|
||||
return "%11 = OpAtomicXor %uint %4 %uint_1 %uint_" + val + " %uint_1";
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicXor) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicXorInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicFlagTestAndSetInst(std::string val) {
|
||||
return "%11 = OpAtomicFlagTestAndSet %uint %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicFlagTestAndSet) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicFlagTestAndSetInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpAtomicFlagClearInst(std::string val) {
|
||||
return "OpAtomicFlagClear %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpAtomicFlagClear) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpAtomicFlagClearInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetOpMemoryNamedBarrierInst(std::string val) {
|
||||
return "OpMemoryNamedBarrier %4 %uint_1 %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_P(MemorySemanticsModified, OpMemoryNamedBarrier) {
|
||||
std::string input, expected;
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetOpMemoryNamedBarrierInst, GetParam());
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
StripAtomicCounterMemoryTest, MemorySemanticsModified,
|
||||
::testing::ValuesIn(std::vector<StripAtomicCounterMemoryParam>({
|
||||
std::make_tuple("1024", "0"),
|
||||
std::make_tuple("5", "5"),
|
||||
std::make_tuple("1288", "264"),
|
||||
std::make_tuple("264", "264")
|
||||
})));
|
||||
// clang-format on
|
||||
|
||||
std::string GetNoMemorySemanticsPresentInst(std::string val) {
|
||||
return "%11 = OpVariable %_ptr_Workgroup_uint Workgroup %uint_" + val;
|
||||
}
|
||||
|
||||
TEST_F(NonMemorySemanticsUnmodifiedTest, NoMemorySemanticsPresent) {
|
||||
std::string input, expected;
|
||||
StripAtomicCounterMemoryParam param = std::make_tuple("1288", "1288");
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetNoMemorySemanticsPresentInst, param);
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
std::string GetMemorySemanticsPresentInst(std::string val) {
|
||||
return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1288";
|
||||
}
|
||||
|
||||
TEST_F(NonMemorySemanticsUnmodifiedTest, MemorySemanticsPresent) {
|
||||
std::string input, expected;
|
||||
StripAtomicCounterMemoryParam param = std::make_tuple("1288", "264");
|
||||
std::tie(input, expected) =
|
||||
GetInputAndExpected(GetMemorySemanticsPresentInst, param);
|
||||
SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
|
||||
/* skip_nop = */ false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
@@ -3023,6 +3023,8 @@ TEST_F(ValidateDecorations,
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
OpDecorate %struct Block
|
||||
OpMemberDecorate %struct 0 Offset 0
|
||||
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
|
||||
@@ -321,13 +321,15 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
|
||||
std::string spirv = GenerateShaderAccessChain(storage_class, "", "");
|
||||
|
||||
const std::vector<std::string> valid_storage_classes = {
|
||||
"UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
|
||||
"Function", "Private", "Workgroup", "AtomicCounter"};
|
||||
bool valid_sc =
|
||||
std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
|
||||
storage_class) != valid_storage_classes.end();
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
spv_result_t expected_result =
|
||||
storage_class == "UniformConstant" ? SPV_SUCCESS : SPV_ERROR_INVALID_ID;
|
||||
EXPECT_EQ(expected_result, ValidateInstructions());
|
||||
if (valid_sc) {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
@@ -338,7 +340,7 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("StorageBuffer pointer operand 2[%gep] requires a "
|
||||
"variable pointers capability"));
|
||||
} else {
|
||||
} else if (storage_class != "UniformConstant") {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Invalid storage class for pointer operand 2[%gep]"));
|
||||
@@ -355,12 +357,12 @@ TEST_P(ValidateFunctionCall,
|
||||
"OpExtension \"SPV_KHR_variable_pointers\"");
|
||||
|
||||
const std::vector<std::string> valid_storage_classes = {
|
||||
"UniformConstant", "Function", "Private",
|
||||
"Workgroup", "StorageBuffer", "AtomicCounter"};
|
||||
"Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
|
||||
bool valid_sc =
|
||||
std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
|
||||
storage_class) != valid_storage_classes.end();
|
||||
bool validate = storage_class == "StorageBuffer";
|
||||
bool validate =
|
||||
storage_class == "StorageBuffer" || storage_class == "UniformConstant";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
if (validate) {
|
||||
@@ -388,13 +390,13 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationVariablePointers) {
|
||||
"OpExtension \"SPV_KHR_variable_pointers\"");
|
||||
|
||||
const std::vector<std::string> valid_storage_classes = {
|
||||
"UniformConstant", "Function", "Private",
|
||||
"Workgroup", "StorageBuffer", "AtomicCounter"};
|
||||
"Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
|
||||
bool valid_sc =
|
||||
std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
|
||||
storage_class) != valid_storage_classes.end();
|
||||
bool validate =
|
||||
storage_class == "StorageBuffer" || storage_class == "Workgroup";
|
||||
bool validate = storage_class == "StorageBuffer" ||
|
||||
storage_class == "Workgroup" ||
|
||||
storage_class == "UniformConstant";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
if (validate) {
|
||||
|
||||
55
3rdparty/spirv-tools/test/val/val_modes_test.cpp
vendored
55
3rdparty/spirv-tools/test/val/val_modes_test.cpp
vendored
@@ -531,16 +531,24 @@ TEST_P(ValidateModeExecution, ExecutionMode) {
|
||||
|
||||
std::ostringstream sstr;
|
||||
sstr << "OpCapability Shader\n";
|
||||
sstr << "OpCapability Geometry\n";
|
||||
sstr << "OpCapability Tessellation\n";
|
||||
sstr << "OpCapability TransformFeedback\n";
|
||||
if (!spvIsVulkanEnv(env)) {
|
||||
if (!spvIsWebGPUEnv(env)) {
|
||||
sstr << "OpCapability Geometry\n";
|
||||
sstr << "OpCapability Tessellation\n";
|
||||
sstr << "OpCapability TransformFeedback\n";
|
||||
}
|
||||
if (!spvIsVulkanOrWebGPUEnv(env)) {
|
||||
sstr << "OpCapability Kernel\n";
|
||||
if (env == SPV_ENV_UNIVERSAL_1_3) {
|
||||
sstr << "OpCapability SubgroupDispatch\n";
|
||||
}
|
||||
}
|
||||
sstr << "OpMemoryModel Logical GLSL450\n";
|
||||
if (spvIsWebGPUEnv(env)) {
|
||||
sstr << "OpCapability VulkanMemoryModelKHR\n";
|
||||
sstr << "OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
|
||||
sstr << "OpMemoryModel Logical VulkanKHR\n";
|
||||
} else {
|
||||
sstr << "OpMemoryModel Logical GLSL450\n";
|
||||
}
|
||||
sstr << "OpEntryPoint " << model << " %main \"main\"\n";
|
||||
if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
|
||||
mode.find("SubgroupsPerWorkgroupId") == 0) {
|
||||
@@ -657,8 +665,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
Values("Geometry", "TessellationControl", "TessellationEvaluation",
|
||||
"GLCompute", "Vertex", "Kernel"),
|
||||
Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
|
||||
"EarlyFragmentTests", "DepthReplacing", "DepthLess",
|
||||
"DepthUnchanged"),
|
||||
"EarlyFragmentTests", "DepthReplacing", "DepthGreater",
|
||||
"DepthLess", "DepthUnchanged"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_0)));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
|
||||
@@ -706,6 +714,39 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
"SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
|
||||
Values(SPV_ENV_UNIVERSAL_1_3)));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ValidateModeGLComputeWebGPUWhitelistGood,
|
||||
ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""),
|
||||
Values("GLCompute"), Values("LocalSize 1 1 1"),
|
||||
Values(SPV_ENV_WEBGPU_0)));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ValidateModeGLComputeWebGPUWhitelistBad, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode must be one of OriginUpperLeft, "
|
||||
"DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
|
||||
"LocalSize, or LocalSizeHint for WebGPU environment"),
|
||||
Values("GLCompute"), Values("LocalSizeId %int1 %int1 %int1"),
|
||||
Values(SPV_ENV_WEBGPU_0)));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ValidateModeFragmentWebGPUWhitelistGood, ValidateModeExecution,
|
||||
Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
|
||||
Values("OriginUpperLeft", "DepthReplacing", "DepthGreater",
|
||||
"DepthLess", "DepthUnchanged"),
|
||||
Values(SPV_ENV_WEBGPU_0)));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ValidateModeFragmentWebGPUWhitelistBad, ValidateModeExecution,
|
||||
Combine(Values(SPV_ERROR_INVALID_DATA),
|
||||
Values("Execution mode must be one of OriginUpperLeft, "
|
||||
"DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
|
||||
"LocalSize, or LocalSizeHint for WebGPU environment"),
|
||||
Values("Fragment"),
|
||||
Values("PixelCenterInteger", "OriginLowerLeft",
|
||||
"EarlyFragmentTests"),
|
||||
Values(SPV_ENV_WEBGPU_0)));
|
||||
|
||||
TEST_F(ValidateModeExecution, MeshNVLocalSize) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
|
||||
128
3rdparty/spirv-tools/test/val/val_storage_test.cpp
vendored
128
3rdparty/spirv-tools/test/val/val_storage_test.cpp
vendored
@@ -26,7 +26,10 @@ namespace val {
|
||||
namespace {
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Values;
|
||||
using ValidateStorage = spvtest::ValidateBase<std::string>;
|
||||
using ValidateStorageClass =
|
||||
spvtest::ValidateBase<std::tuple<std::string, bool, bool, std::string>>;
|
||||
|
||||
TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
|
||||
char str[] = R"(
|
||||
@@ -186,6 +189,131 @@ TEST_F(ValidateStorage, GenericVariableInsideFunction) {
|
||||
HasSubstr("OpVariable storage class cannot be Generic"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParam) {
|
||||
const auto str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
%intt = OpTypeInt 32 1
|
||||
%voidt = OpTypeVoid
|
||||
%ptrt = OpTypePointer Function %intt
|
||||
%vfunct = OpTypeFunction %voidt
|
||||
%vifunct = OpTypeFunction %voidt %ptrt
|
||||
%wgroupptrt = OpTypePointer Workgroup %intt
|
||||
%wgroup = OpVariable %wgroupptrt Workgroup
|
||||
%main = OpFunction %voidt None %vfunct
|
||||
%mainl = OpLabel
|
||||
%ret = OpFunctionCall %voidt %func %wgroup
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%func = OpFunction %voidt None %vifunct
|
||||
%arg = OpFunctionParameter %ptrt
|
||||
%funcl = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(str);
|
||||
getValidatorOptions()->relax_logical_pointer = true;
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) {
|
||||
const auto str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
%floatt = OpTypeFloat 32
|
||||
%intt = OpTypeInt 32 1
|
||||
%voidt = OpTypeVoid
|
||||
%ptrt = OpTypePointer Function %intt
|
||||
%vfunct = OpTypeFunction %voidt
|
||||
%vifunct = OpTypeFunction %voidt %ptrt
|
||||
%wgroupptrt = OpTypePointer Workgroup %floatt
|
||||
%wgroup = OpVariable %wgroupptrt Workgroup
|
||||
%main = OpFunction %voidt None %vfunct
|
||||
%mainl = OpLabel
|
||||
%ret = OpFunctionCall %voidt %func %wgroup
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%func = OpFunction %voidt None %vifunct
|
||||
%arg = OpFunctionParameter %ptrt
|
||||
%funcl = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(str);
|
||||
getValidatorOptions()->relax_logical_pointer = true;
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpFunctionCall Argument <id> '"));
|
||||
}
|
||||
|
||||
std::string GetVarDeclStr(const std::string& storage_class) {
|
||||
if (storage_class != "Output" && storage_class != "Private" &&
|
||||
storage_class != "Function") {
|
||||
return "%var = OpVariable %ptrt " + storage_class + "\n";
|
||||
} else {
|
||||
return "%var = OpVariable %ptrt " + storage_class + " %null\n";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(ValidateStorageClass, WebGPU) {
|
||||
std::string storage_class = std::get<0>(GetParam());
|
||||
bool is_local = std::get<1>(GetParam());
|
||||
bool is_valid = std::get<2>(GetParam());
|
||||
std::string error = std::get<3>(GetParam());
|
||||
|
||||
std::string str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
OpMemoryModel Logical VulkanKHR
|
||||
OpEntryPoint Fragment %func "func"
|
||||
OpExecutionMode %func OriginUpperLeft
|
||||
%intt = OpTypeInt 32 1
|
||||
%voidt = OpTypeVoid
|
||||
%vfunct = OpTypeFunction %voidt
|
||||
%null = OpConstantNull %intt
|
||||
)";
|
||||
str += "%ptrt = OpTypePointer " + storage_class + " %intt\n";
|
||||
if (!is_local) str += GetVarDeclStr(storage_class);
|
||||
str += R"(
|
||||
%func = OpFunction %voidt None %vfunct
|
||||
%funcl = OpLabel
|
||||
)";
|
||||
if (is_local) str += GetVarDeclStr(storage_class);
|
||||
str += R"(
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
|
||||
if (is_valid) {
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
|
||||
} else {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
StorageClass, ValidateStorageClass,
|
||||
Values(std::make_tuple("UniformConstant", false, true, ""),
|
||||
std::make_tuple("Uniform", false, true, ""),
|
||||
std::make_tuple("StorageBuffer", false, true, ""),
|
||||
std::make_tuple("Input", false, true, ""),
|
||||
std::make_tuple("Output", false, true, ""),
|
||||
std::make_tuple("Image", false, true, ""),
|
||||
std::make_tuple("Workgroup", false, true, ""),
|
||||
std::make_tuple("Private", false, true, ""),
|
||||
std::make_tuple("Function", true, true, ""),
|
||||
std::make_tuple(
|
||||
"CrossWorkgroup", false, false,
|
||||
"For WebGPU, OpTypePointer storage class must be one of"),
|
||||
std::make_tuple(
|
||||
"PushConstant", false, false,
|
||||
"For WebGPU, OpTypePointer storage class must be one of")));
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
||||
2
3rdparty/spirv-tools/tools/opt/opt.cpp
vendored
2
3rdparty/spirv-tools/tools/opt/opt.cpp
vendored
@@ -340,6 +340,8 @@ Options (in lexicographical order):
|
||||
This options should be used rarely, and with caution.
|
||||
--strength-reduction
|
||||
Replaces instructions with equivalent and less expensive ones.
|
||||
--strip-atomic-counter-memory
|
||||
Removes AtomicCountMemory bit from memory semantics values.
|
||||
--strip-debug
|
||||
Remove all debug instructions.
|
||||
--strip-reflect
|
||||
|
||||
Reference in New Issue
Block a user