spirv-fuzz: Handle Vulkan SPIR-V versions (#4156)
Fixes #4155.
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index 8f6c6c9..8a23392 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -775,14 +775,15 @@
bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces(
const opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this requirement
- // holds. The check should be refined on demand for other target
- // environments.
+ // TODO(afd): We capture the environments for which this requirement holds.
+ // The check should be refined on demand for other target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
diff --git a/source/fuzz/transformation_flatten_conditional_branch.cpp b/source/fuzz/transformation_flatten_conditional_branch.cpp
index fdee513..c2c1a94 100644
--- a/source/fuzz/transformation_flatten_conditional_branch.cpp
+++ b/source/fuzz/transformation_flatten_conditional_branch.cpp
@@ -844,7 +844,9 @@
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
- case SPV_ENV_UNIVERSAL_1_3: {
+ case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1: {
return true;
}
default:
diff --git a/source/fuzz/transformation_set_loop_control.cpp b/source/fuzz/transformation_set_loop_control.cpp
index b2180d8..7e53911 100644
--- a/source/fuzz/transformation_set_loop_control.cpp
+++ b/source/fuzz/transformation_set_loop_control.cpp
@@ -199,14 +199,16 @@
bool TransformationSetLoopControl::PeelCountIsSupported(
opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this loop
- // control is definitely not supported. The check should be refined on
- // demand for other target environments.
+ // TODO(afd): We capture the environments for which this loop control is
+ // definitely not supported. The check should be refined on demand for other
+ // target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
diff --git a/source/fuzz/transformation_set_memory_operands_mask.cpp b/source/fuzz/transformation_set_memory_operands_mask.cpp
index deb207a..370a70e 100644
--- a/source/fuzz/transformation_set_memory_operands_mask.cpp
+++ b/source/fuzz/transformation_set_memory_operands_mask.cpp
@@ -53,7 +53,9 @@
SpvOpCopyMemory ||
message_.memory_access_instruction().target_instruction_opcode() ==
SpvOpCopyMemorySized);
- assert(MultipleMemoryOperandMasksAreSupported(ir_context));
+ assert(MultipleMemoryOperandMasksAreSupported(ir_context) &&
+ "Multiple memory operand masks are not supported for this SPIR-V "
+ "version.");
}
auto instruction =
@@ -205,14 +207,16 @@
bool TransformationSetMemoryOperandsMask::
MultipleMemoryOperandMasksAreSupported(opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this loop
- // control is definitely not supported. The check should be refined on
- // demand for other target environments.
+ // TODO(afd): We capture the environments for which this loop control is
+ // definitely not supported. The check should be refined on demand for other
+ // target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
diff --git a/test/fuzz/transformation_add_global_variable_test.cpp b/test/fuzz/transformation_add_global_variable_test.cpp
index eb958a7..747cc32 100644
--- a/test/fuzz/transformation_add_global_variable_test.cpp
+++ b/test/fuzz/transformation_add_global_variable_test.cpp
@@ -225,12 +225,10 @@
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
- %20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
- %15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
@@ -246,48 +244,96 @@
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- TransformationAddGlobalVariable transformations[] = {
- // %100 = OpVariable %12 Private
- TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
- true),
+ for (auto env : {SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_2}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ TransformationAddGlobalVariable transformations[] = {
+ // %100 = OpVariable %12 Private
+ TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+ true),
- // %101 = OpVariable %12 Private %16
- TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
- false),
+ // %101 = OpVariable %12 Private %16
+ TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+ false),
- // %102 = OpVariable %19 Private %21
- TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
- true)};
+ // %102 = OpVariable %19 Private %21
+ TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+ true)};
- for (auto& transformation : transformations) {
+ for (auto& transformation : transformations) {
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
- ASSERT_TRUE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
- ASSERT_TRUE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+ ASSERT_FALSE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
- std::string after_transformation = R"(
+ std::string after_transformation_enlarged_interface = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "m1" %100 %101 %102
+ OpEntryPoint Vertex %5 "m2" %100 %101 %102
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeInt 32 1
+ %8 = OpTypeVector %6 2
+ %9 = OpTypePointer Function %6
+ %10 = OpTypePointer Private %6
+ %11 = OpTypePointer Function %7
+ %12 = OpTypePointer Private %7
+ %13 = OpTypePointer Private %8
+ %14 = OpVariable %10 Private
+ %16 = OpConstant %7 1
+ %17 = OpTypePointer Private %10
+ %18 = OpTypeBool
+ %19 = OpTypePointer Private %18
+ %21 = OpConstantTrue %18
+ %100 = OpVariable %12 Private %16
+ %101 = OpVariable %12 Private %16
+ %102 = OpVariable %19 Private %21
+ %4 = OpFunction %2 None %3
+ %30 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %5 = OpFunction %2 None %3
+ %31 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(
+ IsEqual(env, after_transformation_enlarged_interface, context.get()));
+ }
+}
+
+TEST(TransformationAddGlobalVariableTest,
+ TestEntryPointInterfaceNoEnlargement) {
+ // This checks that when global variables are added to a SPIR-V 1.3- module,
+ // they are not added to entry points of that module.
+ std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "m1" %100 %101 %102
- OpEntryPoint Vertex %5 "m2" %100 %101 %102
+ OpEntryPoint Fragment %4 "m1"
+ OpEntryPoint Vertex %5 "m2"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
@@ -297,20 +343,15 @@
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
- %20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
- %15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
%19 = OpTypePointer Private %18
%21 = OpConstantTrue %18
- %100 = OpVariable %12 Private %16
- %101 = OpVariable %12 Private %16
- %102 = OpVariable %19 Private %21
%4 = OpFunction %2 None %3
%30 = OpLabel
OpReturn
@@ -320,7 +361,86 @@
OpReturn
OpFunctionEnd
)";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+
+ for (auto env :
+ {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}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ TransformationAddGlobalVariable transformations[] = {
+ // %100 = OpVariable %12 Private
+ TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+ true),
+
+ // %101 = OpVariable %12 Private %16
+ TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+ false),
+
+ // %102 = OpVariable %19 Private %21
+ TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+ true)};
+
+ for (auto& transformation : transformations) {
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+ ASSERT_FALSE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+
+ std::string after_transformation_fixed_interface = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "m1"
+ OpEntryPoint Vertex %5 "m2"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeInt 32 1
+ %8 = OpTypeVector %6 2
+ %9 = OpTypePointer Function %6
+ %10 = OpTypePointer Private %6
+ %11 = OpTypePointer Function %7
+ %12 = OpTypePointer Private %7
+ %13 = OpTypePointer Private %8
+ %14 = OpVariable %10 Private
+ %16 = OpConstant %7 1
+ %17 = OpTypePointer Private %10
+ %18 = OpTypeBool
+ %19 = OpTypePointer Private %18
+ %21 = OpConstantTrue %18
+ %100 = OpVariable %12 Private %16
+ %101 = OpVariable %12 Private %16
+ %102 = OpVariable %19 Private %21
+ %4 = OpFunction %2 None %3
+ %30 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %5 = OpFunction %2 None %3
+ %31 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(
+ IsEqual(env, after_transformation_fixed_interface, context.get()));
+ }
}
TEST(TransformationAddGlobalVariableTest, TestAddingWorkgroupGlobals) {
diff --git a/test/fuzz/transformation_flatten_conditional_branch_test.cpp b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
index 1a0ff6a..800af0e 100644
--- a/test/fuzz/transformation_flatten_conditional_branch_test.cpp
+++ b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
@@ -1334,20 +1334,24 @@
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
+ for (auto env :
+ {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}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
- auto transformation =
- TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
- ASSERT_FALSE(
- transformation.IsApplicable(context.get(), transformation_context));
+ auto transformation =
+ TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
+ ASSERT_FALSE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ }
}
TEST(TransformationFlattenConditionalBranchTest,
diff --git a/test/fuzz/transformation_set_loop_control_test.cpp b/test/fuzz/transformation_set_loop_control_test.cpp
index 3312a67..060d9a8 100644
--- a/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/test/fuzz/transformation_set_loop_control_test.cpp
@@ -947,7 +947,9 @@
for (auto env :
{SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
- SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5}) {
+ SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4,
+ SPV_ENV_VULKAN_1_2}) {
const auto consumer = nullptr;
const auto context =
BuildModule(env, consumer, shader, kFuzzAssembleOption);
@@ -964,6 +966,8 @@
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
// PeelCount and PartialCount were introduced in SPIRV 1.4, so are not
// valid in the context of older versions.
ASSERT_FALSE(
@@ -971,6 +975,8 @@
break;
case SPV_ENV_UNIVERSAL_1_4:
case SPV_ENV_UNIVERSAL_1_5:
+ case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
+ case SPV_ENV_VULKAN_1_2:
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
break;
diff --git a/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
index 4763d7a..29e57f4 100644
--- a/test/fuzz/transformation_set_memory_operands_mask_test.cpp
+++ b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
@@ -90,187 +90,205 @@
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- // Not OK: the instruction is not a memory access.
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
- SpvMemoryAccessMaskNone, 0)
- .IsApplicable(context.get(), transformation_context));
+ for (auto env :
+ {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}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
- // Not OK to remove Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask,
- 0)
- .IsApplicable(context.get(), transformation_context));
+#ifndef NDEBUG
+ {
+ // Not OK: multiple operands are not supported pre SPIR-V 1.4.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ ASSERT_DEATH(
+ transformation.IsApplicable(context.get(), transformation_context),
+ "Multiple memory operand masks are not supported");
+ }
+#endif
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
+ // Not OK: the instruction is not a memory access.
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
+ SpvMemoryAccessMaskNone, 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ // Not OK to remove Aligned
+ ASSERT_FALSE(
+ TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ // Not OK to remove Aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessMaskNone, 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ // OK: leaves the mask as is
+ ASSERT_TRUE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ {
+ // OK: adds Nontemporal and Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
+ SpvMemoryAccessVolatileMask,
+ 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ // Not OK to remove Volatile
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ // Not OK to add Aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask,
+ 0)
+ .IsApplicable(context.get(), transformation_context));
+
+ {
+ // OK: adds Nontemporal
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ {
+ // OK: adds Nontemporal (creates new operand)
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ {
+ // OK: adds Nontemporal and Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ {
+ // OK: removes Nontemporal, adds Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(148, SpvOpStore, 0),
+ SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "Point3D"
+ OpMemberName %7 0 "x"
+ OpMemberName %7 1 "y"
+ OpMemberName %7 2 "z"
+ OpName %12 "global_points"
+ OpName %15 "block"
+ OpMemberName %15 0 "in_points"
+ OpMemberName %15 1 "in_point"
+ OpName %17 ""
+ OpName %133 "local_points"
+ OpMemberDecorate %7 0 Offset 0
+ OpMemberDecorate %7 1 Offset 4
+ OpMemberDecorate %7 2 Offset 8
+ OpDecorate %10 ArrayStride 16
+ OpMemberDecorate %15 0 Offset 0
+ OpMemberDecorate %15 1 Offset 192
+ OpDecorate %15 Block
+ OpDecorate %17 DescriptorSet 0
+ OpDecorate %17 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6 %6 %6
+ %8 = OpTypeInt 32 0
+ %9 = OpConstant %8 12
+ %10 = OpTypeArray %7 %9
+ %11 = OpTypePointer Private %10
+ %12 = OpVariable %11 Private
+ %15 = OpTypeStruct %10 %7
+ %16 = OpTypePointer Uniform %15
+ %17 = OpVariable %16 Uniform
+ %18 = OpTypeInt 32 1
+ %19 = OpConstant %18 0
+ %20 = OpTypePointer Uniform %10
+ %24 = OpTypePointer Private %7
+ %27 = OpTypePointer Private %6
+ %30 = OpConstant %18 1
+ %132 = OpTypePointer Function %10
+ %135 = OpTypePointer Uniform %7
+ %145 = OpTypePointer Function %7
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %133 = OpVariable %132 Function
+ %21 = OpAccessChain %20 %17 %19
+ OpCopyMemory %12 %21 Aligned|Nontemporal|Volatile 16
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ %136 = OpAccessChain %135 %17 %30
+ %138 = OpAccessChain %24 %12 %19
+ OpCopyMemory %138 %136 Nontemporal|Volatile
+ %146 = OpAccessChain %145 %133 %30
+ %147 = OpLoad %7 %146 Aligned|Volatile 16
+ %148 = OpAccessChain %24 %12 %19
+ OpStore %148 %147 Volatile
+ OpReturn
+ OpFunctionEnd
+ )";
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
-
- // Not OK to remove Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessMaskNone, 0)
- .IsApplicable(context.get(), transformation_context));
-
- // OK: leaves the mask as is
- ASSERT_TRUE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask, 0)
- .IsApplicable(context.get(), transformation_context));
-
- {
- // OK: adds Nontemporal and Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
- SpvMemoryAccessVolatileMask,
- 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
-
- // Not OK to remove Volatile
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
-
- // Not OK to add Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0)
- .IsApplicable(context.get(), transformation_context));
-
- {
- // OK: adds Nontemporal
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
-
- {
- // OK: adds Nontemporal (creates new operand)
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
-
- {
- // OK: adds Nontemporal and Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
-
- {
- // OK: removes Nontemporal, adds Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(148, SpvOpStore, 0),
- SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
-
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "Point3D"
- OpMemberName %7 0 "x"
- OpMemberName %7 1 "y"
- OpMemberName %7 2 "z"
- OpName %12 "global_points"
- OpName %15 "block"
- OpMemberName %15 0 "in_points"
- OpMemberName %15 1 "in_point"
- OpName %17 ""
- OpName %133 "local_points"
- OpMemberDecorate %7 0 Offset 0
- OpMemberDecorate %7 1 Offset 4
- OpMemberDecorate %7 2 Offset 8
- OpDecorate %10 ArrayStride 16
- OpMemberDecorate %15 0 Offset 0
- OpMemberDecorate %15 1 Offset 192
- OpDecorate %15 Block
- OpDecorate %17 DescriptorSet 0
- OpDecorate %17 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6 %6 %6
- %8 = OpTypeInt 32 0
- %9 = OpConstant %8 12
- %10 = OpTypeArray %7 %9
- %11 = OpTypePointer Private %10
- %12 = OpVariable %11 Private
- %15 = OpTypeStruct %10 %7
- %16 = OpTypePointer Uniform %15
- %17 = OpVariable %16 Uniform
- %18 = OpTypeInt 32 1
- %19 = OpConstant %18 0
- %20 = OpTypePointer Uniform %10
- %24 = OpTypePointer Private %7
- %27 = OpTypePointer Private %6
- %30 = OpConstant %18 1
- %132 = OpTypePointer Function %10
- %135 = OpTypePointer Uniform %7
- %145 = OpTypePointer Function %7
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %133 = OpVariable %132 Function
- %21 = OpAccessChain %20 %17 %19
- OpCopyMemory %12 %21 Aligned|Nontemporal|Volatile 16
- OpCopyMemory %133 %12 Nontemporal|Volatile
- OpCopyMemory %133 %12 Nontemporal|Volatile
- %136 = OpAccessChain %135 %17 %30
- %138 = OpAccessChain %24 %12 %19
- OpCopyMemory %138 %136 Nontemporal|Volatile
- %146 = OpAccessChain %145 %133 %30
- %147 = OpLoad %7 %146 Aligned|Volatile 16
- %148 = OpAccessChain %24 %12 %19
- OpStore %148 %147 Volatile
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
-TEST(TransformationSetMemoryOperandsMaskTest, Spirv14) {
+TEST(TransformationSetMemoryOperandsMaskTest, Spirv14OrHigher) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
@@ -339,180 +357,183 @@
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
- // Bad: cannot remove aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessVolatileMask, 1)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ for (auto env : {SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_2}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
+ // Bad: cannot remove aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessVolatileMask, 1)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
- // Bad: cannot remove volatile
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ // Bad: cannot remove volatile
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // Creates the first operand.
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // Creates the first operand.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // Creates both operands.
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // Creates both operands.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
- // Bad: the first mask is None, so Aligned cannot be added to it.
- ASSERT_FALSE(
- TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
+ // Bad: the first mask is None, so Aligned cannot be added to it.
+ ASSERT_FALSE(
+ TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
- SpvMemoryAccessVolatileMask, 1);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
+ SpvMemoryAccessVolatileMask, 1);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(148, SpvOpStore, 0), SpvMemoryAccessMaskNone,
- 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(148, SpvOpStore, 0),
+ SpvMemoryAccessMaskNone, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %12 %17
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "Point3D"
- OpMemberName %7 0 "x"
- OpMemberName %7 1 "y"
- OpMemberName %7 2 "z"
- OpName %12 "global_points"
- OpName %15 "block"
- OpMemberName %15 0 "in_points"
- OpMemberName %15 1 "in_point"
- OpName %17 ""
- OpName %133 "local_points"
- OpMemberDecorate %7 0 Offset 0
- OpMemberDecorate %7 1 Offset 4
- OpMemberDecorate %7 2 Offset 8
- OpDecorate %10 ArrayStride 16
- OpMemberDecorate %15 0 Offset 0
- OpMemberDecorate %15 1 Offset 192
- OpDecorate %15 Block
- OpDecorate %17 DescriptorSet 0
- OpDecorate %17 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6 %6 %6
- %8 = OpTypeInt 32 0
- %9 = OpConstant %8 12
- %10 = OpTypeArray %7 %9
- %11 = OpTypePointer Private %10
- %12 = OpVariable %11 Private
- %15 = OpTypeStruct %10 %7
- %16 = OpTypePointer Uniform %15
- %17 = OpVariable %16 Uniform
- %18 = OpTypeInt 32 1
- %19 = OpConstant %18 0
- %20 = OpTypePointer Uniform %10
- %24 = OpTypePointer Private %7
- %27 = OpTypePointer Private %6
- %30 = OpConstant %18 1
- %132 = OpTypePointer Function %10
- %135 = OpTypePointer Uniform %7
- %145 = OpTypePointer Function %7
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %133 = OpVariable %132 Function
- %21 = OpAccessChain %20 %17 %19
- OpCopyMemory %12 %21 Aligned 16 Aligned|Volatile 16
- OpCopyMemory %133 %12 Volatile Nontemporal|Volatile
- OpCopyMemory %133 %12 Nontemporal|Volatile
- OpCopyMemory %133 %12 None Nontemporal|Volatile
- %136 = OpAccessChain %135 %17 %30
- %138 = OpAccessChain %24 %12 %19
- OpCopyMemory %138 %136 None Aligned|Nontemporal 16
- OpCopyMemory %138 %136 Aligned 16 Volatile
- %146 = OpAccessChain %145 %133 %30
- %147 = OpLoad %7 %146 Volatile|Aligned 16
- %148 = OpAccessChain %24 %12 %19
- OpStore %148 %147 None
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main" %12 %17
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "Point3D"
+ OpMemberName %7 0 "x"
+ OpMemberName %7 1 "y"
+ OpMemberName %7 2 "z"
+ OpName %12 "global_points"
+ OpName %15 "block"
+ OpMemberName %15 0 "in_points"
+ OpMemberName %15 1 "in_point"
+ OpName %17 ""
+ OpName %133 "local_points"
+ OpMemberDecorate %7 0 Offset 0
+ OpMemberDecorate %7 1 Offset 4
+ OpMemberDecorate %7 2 Offset 8
+ OpDecorate %10 ArrayStride 16
+ OpMemberDecorate %15 0 Offset 0
+ OpMemberDecorate %15 1 Offset 192
+ OpDecorate %15 Block
+ OpDecorate %17 DescriptorSet 0
+ OpDecorate %17 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6 %6 %6
+ %8 = OpTypeInt 32 0
+ %9 = OpConstant %8 12
+ %10 = OpTypeArray %7 %9
+ %11 = OpTypePointer Private %10
+ %12 = OpVariable %11 Private
+ %15 = OpTypeStruct %10 %7
+ %16 = OpTypePointer Uniform %15
+ %17 = OpVariable %16 Uniform
+ %18 = OpTypeInt 32 1
+ %19 = OpConstant %18 0
+ %20 = OpTypePointer Uniform %10
+ %24 = OpTypePointer Private %7
+ %27 = OpTypePointer Private %6
+ %30 = OpConstant %18 1
+ %132 = OpTypePointer Function %10
+ %135 = OpTypePointer Uniform %7
+ %145 = OpTypePointer Function %7
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %133 = OpVariable %132 Function
+ %21 = OpAccessChain %20 %17 %19
+ OpCopyMemory %12 %21 Aligned 16 Aligned|Volatile 16
+ OpCopyMemory %133 %12 Volatile Nontemporal|Volatile
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ OpCopyMemory %133 %12 None Nontemporal|Volatile
+ %136 = OpAccessChain %135 %17 %30
+ %138 = OpAccessChain %24 %12 %19
+ OpCopyMemory %138 %136 None Aligned|Nontemporal 16
+ OpCopyMemory %138 %136 Aligned 16 Volatile
+ %146 = OpAccessChain %145 %133 %30
+ %147 = OpLoad %7 %146 Volatile|Aligned 16
+ %148 = OpAccessChain %24 %12 %19
+ OpStore %148 %147 None
+ OpReturn
+ OpFunctionEnd
+ )";
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ }
}
} // namespace