mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2025-02-21 07:12:25 +00:00
Add FlattenDecoration transform
Add --flatten-decorations to spirv-opt Flattens decoration groups. That is, replace OpDecorationGroup and its uses in OpGroupDecorate and OpGroupMemberDecorate with ordinary OpDecorate and OpMemberDecorate instructions. Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/602
This commit is contained in:
parent
5c3c054c1f
commit
11a867f412
1
CHANGES
1
CHANGES
@ -2,6 +2,7 @@ Revision history for SPIRV-Tools
|
||||
|
||||
v2016.7-dev 2017-01-06
|
||||
- Optimizer: Add inlining of all function calls in entry points
|
||||
- Optimizer: Add flattening of decoration groups. Fixes #602
|
||||
- Add build target spirv-tools-vimsyntax to generate spvasm.vim, a SPIR-V
|
||||
assembly syntax file for Vim.
|
||||
- Version string: Allow overriding of wall clock timestamp with contents
|
||||
|
@ -109,6 +109,15 @@ Optimizer::PassToken CreateStripDebugInfoPass();
|
||||
Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
|
||||
const std::unordered_map<uint32_t, std::string>& id_value_map);
|
||||
|
||||
// Creates a flatten-decoration pass.
|
||||
// A flatten-decoration pass replaces grouped decorations with equivalent
|
||||
// ungrouped decorations. That is, it replaces each OpDecorationGroup
|
||||
// instruction and associated OpGroupDecorate and OpGroupMemberDecorate
|
||||
// instructions with equivalent OpDecorate and OpMemberDecorate instructions.
|
||||
// The pass does not attempt to preserve debug information for instructions
|
||||
// it removes.
|
||||
Optimizer::PassToken CreateFlattenDecorationPass();
|
||||
|
||||
// Creates a freeze-spec-constant-value pass.
|
||||
// A freeze-spec-constant pass specializes the value of spec constants to
|
||||
// their default values. This pass only processes the spec constants that have
|
||||
|
@ -17,6 +17,7 @@ add_library(SPIRV-Tools-opt
|
||||
constants.h
|
||||
def_use_manager.h
|
||||
eliminate_dead_constant_pass.h
|
||||
flatten_decoration_pass.h
|
||||
function.h
|
||||
fold_spec_constant_op_and_composite_pass.h
|
||||
freeze_spec_constant_value_pass.h
|
||||
@ -40,6 +41,7 @@ add_library(SPIRV-Tools-opt
|
||||
build_module.cpp
|
||||
def_use_manager.cpp
|
||||
eliminate_dead_constant_pass.cpp
|
||||
flatten_decoration_pass.cpp
|
||||
function.cpp
|
||||
fold_spec_constant_op_and_composite_pass.cpp
|
||||
freeze_spec_constant_value_pass.cpp
|
||||
|
164
source/opt/flatten_decoration_pass.cpp
Normal file
164
source/opt/flatten_decoration_pass.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2017 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 "flatten_decoration_pass.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
using ir::Instruction;
|
||||
using ir::Operand;
|
||||
|
||||
using Words = std::vector<uint32_t>;
|
||||
using OrderedUsesMap = std::unordered_map<uint32_t, Words>;
|
||||
|
||||
Pass::Status FlattenDecorationPass::Process(ir::Module* module) {
|
||||
bool modified = false;
|
||||
|
||||
// The target Id of OpDecorationGroup instructions.
|
||||
// We have to track this separately from its uses, in case it
|
||||
// has no uses.
|
||||
std::unordered_set<uint32_t> group_ids;
|
||||
// Maps a decoration group Id to its GroupDecorate targets, in order
|
||||
// of appearance.
|
||||
OrderedUsesMap normal_uses;
|
||||
// Maps a decoration group Id to its GroupMemberDecorate targets and
|
||||
// their indices, in of appearance.
|
||||
OrderedUsesMap member_uses;
|
||||
|
||||
auto annotations = module->annotations();
|
||||
|
||||
// On the first pass, record each OpDecorationGroup with its ordered uses.
|
||||
// Rely on unordered_map::operator[] to create its entries on first access.
|
||||
for (const auto& inst : annotations) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOp::SpvOpDecorationGroup:
|
||||
group_ids.insert(inst.result_id());
|
||||
break;
|
||||
case SpvOp::SpvOpGroupDecorate: {
|
||||
Words& words = normal_uses[inst.GetSingleWordInOperand(0)];
|
||||
for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
|
||||
words.push_back(inst.GetSingleWordInOperand(i));
|
||||
}
|
||||
} break;
|
||||
case SpvOp::SpvOpGroupMemberDecorate: {
|
||||
Words& words = member_uses[inst.GetSingleWordInOperand(0)];
|
||||
for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
|
||||
words.push_back(inst.GetSingleWordInOperand(i));
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// On the second pass, replace OpDecorationGroup and its uses with
|
||||
// equivalent normal and struct member uses.
|
||||
auto inst_iter = annotations.begin();
|
||||
// We have to re-evaluate the end pointer
|
||||
while (inst_iter != module->annotations().end()) {
|
||||
// Should we replace this instruction?
|
||||
bool replace = false;
|
||||
switch (inst_iter->opcode()) {
|
||||
case SpvOp::SpvOpDecorationGroup:
|
||||
case SpvOp::SpvOpGroupDecorate:
|
||||
case SpvOp::SpvOpGroupMemberDecorate:
|
||||
replace = true;
|
||||
break;
|
||||
case SpvOp::SpvOpDecorate: {
|
||||
// If this decoration targets a group, then replace it
|
||||
// by sets of normal and member decorations.
|
||||
const uint32_t group = inst_iter->GetSingleWordOperand(0);
|
||||
const auto normal_uses_iter = normal_uses.find(group);
|
||||
if (normal_uses_iter != normal_uses.end()) {
|
||||
for (auto target : normal_uses[group]) {
|
||||
std::unique_ptr<Instruction> new_inst(new Instruction(*inst_iter));
|
||||
new_inst->SetInOperand(0, Words{target});
|
||||
inst_iter = inst_iter.InsertBefore(std::move(new_inst));
|
||||
++inst_iter;
|
||||
replace = true;
|
||||
}
|
||||
}
|
||||
const auto member_uses_iter = member_uses.find(group);
|
||||
if (member_uses_iter != member_uses.end()) {
|
||||
const Words& member_id_pairs = (*member_uses_iter).second;
|
||||
// The collection is a sequence of pairs.
|
||||
assert((member_id_pairs.size() % 2) == 0);
|
||||
for (size_t i = 0; i < member_id_pairs.size(); i += 2) {
|
||||
// Make an OpMemberDecorate instruction for each (target, member)
|
||||
// pair.
|
||||
const uint32_t target = member_id_pairs[i];
|
||||
const uint32_t member = member_id_pairs[i + 1];
|
||||
std::vector<Operand> operands;
|
||||
operands.push_back(Operand(SPV_OPERAND_TYPE_ID, {target}));
|
||||
operands.push_back(
|
||||
Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {member}));
|
||||
auto decoration_operands_iter = inst_iter->begin();
|
||||
decoration_operands_iter++; // Skip the group target.
|
||||
operands.insert(operands.end(), decoration_operands_iter,
|
||||
inst_iter->end());
|
||||
std::unique_ptr<Instruction> new_inst(
|
||||
new Instruction(SpvOp::SpvOpMemberDecorate, 0, 0, operands));
|
||||
inst_iter = inst_iter.InsertBefore(std::move(new_inst));
|
||||
++inst_iter;
|
||||
replace = true;
|
||||
}
|
||||
}
|
||||
// If this is an OpDecorate targeting the OpDecorationGroup itself,
|
||||
// remove it even if that decoration group itself is not the target of
|
||||
// any OpGroupDecorate or OpGroupMemberDecorate.
|
||||
if (!replace && group_ids.count(group)) {
|
||||
replace = true;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (replace) {
|
||||
inst_iter = inst_iter.Erase();
|
||||
modified = true;
|
||||
} else {
|
||||
// Handle the case of decorations unrelated to decoration groups.
|
||||
++inst_iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove OpName instructions which reference the removed group decorations.
|
||||
// An OpDecorationGroup instruction might not have been used by an
|
||||
// OpGroupDecorate or OpGroupMemberDecorate instruction.
|
||||
if (!group_ids.empty()) {
|
||||
for (auto debug_inst_iter = module->debug_begin();
|
||||
debug_inst_iter != module->debug_end();) {
|
||||
if (debug_inst_iter->opcode() == SpvOp::SpvOpName) {
|
||||
const uint32_t target = debug_inst_iter->GetSingleWordOperand(0);
|
||||
if (group_ids.count(target)) {
|
||||
debug_inst_iter = debug_inst_iter.Erase();
|
||||
modified = true;
|
||||
} else {
|
||||
++debug_inst_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
34
source/opt/flatten_decoration_pass.h
Normal file
34
source/opt/flatten_decoration_pass.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2017 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 LIBSPIRV_OPT_FLATTEN_DECORATION_PASS_H_
|
||||
#define LIBSPIRV_OPT_FLATTEN_DECORATION_PASS_H_
|
||||
|
||||
#include "module.h"
|
||||
#include "pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class FlattenDecorationPass : public Pass {
|
||||
public:
|
||||
const char* name() const override { return "flatten-decoration"; }
|
||||
Status Process(ir::Module*) override;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_FLATTEN_DECORATION_PASS_H_
|
@ -101,6 +101,11 @@ Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
|
||||
MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateFlattenDecorationPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::FlattenDecorationPass>());
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::FreezeSpecConstantValuePass>());
|
||||
|
@ -18,6 +18,7 @@
|
||||
// A single header to include all passes.
|
||||
|
||||
#include "eliminate_dead_constant_pass.h"
|
||||
#include "flatten_decoration_pass.h"
|
||||
#include "fold_spec_constant_op_and_composite_pass.h"
|
||||
#include "inline_pass.h"
|
||||
#include "freeze_spec_constant_value_pass.h"
|
||||
|
@ -38,6 +38,11 @@ add_spvtools_unittest(TARGET pass_strip_debug_info
|
||||
LIBS SPIRV-Tools-opt
|
||||
)
|
||||
|
||||
add_spvtools_unittest(TARGET pass_flatten_decoration
|
||||
SRCS flatten_decoration_test.cpp pass_utils.cpp
|
||||
LIBS SPIRV-Tools-opt
|
||||
)
|
||||
|
||||
add_spvtools_unittest(TARGET pass_freeze_spec_const
|
||||
SRCS freeze_spec_const_test.cpp pass_utils.cpp
|
||||
LIBS SPIRV-Tools-opt
|
||||
|
234
test/opt/flatten_decoration_test.cpp
Normal file
234
test/opt/flatten_decoration_test.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG 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 <gmock/gmock.h>
|
||||
|
||||
#include "pass_fixture.h"
|
||||
#include "pass_utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace spvtools;
|
||||
|
||||
// Returns the initial part of the assembly text for a valid
|
||||
// SPIR-V module, including instructions prior to decorations.
|
||||
std::string PreambleAssembly() {
|
||||
return
|
||||
R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %hue %saturation %value
|
||||
OpName %main "main"
|
||||
OpName %void_fn "void_fn"
|
||||
OpName %hue "hue"
|
||||
OpName %saturation "saturation"
|
||||
OpName %value "value"
|
||||
OpName %entry "entry"
|
||||
OpName %Point "Point"
|
||||
OpName %Camera "Camera"
|
||||
)";
|
||||
}
|
||||
|
||||
// Retuns types
|
||||
std::string TypesAndFunctionsAssembly() {
|
||||
return
|
||||
R"(%void = OpTypeVoid
|
||||
%void_fn = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%Point = OpTypeStruct %float %float %float
|
||||
%Camera = OpTypeStruct %float %float
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%hue = OpVariable %_ptr_Input_float Input
|
||||
%saturation = OpVariable %_ptr_Input_float Input
|
||||
%value = OpVariable %_ptr_Input_float Input
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
}
|
||||
|
||||
struct FlattenDecorationCase {
|
||||
// Names and decorations before the pass.
|
||||
std::string input;
|
||||
// Names and decorations after the pass.
|
||||
std::string expected;
|
||||
};
|
||||
|
||||
using FlattenDecorationTest =
|
||||
PassTest<::testing::TestWithParam<FlattenDecorationCase>>;
|
||||
|
||||
TEST_P(FlattenDecorationTest, TransformsDecorations) {
|
||||
const auto before =
|
||||
PreambleAssembly() + GetParam().input + TypesAndFunctionsAssembly();
|
||||
const auto after =
|
||||
PreambleAssembly() + GetParam().expected + TypesAndFunctionsAssembly();
|
||||
|
||||
SinglePassRunAndCheck<opt::FlattenDecorationPass>(before, after, false, true);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(NoUses, FlattenDecorationTest,
|
||||
::testing::ValuesIn(std::vector<FlattenDecorationCase>{
|
||||
// No OpDecorationGroup
|
||||
{"", ""},
|
||||
|
||||
// OpDecorationGroup without any uses, and
|
||||
// no OpName.
|
||||
{"%group = OpDecorationGroup\n", ""},
|
||||
|
||||
// OpDecorationGroup without any uses, and
|
||||
// with OpName targeting it. Proves you must
|
||||
// remove the names as well.
|
||||
{"OpName %group \"group\"\n"
|
||||
"%group = OpDecorationGroup\n",
|
||||
""},
|
||||
|
||||
// OpDecorationGroup with decorations that
|
||||
// target it, but no uses in OpGroupDecorate
|
||||
// or OpGroupMemberDecorate instructions.
|
||||
{"OpDecorate %group Flat\n"
|
||||
"OpDecorate %group NoPerspective\n"
|
||||
"%group = OpDecorationGroup\n",
|
||||
""},
|
||||
}), );
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(OpGroupDecorate, FlattenDecorationTest,
|
||||
::testing::ValuesIn(std::vector<FlattenDecorationCase>{
|
||||
// One OpGroupDecorate
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpDecorate %group NoPerspective\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupDecorate %group %hue %saturation\n",
|
||||
"OpDecorate %hue Flat\n"
|
||||
"OpDecorate %saturation Flat\n"
|
||||
"OpDecorate %hue NoPerspective\n"
|
||||
"OpDecorate %saturation NoPerspective\n"},
|
||||
// Multiple OpGroupDecorate
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpDecorate %group NoPerspective\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupDecorate %group %hue %value\n"
|
||||
"OpGroupDecorate %group %saturation\n",
|
||||
"OpDecorate %hue Flat\n"
|
||||
"OpDecorate %value Flat\n"
|
||||
"OpDecorate %saturation Flat\n"
|
||||
"OpDecorate %hue NoPerspective\n"
|
||||
"OpDecorate %value NoPerspective\n"
|
||||
"OpDecorate %saturation NoPerspective\n"},
|
||||
// Two group decorations, interleaved
|
||||
{"OpName %group0 \"group0\"\n"
|
||||
"OpName %group1 \"group1\"\n"
|
||||
"OpDecorate %group0 Flat\n"
|
||||
"OpDecorate %group1 NoPerspective\n"
|
||||
"%group0 = OpDecorationGroup\n"
|
||||
"%group1 = OpDecorationGroup\n"
|
||||
"OpGroupDecorate %group0 %hue %value\n"
|
||||
"OpGroupDecorate %group1 %saturation\n",
|
||||
"OpDecorate %hue Flat\n"
|
||||
"OpDecorate %value Flat\n"
|
||||
"OpDecorate %saturation NoPerspective\n"},
|
||||
// Decoration with operands
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Location 42\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupDecorate %group %hue %saturation\n",
|
||||
"OpDecorate %hue Location 42\n"
|
||||
"OpDecorate %saturation Location 42\n"},
|
||||
}), );
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(OpGroupMemberDecorate, FlattenDecorationTest,
|
||||
::testing::ValuesIn(std::vector<FlattenDecorationCase>{
|
||||
// One OpGroupMemberDecorate
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpDecorate %group Offset 16\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupMemberDecorate %group %Point 1\n",
|
||||
"OpMemberDecorate %Point 1 Flat\n"
|
||||
"OpMemberDecorate %Point 1 Offset 16\n"},
|
||||
// Multiple OpGroupMemberDecorate using the same
|
||||
// decoration group.
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpDecorate %group NoPerspective\n"
|
||||
"OpDecorate %group Offset 8\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupMemberDecorate %group %Point 2\n"
|
||||
"OpGroupMemberDecorate %group %Camera 1\n",
|
||||
"OpMemberDecorate %Point 2 Flat\n"
|
||||
"OpMemberDecorate %Camera 1 Flat\n"
|
||||
"OpMemberDecorate %Point 2 NoPerspective\n"
|
||||
"OpMemberDecorate %Camera 1 NoPerspective\n"
|
||||
"OpMemberDecorate %Point 2 Offset 8\n"
|
||||
"OpMemberDecorate %Camera 1 Offset 8\n"},
|
||||
// Two groups of member decorations, interleaved.
|
||||
// Decoration is with and without operands.
|
||||
{"OpName %group0 \"group0\"\n"
|
||||
"OpName %group1 \"group1\"\n"
|
||||
"OpDecorate %group0 Flat\n"
|
||||
"OpDecorate %group0 Offset 8\n"
|
||||
"OpDecorate %group1 NoPerspective\n"
|
||||
"OpDecorate %group1 Offset 16\n"
|
||||
"%group0 = OpDecorationGroup\n"
|
||||
"%group1 = OpDecorationGroup\n"
|
||||
"OpGroupMemberDecorate %group0 %Point 0\n"
|
||||
"OpGroupMemberDecorate %group1 %Point 2\n",
|
||||
"OpMemberDecorate %Point 0 Flat\n"
|
||||
"OpMemberDecorate %Point 0 Offset 8\n"
|
||||
"OpMemberDecorate %Point 2 NoPerspective\n"
|
||||
"OpMemberDecorate %Point 2 Offset 16\n"},
|
||||
}), );
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(UnrelatedDecorations, FlattenDecorationTest,
|
||||
::testing::ValuesIn(std::vector<FlattenDecorationCase>{
|
||||
// A non-group non-member decoration is untouched.
|
||||
{"OpDecorate %hue Centroid\n"
|
||||
"OpDecorate %saturation Flat\n",
|
||||
"OpDecorate %hue Centroid\n"
|
||||
"OpDecorate %saturation Flat\n"},
|
||||
// A non-group member decoration is untouched.
|
||||
{"OpMemberDecorate %Point 0 Offset 0\n"
|
||||
"OpMemberDecorate %Point 1 Offset 4\n"
|
||||
"OpMemberDecorate %Point 1 Flat\n",
|
||||
"OpMemberDecorate %Point 0 Offset 0\n"
|
||||
"OpMemberDecorate %Point 1 Offset 4\n"
|
||||
"OpMemberDecorate %Point 1 Flat\n"},
|
||||
// A non-group non-member decoration survives any
|
||||
// replacement of group decorations.
|
||||
{"OpName %group \"group\"\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpDecorate %hue Centroid\n"
|
||||
"OpDecorate %group NoPerspective\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupDecorate %group %hue %saturation\n",
|
||||
"OpDecorate %hue Flat\n"
|
||||
"OpDecorate %saturation Flat\n"
|
||||
"OpDecorate %hue Centroid\n"
|
||||
"OpDecorate %hue NoPerspective\n"
|
||||
"OpDecorate %saturation NoPerspective\n"},
|
||||
// A non-group member decoration survives any
|
||||
// replacement of group decorations.
|
||||
{"OpDecorate %group Offset 0\n"
|
||||
"OpDecorate %group Flat\n"
|
||||
"OpMemberDecorate %Point 1 Offset 4\n"
|
||||
"%group = OpDecorationGroup\n"
|
||||
"OpGroupMemberDecorate %group %Point 0\n",
|
||||
"OpMemberDecorate %Point 0 Offset 0\n"
|
||||
"OpMemberDecorate %Point 0 Flat\n"
|
||||
"OpMemberDecorate %Point 1 Offset 4\n"},
|
||||
}), );
|
||||
|
||||
} // anonymous namespace
|
@ -63,6 +63,9 @@ Options:
|
||||
Remove the duplicated constants.
|
||||
--inline-entry-points-all
|
||||
Exhaustively inline all function calls in entry points
|
||||
--flatten-decorations
|
||||
Replace decoration groups with repeated OpDecorate and
|
||||
OpMemberDecorate instructions.
|
||||
-h, --help Print this help.
|
||||
--version Display optimizer version information.
|
||||
)",
|
||||
@ -131,6 +134,8 @@ int main(int argc, char** argv) {
|
||||
optimizer.RegisterPass(CreateFoldSpecConstantOpAndCompositePass());
|
||||
} else if (0 == strcmp(cur_arg, "--unify-const")) {
|
||||
optimizer.RegisterPass(CreateUnifyConstantPass());
|
||||
} else if (0 == strcmp(cur_arg, "--flatten-decorations")) {
|
||||
optimizer.RegisterPass(CreateFlattenDecorationPass());
|
||||
} else if ('\0' == cur_arg[1]) {
|
||||
// Setting a filename of "-" to indicate stdin.
|
||||
if (!in_file) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user