Родитель
43cfa9bc1d
Коммит
f7043c0de6
|
@ -775,14 +775,15 @@ bool IsNullConstantSupported(const opt::analysis::Type& type) {
|
|||
|
||||
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;
|
||||
|
|
|
@ -844,7 +844,9 @@ bool TransformationFlattenConditionalBranch::OpSelectArgumentsAreRestricted(
|
|||
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:
|
||||
|
|
|
@ -199,14 +199,16 @@ bool TransformationSetLoopControl::PartialCountIsSupported(
|
|||
|
||||
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;
|
||||
|
|
|
@ -53,7 +53,9 @@ bool TransformationSetMemoryOperandsMask::IsApplicable(
|
|||
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 @@ uint32_t TransformationSetMemoryOperandsMask::GetInOperandIndexForMask(
|
|||
|
||||
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;
|
||||
|
|
|
@ -225,12 +225,10 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
|
|||
%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 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
|
|||
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 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
|
|||
%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 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
|
|||
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) {
|
||||
|
|
|
@ -1334,20 +1334,24 @@ TEST(TransformationFlattenConditionalBranchTest,
|
|||
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,
|
||||
|
|
|
@ -947,7 +947,9 @@ TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
|
|||
|
||||
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 @@ TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
|
|||
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 @@ TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
|
|||
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;
|
||||
|
|
|
@ -90,187 +90,205 @@ TEST(TransformationSetMemoryOperandsMaskTest, PreSpirv14) {
|
|||
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 @@ TEST(TransformationSetMemoryOperandsMaskTest, Spirv14) {
|
|||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче