mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-tools.
This commit is contained in:
@@ -1 +1 @@
|
||||
"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-140-g0dbd4e35"
|
||||
"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-144-g42f88523"
|
||||
|
||||
@@ -68,7 +68,8 @@ if(SPIRV_BUILD_FUZZER)
|
||||
transformation_add_type_float.h
|
||||
transformation_add_type_int.h
|
||||
transformation_add_type_pointer.h
|
||||
transformation_construct_composite.h
|
||||
transformation_composite_construct.h
|
||||
transformation_composite_extract.h
|
||||
transformation_copy_object.h
|
||||
transformation_move_block_down.h
|
||||
transformation_replace_boolean_constant_with_constant_binary.h
|
||||
@@ -119,7 +120,8 @@ if(SPIRV_BUILD_FUZZER)
|
||||
transformation_add_type_float.cpp
|
||||
transformation_add_type_int.cpp
|
||||
transformation_add_type_pointer.cpp
|
||||
transformation_construct_composite.cpp
|
||||
transformation_composite_construct.cpp
|
||||
transformation_composite_extract.cpp
|
||||
transformation_copy_object.cpp
|
||||
transformation_move_block_down.cpp
|
||||
transformation_replace_boolean_constant_with_constant_binary.cpp
|
||||
|
||||
@@ -283,7 +283,7 @@ bool FactManager::ConstantUniformFacts::AddFact(
|
||||
auto composite_type =
|
||||
should_be_uniform_pointer_instruction->GetSingleWordInOperand(1);
|
||||
|
||||
auto final_element_type_id = fuzzerutil::WalkCompositeIndices(
|
||||
auto final_element_type_id = fuzzerutil::WalkCompositeTypeIndices(
|
||||
context, composite_type,
|
||||
fact.uniform_buffer_element_descriptor().index());
|
||||
if (!final_element_type_id) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/transformation_construct_composite.h"
|
||||
#include "source/fuzz/transformation_composite_construct.h"
|
||||
#include "source/util/make_unique.h"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -140,7 +140,7 @@ void FuzzerPassConstructComposites::Apply() {
|
||||
assert(constructor_arguments != nullptr);
|
||||
|
||||
// Make and apply a transformation.
|
||||
TransformationConstructComposite transformation(
|
||||
TransformationCompositeConstruct transformation(
|
||||
chosen_composite_type, *constructor_arguments,
|
||||
instruction_descriptor, GetFuzzerContext()->GetFreshId());
|
||||
assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
|
||||
|
||||
@@ -330,7 +330,7 @@ bool IsCompositeType(const opt::analysis::Type* type) {
|
||||
type->AsVector());
|
||||
}
|
||||
|
||||
uint32_t WalkCompositeIndices(
|
||||
uint32_t WalkCompositeTypeIndices(
|
||||
opt::IRContext* context, uint32_t base_object_type_id,
|
||||
const google::protobuf::RepeatedField<google::protobuf::uint32>& indices) {
|
||||
uint32_t sub_object_type_id = base_object_type_id;
|
||||
|
||||
@@ -98,7 +98,7 @@ bool IsCompositeType(const opt::analysis::Type* type);
|
||||
// |indices| is suitable for indexing into this type. Returns the id of the
|
||||
// type of the final sub-object reached via the indices if they are valid, and
|
||||
// 0 otherwise.
|
||||
uint32_t WalkCompositeIndices(
|
||||
uint32_t WalkCompositeTypeIndices(
|
||||
opt::IRContext* context, uint32_t base_object_type_id,
|
||||
const google::protobuf::RepeatedField<google::protobuf::uint32>& indices);
|
||||
|
||||
|
||||
@@ -187,11 +187,12 @@ message Transformation {
|
||||
TransformationCopyObject copy_object = 13;
|
||||
TransformationReplaceIdWithSynonym replace_id_with_synonym = 14;
|
||||
TransformationSetSelectionControl set_selection_control = 15;
|
||||
TransformationConstructComposite construct_composite = 16;
|
||||
TransformationCompositeConstruct composite_construct = 16;
|
||||
TransformationSetLoopControl set_loop_control = 17;
|
||||
TransformationSetFunctionControl set_function_control = 18;
|
||||
TransformationAddNoContractionDecoration add_no_contraction_decoration = 19;
|
||||
TransformationSetMemoryOperandsMask set_memory_operands_mask = 20;
|
||||
TransformationCompositeExtract composite_extract = 21;
|
||||
// Add additional option using the next available number.
|
||||
}
|
||||
}
|
||||
@@ -325,24 +326,7 @@ message TransformationAddTypePointer {
|
||||
|
||||
}
|
||||
|
||||
message TransformationCopyObject {
|
||||
|
||||
// A transformation that introduces an OpCopyObject instruction to make a
|
||||
// copy of an object.
|
||||
|
||||
// Id of the object to be copied
|
||||
uint32 object = 1;
|
||||
|
||||
// A descriptor for an instruction in a block before which the new
|
||||
// OpCopyObject instruction should be inserted
|
||||
InstructionDescriptor instruction_to_insert_before = 2;
|
||||
|
||||
// A fresh id for the copied object
|
||||
uint32 fresh_id = 3;
|
||||
|
||||
}
|
||||
|
||||
message TransformationConstructComposite {
|
||||
message TransformationCompositeConstruct {
|
||||
|
||||
// A transformation that introduces an OpCompositeConstruct instruction to
|
||||
// make a composite object.
|
||||
@@ -362,6 +346,43 @@ message TransformationConstructComposite {
|
||||
|
||||
}
|
||||
|
||||
message TransformationCompositeExtract {
|
||||
|
||||
// A transformation that adds an instruction to extract an element from a
|
||||
// composite.
|
||||
|
||||
// A descriptor for an instruction in a block before which the new
|
||||
// OpCompositeExtract instruction should be inserted
|
||||
InstructionDescriptor instruction_to_insert_before = 1;
|
||||
|
||||
// Result id for the extract operation.
|
||||
uint32 fresh_id = 2;
|
||||
|
||||
// Id of the composite from which data is to be extracted.
|
||||
uint32 composite_id = 3;
|
||||
|
||||
// Indices that indicate which part of the composite should be extracted.
|
||||
repeated uint32 index = 4;
|
||||
|
||||
}
|
||||
|
||||
message TransformationCopyObject {
|
||||
|
||||
// A transformation that introduces an OpCopyObject instruction to make a
|
||||
// copy of an object.
|
||||
|
||||
// Id of the object to be copied
|
||||
uint32 object = 1;
|
||||
|
||||
// A descriptor for an instruction in a block before which the new
|
||||
// OpCopyObject instruction should be inserted
|
||||
InstructionDescriptor instruction_to_insert_before = 2;
|
||||
|
||||
// A fresh id for the copied object
|
||||
uint32 fresh_id = 3;
|
||||
|
||||
}
|
||||
|
||||
message TransformationMoveBlockDown {
|
||||
|
||||
// A transformation that moves a basic block to be one position lower in
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include "source/fuzz/transformation_add_type_float.h"
|
||||
#include "source/fuzz/transformation_add_type_int.h"
|
||||
#include "source/fuzz/transformation_add_type_pointer.h"
|
||||
#include "source/fuzz/transformation_construct_composite.h"
|
||||
#include "source/fuzz/transformation_composite_construct.h"
|
||||
#include "source/fuzz/transformation_composite_extract.h"
|
||||
#include "source/fuzz/transformation_copy_object.h"
|
||||
#include "source/fuzz/transformation_move_block_down.h"
|
||||
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
|
||||
@@ -71,9 +72,12 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
||||
case protobufs::Transformation::TransformationCase::kAddTypePointer:
|
||||
return MakeUnique<TransformationAddTypePointer>(
|
||||
message.add_type_pointer());
|
||||
case protobufs::Transformation::TransformationCase::kConstructComposite:
|
||||
return MakeUnique<TransformationConstructComposite>(
|
||||
message.construct_composite());
|
||||
case protobufs::Transformation::TransformationCase::kCompositeConstruct:
|
||||
return MakeUnique<TransformationCompositeConstruct>(
|
||||
message.composite_construct());
|
||||
case protobufs::Transformation::TransformationCase::kCompositeExtract:
|
||||
return MakeUnique<TransformationCompositeExtract>(
|
||||
message.composite_extract());
|
||||
case protobufs::Transformation::TransformationCase::kCopyObject:
|
||||
return MakeUnique<TransformationCopyObject>(message.copy_object());
|
||||
case protobufs::Transformation::TransformationCase::kMoveBlockDown:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/transformation_construct_composite.h"
|
||||
#include "source/fuzz/transformation_composite_construct.h"
|
||||
|
||||
#include "source/fuzz/data_descriptor.h"
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
@@ -22,11 +22,11 @@
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
TransformationConstructComposite::TransformationConstructComposite(
|
||||
const protobufs::TransformationConstructComposite& message)
|
||||
TransformationCompositeConstruct::TransformationCompositeConstruct(
|
||||
const protobufs::TransformationCompositeConstruct& message)
|
||||
: message_(message) {}
|
||||
|
||||
TransformationConstructComposite::TransformationConstructComposite(
|
||||
TransformationCompositeConstruct::TransformationCompositeConstruct(
|
||||
uint32_t composite_type_id, std::vector<uint32_t> component,
|
||||
const protobufs::InstructionDescriptor& instruction_to_insert_before,
|
||||
uint32_t fresh_id) {
|
||||
@@ -39,7 +39,7 @@ TransformationConstructComposite::TransformationConstructComposite(
|
||||
message_.set_fresh_id(fresh_id);
|
||||
}
|
||||
|
||||
bool TransformationConstructComposite::IsApplicable(
|
||||
bool TransformationCompositeConstruct::IsApplicable(
|
||||
opt::IRContext* context, const FactManager& /*fact_manager*/) const {
|
||||
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
|
||||
// We require the id for the composite constructor to be unused.
|
||||
@@ -112,7 +112,7 @@ bool TransformationConstructComposite::IsApplicable(
|
||||
return true;
|
||||
}
|
||||
|
||||
void TransformationConstructComposite::Apply(opt::IRContext* context,
|
||||
void TransformationCompositeConstruct::Apply(opt::IRContext* context,
|
||||
FactManager* fact_manager) const {
|
||||
// Use the base and offset information from the transformation to determine
|
||||
// where in the module a new instruction should be inserted.
|
||||
@@ -174,7 +174,7 @@ void TransformationConstructComposite::Apply(opt::IRContext* context,
|
||||
context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
}
|
||||
|
||||
bool TransformationConstructComposite::ComponentsForArrayConstructionAreOK(
|
||||
bool TransformationCompositeConstruct::ComponentsForArrayConstructionAreOK(
|
||||
opt::IRContext* context, const opt::analysis::Array& array_type) const {
|
||||
if (array_type.length_info().words[0] !=
|
||||
opt::analysis::Array::LengthInfo::kConstant) {
|
||||
@@ -211,7 +211,7 @@ bool TransformationConstructComposite::ComponentsForArrayConstructionAreOK(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransformationConstructComposite::ComponentsForMatrixConstructionAreOK(
|
||||
bool TransformationCompositeConstruct::ComponentsForMatrixConstructionAreOK(
|
||||
opt::IRContext* context, const opt::analysis::Matrix& matrix_type) const {
|
||||
if (static_cast<uint32_t>(message_.component().size()) !=
|
||||
matrix_type.element_count()) {
|
||||
@@ -237,7 +237,7 @@ bool TransformationConstructComposite::ComponentsForMatrixConstructionAreOK(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransformationConstructComposite::ComponentsForStructConstructionAreOK(
|
||||
bool TransformationCompositeConstruct::ComponentsForStructConstructionAreOK(
|
||||
opt::IRContext* context, const opt::analysis::Struct& struct_type) const {
|
||||
if (static_cast<uint32_t>(message_.component().size()) !=
|
||||
struct_type.element_types().size()) {
|
||||
@@ -265,7 +265,7 @@ bool TransformationConstructComposite::ComponentsForStructConstructionAreOK(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransformationConstructComposite::ComponentsForVectorConstructionAreOK(
|
||||
bool TransformationCompositeConstruct::ComponentsForVectorConstructionAreOK(
|
||||
opt::IRContext* context, const opt::analysis::Vector& vector_type) const {
|
||||
uint32_t base_element_count = 0;
|
||||
auto element_type = vector_type.element_type();
|
||||
@@ -295,9 +295,9 @@ bool TransformationConstructComposite::ComponentsForVectorConstructionAreOK(
|
||||
return base_element_count == vector_type.element_count();
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationConstructComposite::ToMessage() const {
|
||||
protobufs::Transformation TransformationCompositeConstruct::ToMessage() const {
|
||||
protobufs::Transformation result;
|
||||
*result.mutable_construct_composite() = message_;
|
||||
*result.mutable_composite_construct() = message_;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_FUZZ_TRANSFORMATION_CONSTRUCT_COMPOSITE_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_CONSTRUCT_COMPOSITE_H_
|
||||
#ifndef SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_CONSTRUCT_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_CONSTRUCT_H_
|
||||
|
||||
#include "source/fuzz/fact_manager.h"
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
@@ -23,12 +23,12 @@
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
class TransformationConstructComposite : public Transformation {
|
||||
class TransformationCompositeConstruct : public Transformation {
|
||||
public:
|
||||
explicit TransformationConstructComposite(
|
||||
const protobufs::TransformationConstructComposite& message);
|
||||
explicit TransformationCompositeConstruct(
|
||||
const protobufs::TransformationCompositeConstruct& message);
|
||||
|
||||
TransformationConstructComposite(
|
||||
TransformationCompositeConstruct(
|
||||
uint32_t composite_type_id, std::vector<uint32_t> component,
|
||||
const protobufs::InstructionDescriptor& instruction_to_insert_before,
|
||||
uint32_t fresh_id);
|
||||
@@ -79,10 +79,10 @@ class TransformationConstructComposite : public Transformation {
|
||||
bool ComponentsForVectorConstructionAreOK(
|
||||
opt::IRContext* context, const opt::analysis::Vector& vector_type) const;
|
||||
|
||||
protobufs::TransformationConstructComposite message_;
|
||||
protobufs::TransformationCompositeConstruct message_;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_CONSTRUCT_COMPOSITE_H_
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_CONSTRUCT_H_
|
||||
123
3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.cpp
vendored
Normal file
123
3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.cpp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/transformation_composite_extract.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "source/fuzz/data_descriptor.h"
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
TransformationCompositeExtract::TransformationCompositeExtract(
|
||||
const spvtools::fuzz::protobufs::TransformationCompositeExtract& message)
|
||||
: message_(message) {}
|
||||
|
||||
TransformationCompositeExtract::TransformationCompositeExtract(
|
||||
const protobufs::InstructionDescriptor& instruction_to_insert_before,
|
||||
uint32_t fresh_id, uint32_t composite_id, std::vector<uint32_t>&& index) {
|
||||
*message_.mutable_instruction_to_insert_before() =
|
||||
instruction_to_insert_before;
|
||||
message_.set_fresh_id(fresh_id);
|
||||
message_.set_composite_id(composite_id);
|
||||
for (auto an_index : index) {
|
||||
message_.add_index(an_index);
|
||||
}
|
||||
}
|
||||
|
||||
bool TransformationCompositeExtract::IsApplicable(
|
||||
opt::IRContext* context,
|
||||
const spvtools::fuzz::FactManager& /*unused*/) const {
|
||||
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
|
||||
return false;
|
||||
}
|
||||
auto instruction_to_insert_before =
|
||||
FindInstruction(message_.instruction_to_insert_before(), context);
|
||||
if (!instruction_to_insert_before) {
|
||||
return false;
|
||||
}
|
||||
auto composite_instruction =
|
||||
context->get_def_use_mgr()->GetDef(message_.composite_id());
|
||||
if (!composite_instruction) {
|
||||
return false;
|
||||
}
|
||||
if (auto block = context->get_instr_block(composite_instruction)) {
|
||||
if (composite_instruction == instruction_to_insert_before ||
|
||||
!context->GetDominatorAnalysis(block->GetParent())
|
||||
->Dominates(composite_instruction, instruction_to_insert_before)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
assert(composite_instruction->type_id() &&
|
||||
"An instruction in a block cannot have a result id but no type id.");
|
||||
|
||||
auto composite_type =
|
||||
context->get_type_mgr()->GetType(composite_instruction->type_id());
|
||||
if (!composite_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
||||
SpvOpCompositeExtract, instruction_to_insert_before)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fuzzerutil::WalkCompositeTypeIndices(
|
||||
context, composite_instruction->type_id(), message_.index()) != 0;
|
||||
}
|
||||
|
||||
void TransformationCompositeExtract::Apply(
|
||||
opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
|
||||
opt::Instruction::OperandList extract_operands;
|
||||
extract_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.composite_id()}});
|
||||
for (auto an_index : message_.index()) {
|
||||
extract_operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {an_index}});
|
||||
}
|
||||
auto composite_instruction =
|
||||
context->get_def_use_mgr()->GetDef(message_.composite_id());
|
||||
auto extracted_type = fuzzerutil::WalkCompositeTypeIndices(
|
||||
context, composite_instruction->type_id(), message_.index());
|
||||
|
||||
FindInstruction(message_.instruction_to_insert_before(), context)
|
||||
->InsertBefore(MakeUnique<opt::Instruction>(
|
||||
context, SpvOpCompositeExtract, extracted_type, message_.fresh_id(),
|
||||
extract_operands));
|
||||
|
||||
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
|
||||
|
||||
// Add the fact that the id storing the extracted element is synonymous with
|
||||
// the index into the structure.
|
||||
std::vector<uint32_t> indices;
|
||||
for (auto an_index : message_.index()) {
|
||||
indices.push_back(an_index);
|
||||
}
|
||||
protobufs::DataDescriptor data_descriptor_for_extracted_element =
|
||||
MakeDataDescriptor(message_.composite_id(), std::move(indices), 1);
|
||||
protobufs::DataDescriptor data_descriptor_for_result_id =
|
||||
MakeDataDescriptor(message_.fresh_id(), {}, 1);
|
||||
fact_manager->AddFactDataSynonym(data_descriptor_for_extracted_element,
|
||||
data_descriptor_for_result_id);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationCompositeExtract::ToMessage() const {
|
||||
protobufs::Transformation result;
|
||||
*result.mutable_composite_extract() = message_;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
63
3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.h
vendored
Normal file
63
3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.h
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_EXTRACT_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_EXTRACT_H_
|
||||
|
||||
#include "source/fuzz/fact_manager.h"
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/fuzz/transformation.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
class TransformationCompositeExtract : public Transformation {
|
||||
public:
|
||||
explicit TransformationCompositeExtract(
|
||||
const protobufs::TransformationCompositeExtract& message);
|
||||
|
||||
TransformationCompositeExtract(
|
||||
const protobufs::InstructionDescriptor& instruction_to_insert_before,
|
||||
uint32_t fresh_id, uint32_t composite_id, std::vector<uint32_t>&& index);
|
||||
|
||||
// - |message_.fresh_id| must be available
|
||||
// - |message_.instruction_to_insert_before| must identify an instruction
|
||||
// before which it is valid to place an OpCompositeExtract
|
||||
// - |message_.composite_id| must be the id of an instruction that defines
|
||||
// a composite object, and this id must be available at the instruction
|
||||
// identified by |message_.instruction_to_insert_before|
|
||||
// - |message_.index| must be a suitable set of indices for
|
||||
// |message_.composite_id|, i.e. it must be possible to follow this chain
|
||||
// of indices to reach a sub-object of |message_.composite_id|
|
||||
bool IsApplicable(opt::IRContext* context,
|
||||
const FactManager& fact_manager) const override;
|
||||
|
||||
// Adds an OpCompositeConstruct instruction before the instruction identified
|
||||
// by |message_.instruction_to_insert_before|, that extracts from
|
||||
// |message_.composite_id| via indices |message_.index| into
|
||||
// |message_.fresh_id|. Generates a data synonym fact relating
|
||||
// |message_.fresh_id| to the extracted element.
|
||||
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
|
||||
|
||||
protobufs::Transformation ToMessage() const override;
|
||||
|
||||
private:
|
||||
protobufs::TransformationCompositeExtract message_;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_EXTRACT_H_
|
||||
@@ -275,22 +275,27 @@ bool TransformationReplaceIdWithSynonym::ReplacingUseWithSynonymIsOk(
|
||||
|
||||
// We now need to check that replacing the use with the synonym will respect
|
||||
// dominance rules - i.e. the synonym needs to dominate the use.
|
||||
auto dominator_analysis = context->GetDominatorAnalysis(
|
||||
context->get_instr_block(use_instruction)->GetParent());
|
||||
if (use_instruction->opcode() == SpvOpPhi) {
|
||||
// In the case where the use is an operand to OpPhi, it is actually the
|
||||
// *parent* block associated with the operand that must be dominated by the
|
||||
// synonym.
|
||||
auto parent_block =
|
||||
use_instruction->GetSingleWordInOperand(use_in_operand_index + 1);
|
||||
if (!dominator_analysis->Dominates(
|
||||
context->get_instr_block(defining_instruction)->id(),
|
||||
parent_block)) {
|
||||
// This is only relevant if the defining instruction is in a block; if it is
|
||||
// not in a block then it is at global scope, and so replacing the use with it
|
||||
// is fine.
|
||||
if (context->get_instr_block(defining_instruction)) {
|
||||
auto dominator_analysis = context->GetDominatorAnalysis(
|
||||
context->get_instr_block(use_instruction)->GetParent());
|
||||
if (use_instruction->opcode() == SpvOpPhi) {
|
||||
// In the case where the use is an operand to OpPhi, it is actually the
|
||||
// *parent* block associated with the operand that must be dominated by
|
||||
// the synonym.
|
||||
auto parent_block =
|
||||
use_instruction->GetSingleWordInOperand(use_in_operand_index + 1);
|
||||
if (!dominator_analysis->Dominates(
|
||||
context->get_instr_block(defining_instruction)->id(),
|
||||
parent_block)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!dominator_analysis->Dominates(defining_instruction,
|
||||
use_instruction)) {
|
||||
return false;
|
||||
}
|
||||
} else if (!dominator_analysis->Dominates(defining_instruction,
|
||||
use_instruction)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
116
3rdparty/spirv-tools/source/opt/folding_rules.cpp
vendored
116
3rdparty/spirv-tools/source/opt/folding_rules.cpp
vendored
@@ -18,6 +18,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "ir_builder.h"
|
||||
#include "source/latest_version_glsl_std_450_header.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
@@ -1239,6 +1240,117 @@ FoldingRule MergeSubSubArithmetic() {
|
||||
};
|
||||
}
|
||||
|
||||
// Helper function for MergeGenericAddSubArithmetic. If |addend| and
|
||||
// subtrahend of |sub| is the same, merge to copy of minuend of |sub|.
|
||||
bool MergeGenericAddendSub(uint32_t addend, uint32_t sub, Instruction* inst) {
|
||||
IRContext* context = inst->context();
|
||||
analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
|
||||
Instruction* sub_inst = def_use_mgr->GetDef(sub);
|
||||
if (sub_inst->opcode() != SpvOpFSub && sub_inst->opcode() != SpvOpISub)
|
||||
return false;
|
||||
if (sub_inst->opcode() == SpvOpFSub &&
|
||||
!sub_inst->IsFloatingPointFoldingAllowed())
|
||||
return false;
|
||||
if (addend != sub_inst->GetSingleWordInOperand(1)) return false;
|
||||
inst->SetOpcode(SpvOpCopyObject);
|
||||
inst->SetInOperands(
|
||||
{{SPV_OPERAND_TYPE_ID, {sub_inst->GetSingleWordInOperand(0)}}});
|
||||
context->UpdateDefUse(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Folds addition of a subtraction where the subtrahend is equal to the
|
||||
// other addend. Return a copy of the minuend. Accepts generic (const and
|
||||
// non-const) operands.
|
||||
// Cases:
|
||||
// (a - b) + b = a
|
||||
// b + (a - b) = a
|
||||
FoldingRule MergeGenericAddSubArithmetic() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>&) {
|
||||
assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
|
||||
const analysis::Type* type =
|
||||
context->get_type_mgr()->GetType(inst->type_id());
|
||||
bool uses_float = HasFloatingPoint(type);
|
||||
if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;
|
||||
|
||||
uint32_t width = ElementWidth(type);
|
||||
if (width != 32 && width != 64) return false;
|
||||
|
||||
uint32_t add_op0 = inst->GetSingleWordInOperand(0);
|
||||
uint32_t add_op1 = inst->GetSingleWordInOperand(1);
|
||||
if (MergeGenericAddendSub(add_op0, add_op1, inst)) return true;
|
||||
return MergeGenericAddendSub(add_op1, add_op0, inst);
|
||||
};
|
||||
}
|
||||
|
||||
// Helper function for FactorAddMuls. If |factor0_0| is the same as |factor1_0|,
|
||||
// generate |factor0_0| * (|factor0_1| + |factor1_1|).
|
||||
bool FactorAddMulsOpnds(uint32_t factor0_0, uint32_t factor0_1,
|
||||
uint32_t factor1_0, uint32_t factor1_1,
|
||||
Instruction* inst) {
|
||||
IRContext* context = inst->context();
|
||||
if (factor0_0 != factor1_0) return false;
|
||||
InstructionBuilder ir_builder(
|
||||
context, inst,
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||
Instruction* new_add_inst = ir_builder.AddBinaryOp(
|
||||
inst->type_id(), inst->opcode(), factor0_1, factor1_1);
|
||||
inst->SetOpcode(inst->opcode() == SpvOpFAdd ? SpvOpFMul : SpvOpIMul);
|
||||
inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {factor0_0}},
|
||||
{SPV_OPERAND_TYPE_ID, {new_add_inst->result_id()}}});
|
||||
context->UpdateDefUse(inst);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Perform the following factoring identity, handling all operand order
|
||||
// combinations: (a * b) + (a * c) = a * (b + c)
|
||||
FoldingRule FactorAddMuls() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>&) {
|
||||
assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
|
||||
const analysis::Type* type =
|
||||
context->get_type_mgr()->GetType(inst->type_id());
|
||||
bool uses_float = HasFloatingPoint(type);
|
||||
if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;
|
||||
|
||||
analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
|
||||
uint32_t add_op0 = inst->GetSingleWordInOperand(0);
|
||||
Instruction* add_op0_inst = def_use_mgr->GetDef(add_op0);
|
||||
if (add_op0_inst->opcode() != SpvOpFMul &&
|
||||
add_op0_inst->opcode() != SpvOpIMul)
|
||||
return false;
|
||||
uint32_t add_op1 = inst->GetSingleWordInOperand(1);
|
||||
Instruction* add_op1_inst = def_use_mgr->GetDef(add_op1);
|
||||
if (add_op1_inst->opcode() != SpvOpFMul &&
|
||||
add_op1_inst->opcode() != SpvOpIMul)
|
||||
return false;
|
||||
|
||||
// Only perform this optimization if both of the muls only have one use.
|
||||
// Otherwise this is a deoptimization in size and performance.
|
||||
if (def_use_mgr->NumUses(add_op0_inst) > 1) return false;
|
||||
if (def_use_mgr->NumUses(add_op1_inst) > 1) return false;
|
||||
|
||||
if (add_op0_inst->opcode() == SpvOpFMul &&
|
||||
(!add_op0_inst->IsFloatingPointFoldingAllowed() ||
|
||||
!add_op1_inst->IsFloatingPointFoldingAllowed()))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
// Check if operand i in add_op0_inst matches operand j in add_op1_inst.
|
||||
if (FactorAddMulsOpnds(add_op0_inst->GetSingleWordInOperand(i),
|
||||
add_op0_inst->GetSingleWordInOperand(1 - i),
|
||||
add_op1_inst->GetSingleWordInOperand(j),
|
||||
add_op1_inst->GetSingleWordInOperand(1 - j),
|
||||
inst))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
FoldingRule IntMultipleBy1() {
|
||||
return [](IRContext*, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants) {
|
||||
@@ -2226,6 +2338,8 @@ void FoldingRules::AddFoldingRules() {
|
||||
rules_[SpvOpFAdd].push_back(MergeAddNegateArithmetic());
|
||||
rules_[SpvOpFAdd].push_back(MergeAddAddArithmetic());
|
||||
rules_[SpvOpFAdd].push_back(MergeAddSubArithmetic());
|
||||
rules_[SpvOpFAdd].push_back(MergeGenericAddSubArithmetic());
|
||||
rules_[SpvOpFAdd].push_back(FactorAddMuls());
|
||||
|
||||
rules_[SpvOpFDiv].push_back(RedundantFDiv());
|
||||
rules_[SpvOpFDiv].push_back(ReciprocalFDiv());
|
||||
@@ -2251,6 +2365,8 @@ void FoldingRules::AddFoldingRules() {
|
||||
rules_[SpvOpIAdd].push_back(MergeAddNegateArithmetic());
|
||||
rules_[SpvOpIAdd].push_back(MergeAddAddArithmetic());
|
||||
rules_[SpvOpIAdd].push_back(MergeAddSubArithmetic());
|
||||
rules_[SpvOpIAdd].push_back(MergeGenericAddSubArithmetic());
|
||||
rules_[SpvOpIAdd].push_back(FactorAddMuls());
|
||||
|
||||
rules_[SpvOpIMul].push_back(IntMultipleBy1());
|
||||
rules_[SpvOpIMul].push_back(MergeMulMulArithmetic());
|
||||
|
||||
@@ -32,6 +32,18 @@ Pass::Status SimplificationPass::Process() {
|
||||
return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
|
||||
}
|
||||
|
||||
void SimplificationPass::AddNewOperands(
|
||||
Instruction* folded_inst, std::unordered_set<Instruction*>* inst_seen,
|
||||
std::vector<Instruction*>* work_list) {
|
||||
analysis::DefUseManager* def_use_mgr = get_def_use_mgr();
|
||||
folded_inst->ForEachInId(
|
||||
[&inst_seen, &def_use_mgr, &work_list](uint32_t* iid) {
|
||||
Instruction* iid_inst = def_use_mgr->GetDef(*iid);
|
||||
if (!inst_seen->insert(iid_inst).second) return;
|
||||
work_list->push_back(iid_inst);
|
||||
});
|
||||
}
|
||||
|
||||
bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
bool modified = false;
|
||||
// Phase 1: Traverse all instructions in dominance order.
|
||||
@@ -44,13 +56,15 @@ bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
std::unordered_set<Instruction*> process_phis;
|
||||
std::unordered_set<Instruction*> inst_to_kill;
|
||||
std::unordered_set<Instruction*> in_work_list;
|
||||
std::unordered_set<Instruction*> inst_seen;
|
||||
const InstructionFolder& folder = context()->get_instruction_folder();
|
||||
|
||||
cfg()->ForEachBlockInReversePostOrder(
|
||||
function->entry().get(),
|
||||
[&modified, &process_phis, &work_list, &in_work_list, &inst_to_kill,
|
||||
&folder, this](BasicBlock* bb) {
|
||||
&folder, &inst_seen, this](BasicBlock* bb) {
|
||||
for (Instruction* inst = &*bb->begin(); inst; inst = inst->NextNode()) {
|
||||
inst_seen.insert(inst);
|
||||
if (inst->opcode() == SpvOpPhi) {
|
||||
process_phis.insert(inst);
|
||||
}
|
||||
@@ -70,6 +84,9 @@ bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
work_list.push_back(use);
|
||||
}
|
||||
});
|
||||
|
||||
AddNewOperands(inst, &inst_seen, &work_list);
|
||||
|
||||
if (inst->opcode() == SpvOpCopyObject) {
|
||||
context()->ReplaceAllUsesWithPredicate(
|
||||
inst->result_id(), inst->GetSingleWordInOperand(0),
|
||||
@@ -97,6 +114,7 @@ bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
for (size_t i = 0; i < work_list.size(); ++i) {
|
||||
Instruction* inst = work_list[i];
|
||||
in_work_list.erase(inst);
|
||||
inst_seen.insert(inst);
|
||||
|
||||
bool is_foldable_copy =
|
||||
inst->opcode() == SpvOpCopyObject &&
|
||||
@@ -114,6 +132,8 @@ bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
}
|
||||
});
|
||||
|
||||
AddNewOperands(inst, &inst_seen, &work_list);
|
||||
|
||||
if (inst->opcode() == SpvOpCopyObject) {
|
||||
context()->ReplaceAllUsesWithPredicate(
|
||||
inst->result_id(), inst->GetSingleWordInOperand(0),
|
||||
|
||||
@@ -42,6 +42,14 @@ class SimplificationPass : public Pass {
|
||||
// instruction in |function| until nothing else in the function can be
|
||||
// simplified.
|
||||
bool SimplifyFunction(Function* function);
|
||||
|
||||
// FactorAddMul can create |folded_inst| Mul of new Add. If Mul, push any Add
|
||||
// operand not in |seen_inst| into |worklist|. This is heavily restricted to
|
||||
// improve compile time but can be expanded for future simplifications which
|
||||
// simiarly create new operations.
|
||||
void AddNewOperands(Instruction* folded_inst,
|
||||
std::unordered_set<Instruction*>* inst_seen,
|
||||
std::vector<Instruction*>* work_list);
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
|
||||
@@ -31,7 +31,8 @@ if (${SPIRV_BUILD_FUZZER})
|
||||
transformation_add_type_float_test.cpp
|
||||
transformation_add_type_int_test.cpp
|
||||
transformation_add_type_pointer_test.cpp
|
||||
transformation_construct_composite_test.cpp
|
||||
transformation_composite_construct_test.cpp
|
||||
transformation_composite_extract_test.cpp
|
||||
transformation_copy_object_test.cpp
|
||||
transformation_move_block_down_test.cpp
|
||||
transformation_replace_boolean_constant_with_constant_binary_test.cpp
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/transformation_construct_composite.h"
|
||||
#include "source/fuzz/transformation_composite_construct.h"
|
||||
#include "source/fuzz/data_descriptor.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
@@ -36,7 +36,7 @@ bool SynonymFactHolds(const FactManager& fact_manager, uint32_t id,
|
||||
}) != synonyms.end();
|
||||
}
|
||||
|
||||
TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@@ -146,11 +146,11 @@ TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
FactManager fact_manager;
|
||||
|
||||
// Make a vec2[3]
|
||||
TransformationConstructComposite make_vec2_array_length_3(
|
||||
TransformationCompositeConstruct make_vec2_array_length_3(
|
||||
37, {41, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
|
||||
200);
|
||||
// Bad: there are too many components
|
||||
TransformationConstructComposite make_vec2_array_length_3_bad(
|
||||
TransformationCompositeConstruct make_vec2_array_length_3_bad(
|
||||
37, {41, 45, 27, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
|
||||
200);
|
||||
ASSERT_TRUE(
|
||||
@@ -164,10 +164,10 @@ TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 27, 200, {2}));
|
||||
|
||||
// Make a float[2]
|
||||
TransformationConstructComposite make_float_array_length_2(
|
||||
TransformationCompositeConstruct make_float_array_length_2(
|
||||
9, {24, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
|
||||
// Bad: %41 does not have type float
|
||||
TransformationConstructComposite make_float_array_length_2_bad(
|
||||
TransformationCompositeConstruct make_float_array_length_2_bad(
|
||||
9, {41, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
|
||||
ASSERT_TRUE(
|
||||
make_float_array_length_2.IsApplicable(context.get(), fact_manager));
|
||||
@@ -179,11 +179,11 @@ TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 40, 201, {1}));
|
||||
|
||||
// Make a bool[3]
|
||||
TransformationConstructComposite make_bool_array_length_3(
|
||||
TransformationCompositeConstruct make_bool_array_length_3(
|
||||
47, {33, 50, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
|
||||
202);
|
||||
// Bad: %54 is not available at the desired program point.
|
||||
TransformationConstructComposite make_bool_array_length_3_bad(
|
||||
TransformationCompositeConstruct make_bool_array_length_3_bad(
|
||||
47, {33, 54, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
|
||||
202);
|
||||
ASSERT_TRUE(
|
||||
@@ -197,10 +197,10 @@ TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 50, 202, {2}));
|
||||
|
||||
// make a uvec3[2][2]
|
||||
TransformationConstructComposite make_uvec3_array_length_2_2(
|
||||
TransformationCompositeConstruct make_uvec3_array_length_2_2(
|
||||
58, {69, 100}, MakeInstructionDescriptor(64, SpvOpStore, 0), 203);
|
||||
// Bad: Skip count 100 is too large.
|
||||
TransformationConstructComposite make_uvec3_array_length_2_2_bad(
|
||||
TransformationCompositeConstruct make_uvec3_array_length_2_2_bad(
|
||||
58, {33, 54}, MakeInstructionDescriptor(64, SpvOpStore, 100), 203);
|
||||
ASSERT_TRUE(
|
||||
make_uvec3_array_length_2_2.IsApplicable(context.get(), fact_manager));
|
||||
@@ -319,7 +319,7 @@ TEST(TransformationConstructCompositeTest, ConstructArrays) {
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
TEST(TransformationConstructCompositeTest, ConstructMatrices) {
|
||||
TEST(TransformationCompositeConstructTest, ConstructMatrices) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@@ -399,10 +399,10 @@ TEST(TransformationConstructCompositeTest, ConstructMatrices) {
|
||||
FactManager fact_manager;
|
||||
|
||||
// make a mat3x4
|
||||
TransformationConstructComposite make_mat34(
|
||||
TransformationCompositeConstruct make_mat34(
|
||||
32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
|
||||
// Bad: %35 is mat4x3, not mat3x4.
|
||||
TransformationConstructComposite make_mat34_bad(
|
||||
TransformationCompositeConstruct make_mat34_bad(
|
||||
35, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
|
||||
ASSERT_TRUE(make_mat34.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_mat34_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -413,10 +413,10 @@ TEST(TransformationConstructCompositeTest, ConstructMatrices) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 31, 200, {2}));
|
||||
|
||||
// make a mat4x3
|
||||
TransformationConstructComposite make_mat43(
|
||||
TransformationCompositeConstruct make_mat43(
|
||||
35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
|
||||
// Bad: %25 does not match the matrix's column type.
|
||||
TransformationConstructComposite make_mat43_bad(
|
||||
TransformationCompositeConstruct make_mat43_bad(
|
||||
35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
|
||||
ASSERT_TRUE(make_mat43.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_mat43_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -503,7 +503,7 @@ TEST(TransformationConstructCompositeTest, ConstructMatrices) {
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
TEST(TransformationConstructCompositeTest, ConstructStructs) {
|
||||
TEST(TransformationCompositeConstructTest, ConstructStructs) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@@ -600,10 +600,10 @@ TEST(TransformationConstructCompositeTest, ConstructStructs) {
|
||||
FactManager fact_manager;
|
||||
|
||||
// make an Inner
|
||||
TransformationConstructComposite make_inner(
|
||||
TransformationCompositeConstruct make_inner(
|
||||
9, {25, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
|
||||
// Bad: Too few fields to make the struct.
|
||||
TransformationConstructComposite make_inner_bad(
|
||||
TransformationCompositeConstruct make_inner_bad(
|
||||
9, {25}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
|
||||
ASSERT_TRUE(make_inner.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_inner_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -613,11 +613,11 @@ TEST(TransformationConstructCompositeTest, ConstructStructs) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 19, 200, {1}));
|
||||
|
||||
// make an Outer
|
||||
TransformationConstructComposite make_outer(
|
||||
TransformationCompositeConstruct make_outer(
|
||||
33, {46, 200, 56}, MakeInstructionDescriptor(200, SpvOpAccessChain, 0),
|
||||
201);
|
||||
// Bad: %200 is not available at the desired program point.
|
||||
TransformationConstructComposite make_outer_bad(
|
||||
TransformationCompositeConstruct make_outer_bad(
|
||||
33, {46, 200, 56},
|
||||
MakeInstructionDescriptor(200, SpvOpCompositeConstruct, 0), 201);
|
||||
ASSERT_TRUE(make_outer.IsApplicable(context.get(), fact_manager));
|
||||
@@ -721,7 +721,7 @@ TEST(TransformationConstructCompositeTest, ConstructStructs) {
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
@@ -913,10 +913,10 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
|
||||
FactManager fact_manager;
|
||||
|
||||
TransformationConstructComposite make_vec2(
|
||||
TransformationCompositeConstruct make_vec2(
|
||||
7, {17, 11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
|
||||
// Bad: not enough data for a vec2
|
||||
TransformationConstructComposite make_vec2_bad(
|
||||
TransformationCompositeConstruct make_vec2_bad(
|
||||
7, {11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
|
||||
ASSERT_TRUE(make_vec2.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_vec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -925,11 +925,11 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 17, 200, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 11, 200, {1}));
|
||||
|
||||
TransformationConstructComposite make_vec3(
|
||||
TransformationCompositeConstruct make_vec3(
|
||||
25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0),
|
||||
201);
|
||||
// Bad: too much data for a vec3
|
||||
TransformationConstructComposite make_vec3_bad(
|
||||
TransformationCompositeConstruct make_vec3_bad(
|
||||
25, {12, 32, 32},
|
||||
MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), 201);
|
||||
ASSERT_TRUE(make_vec3.IsApplicable(context.get(), fact_manager));
|
||||
@@ -939,11 +939,11 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 12, 201, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 32, 201, {2}));
|
||||
|
||||
TransformationConstructComposite make_vec4(
|
||||
TransformationCompositeConstruct make_vec4(
|
||||
44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
|
||||
202);
|
||||
// Bad: id 48 is not available at the insertion points
|
||||
TransformationConstructComposite make_vec4_bad(
|
||||
TransformationCompositeConstruct make_vec4_bad(
|
||||
44, {48, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
|
||||
202);
|
||||
ASSERT_TRUE(make_vec4.IsApplicable(context.get(), fact_manager));
|
||||
@@ -955,10 +955,10 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 10, 202, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 11, 202, {3}));
|
||||
|
||||
TransformationConstructComposite make_ivec2(
|
||||
TransformationCompositeConstruct make_ivec2(
|
||||
51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
|
||||
// Bad: if 128 is not available at the instruction that defines 128
|
||||
TransformationConstructComposite make_ivec2_bad(
|
||||
TransformationCompositeConstruct make_ivec2_bad(
|
||||
51, {128, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
|
||||
ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_ivec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -967,11 +967,11 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 126, 203, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 120, 203, {1}));
|
||||
|
||||
TransformationConstructComposite make_ivec3(
|
||||
TransformationCompositeConstruct make_ivec3(
|
||||
114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
|
||||
204);
|
||||
// Bad because 1300 is not an id
|
||||
TransformationConstructComposite make_ivec3_bad(
|
||||
TransformationCompositeConstruct make_ivec3_bad(
|
||||
114, {56, 117, 1300}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
|
||||
204);
|
||||
ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), fact_manager));
|
||||
@@ -982,11 +982,11 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 204, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 56, 204, {2}));
|
||||
|
||||
TransformationConstructComposite make_ivec4(
|
||||
TransformationCompositeConstruct make_ivec4(
|
||||
122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
|
||||
205);
|
||||
// Bad because 86 is the wrong type.
|
||||
TransformationConstructComposite make_ivec4_bad(
|
||||
TransformationCompositeConstruct make_ivec4_bad(
|
||||
86, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
|
||||
205);
|
||||
ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), fact_manager));
|
||||
@@ -998,9 +998,9 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 205, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 205, {3}));
|
||||
|
||||
TransformationConstructComposite make_uvec2(
|
||||
TransformationCompositeConstruct make_uvec2(
|
||||
86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206);
|
||||
TransformationConstructComposite make_uvec2_bad(
|
||||
TransformationCompositeConstruct make_uvec2_bad(
|
||||
86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 200), 206);
|
||||
ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_uvec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -1009,10 +1009,10 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 18, 206, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 38, 206, {1}));
|
||||
|
||||
TransformationConstructComposite make_uvec3(
|
||||
TransformationCompositeConstruct make_uvec3(
|
||||
59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
|
||||
// Bad because 1300 is not an id
|
||||
TransformationConstructComposite make_uvec3_bad(
|
||||
TransformationCompositeConstruct make_uvec3_bad(
|
||||
59, {14, 18, 1300}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
|
||||
ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_uvec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -1022,11 +1022,11 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 18, 207, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 207, {2}));
|
||||
|
||||
TransformationConstructComposite make_uvec4(
|
||||
TransformationCompositeConstruct make_uvec4(
|
||||
131, {14, 18, 136, 136},
|
||||
MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
|
||||
// Bad because 86 is the wrong type.
|
||||
TransformationConstructComposite make_uvec4_bad(
|
||||
TransformationCompositeConstruct make_uvec4_bad(
|
||||
86, {14, 18, 136, 136},
|
||||
MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
|
||||
ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), fact_manager));
|
||||
@@ -1038,7 +1038,7 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 208, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 208, {3}));
|
||||
|
||||
TransformationConstructComposite make_bvec2(
|
||||
TransformationCompositeConstruct make_bvec2(
|
||||
102,
|
||||
{
|
||||
111,
|
||||
@@ -1046,7 +1046,7 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
},
|
||||
MakeInstructionDescriptor(75, SpvOpAccessChain, 0), 209);
|
||||
// Bad because 0 is not a valid base instruction id
|
||||
TransformationConstructComposite make_bvec2_bad(
|
||||
TransformationCompositeConstruct make_bvec2_bad(
|
||||
102,
|
||||
{
|
||||
111,
|
||||
@@ -1060,10 +1060,10 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 111, 209, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 41, 209, {1}));
|
||||
|
||||
TransformationConstructComposite make_bvec3(
|
||||
TransformationCompositeConstruct make_bvec3(
|
||||
93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
|
||||
// Bad because there are too many components for a bvec3
|
||||
TransformationConstructComposite make_bvec3_bad(
|
||||
TransformationCompositeConstruct make_bvec3_bad(
|
||||
93, {108, 108}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
|
||||
ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_bvec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
@@ -1072,10 +1072,10 @@ TEST(TransformationConstructCompositeTest, ConstructVectors) {
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 108, 210, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 73, 210, {2}));
|
||||
|
||||
TransformationConstructComposite make_bvec4(
|
||||
TransformationCompositeConstruct make_bvec4(
|
||||
70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
|
||||
// Bad because 21 is a type, not a result id
|
||||
TransformationConstructComposite make_bvec4_bad(
|
||||
TransformationCompositeConstruct make_bvec4_bad(
|
||||
70, {21, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
|
||||
ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(make_bvec4_bad.IsApplicable(context.get(), fact_manager));
|
||||
393
3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp
vendored
Normal file
393
3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
// Copyright (c) 2019 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/transformation_composite_extract.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
bool IsSynonymous(const FactManager& fact_manager, uint32_t id,
|
||||
uint32_t composite_id, std::vector<uint32_t>&& indices) {
|
||||
protobufs::DataDescriptor data_descriptor =
|
||||
MakeDataDescriptor(composite_id, std::move(indices), 1);
|
||||
return fact_manager.GetSynonymsForId(id).count(&data_descriptor) == 1;
|
||||
}
|
||||
|
||||
TEST(TransformationCompositeExtractTest, BasicTest) {
|
||||
std::string shader = 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 %8 "a"
|
||||
OpName %10 "b"
|
||||
OpName %17 "FunnyPoint"
|
||||
OpMemberName %17 0 "x"
|
||||
OpMemberName %17 1 "y"
|
||||
OpMemberName %17 2 "z"
|
||||
OpName %19 "p"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeInt 32 1
|
||||
%7 = OpTypePointer Function %6
|
||||
%12 = OpTypeBool
|
||||
%16 = OpTypeFloat 32
|
||||
%17 = OpTypeStruct %16 %16 %6
|
||||
%81 = OpTypeStruct %17 %16
|
||||
%18 = OpTypePointer Function %17
|
||||
%20 = OpConstant %6 0
|
||||
%23 = OpTypePointer Function %16
|
||||
%26 = OpConstant %6 1
|
||||
%30 = OpConstant %6 2
|
||||
%80 = OpUndef %16
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%8 = OpVariable %7 Function
|
||||
%10 = OpVariable %7 Function
|
||||
%19 = OpVariable %18 Function
|
||||
%9 = OpLoad %6 %8
|
||||
%11 = OpLoad %6 %10
|
||||
%100 = OpCompositeConstruct %17 %80 %80 %26
|
||||
%104 = OpCompositeConstruct %81 %100 %80
|
||||
%13 = OpIEqual %12 %9 %11
|
||||
OpSelectionMerge %15 None
|
||||
OpBranchConditional %13 %14 %25
|
||||
%14 = OpLabel
|
||||
%21 = OpLoad %6 %8
|
||||
%22 = OpConvertSToF %16 %21
|
||||
%101 = OpCompositeConstruct %17 %22 %80 %30
|
||||
%24 = OpAccessChain %23 %19 %20
|
||||
OpStore %24 %22
|
||||
OpBranch %15
|
||||
%25 = OpLabel
|
||||
%27 = OpLoad %6 %10
|
||||
%28 = OpConvertSToF %16 %27
|
||||
%102 = OpCompositeConstruct %17 %80 %28 %27
|
||||
%29 = OpAccessChain %23 %19 %26
|
||||
OpStore %29 %28
|
||||
OpBranch %15
|
||||
%15 = OpLabel
|
||||
%31 = OpAccessChain %23 %19 %20
|
||||
%32 = OpLoad %16 %31
|
||||
%33 = OpAccessChain %23 %19 %26
|
||||
%34 = OpLoad %16 %33
|
||||
%103 = OpCompositeConstruct %17 %34 %32 %9
|
||||
%35 = OpFAdd %16 %32 %34
|
||||
%36 = OpConvertFToS %6 %35
|
||||
%37 = OpAccessChain %7 %19 %30
|
||||
OpStore %37 %36
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_4;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
|
||||
// Instruction does not exist.
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Id for composite is not a composite.
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 27, {})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Composite does not dominate instruction being inserted before.
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Too many indices for extraction from struct composite.
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Too many indices for extraction from struct composite.
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Out of bounds index for extraction from struct composite.
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Result id already used.
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
TransformationCompositeExtract transformation_1(
|
||||
MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
|
||||
ASSERT_TRUE(transformation_1.IsApplicable(context.get(), fact_manager));
|
||||
transformation_1.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
TransformationCompositeExtract transformation_2(
|
||||
MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2});
|
||||
ASSERT_TRUE(transformation_2.IsApplicable(context.get(), fact_manager));
|
||||
transformation_2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
TransformationCompositeExtract transformation_3(
|
||||
MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0});
|
||||
ASSERT_TRUE(transformation_3.IsApplicable(context.get(), fact_manager));
|
||||
transformation_3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
TransformationCompositeExtract transformation_4(
|
||||
MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0});
|
||||
ASSERT_TRUE(transformation_4.IsApplicable(context.get(), fact_manager));
|
||||
transformation_4.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
TransformationCompositeExtract transformation_5(
|
||||
MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2});
|
||||
ASSERT_TRUE(transformation_5.IsApplicable(context.get(), fact_manager));
|
||||
transformation_5.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
TransformationCompositeExtract transformation_6(
|
||||
MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1});
|
||||
ASSERT_TRUE(transformation_6.IsApplicable(context.get(), fact_manager));
|
||||
transformation_6.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 201, 100, {2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 202, 104, {0, 2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 203, 104, {0}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 204, 101, {0}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 205, 102, {2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 206, 103, {1}));
|
||||
|
||||
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 %8 "a"
|
||||
OpName %10 "b"
|
||||
OpName %17 "FunnyPoint"
|
||||
OpMemberName %17 0 "x"
|
||||
OpMemberName %17 1 "y"
|
||||
OpMemberName %17 2 "z"
|
||||
OpName %19 "p"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeInt 32 1
|
||||
%7 = OpTypePointer Function %6
|
||||
%12 = OpTypeBool
|
||||
%16 = OpTypeFloat 32
|
||||
%17 = OpTypeStruct %16 %16 %6
|
||||
%81 = OpTypeStruct %17 %16
|
||||
%18 = OpTypePointer Function %17
|
||||
%20 = OpConstant %6 0
|
||||
%23 = OpTypePointer Function %16
|
||||
%26 = OpConstant %6 1
|
||||
%30 = OpConstant %6 2
|
||||
%80 = OpUndef %16
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%8 = OpVariable %7 Function
|
||||
%10 = OpVariable %7 Function
|
||||
%19 = OpVariable %18 Function
|
||||
%9 = OpLoad %6 %8
|
||||
%11 = OpLoad %6 %10
|
||||
%100 = OpCompositeConstruct %17 %80 %80 %26
|
||||
%104 = OpCompositeConstruct %81 %100 %80
|
||||
%13 = OpIEqual %12 %9 %11
|
||||
OpSelectionMerge %15 None
|
||||
OpBranchConditional %13 %14 %25
|
||||
%14 = OpLabel
|
||||
%21 = OpLoad %6 %8
|
||||
%22 = OpConvertSToF %16 %21
|
||||
%101 = OpCompositeConstruct %17 %22 %80 %30
|
||||
%24 = OpAccessChain %23 %19 %20
|
||||
%204 = OpCompositeExtract %16 %101 0
|
||||
OpStore %24 %22
|
||||
OpBranch %15
|
||||
%25 = OpLabel
|
||||
%27 = OpLoad %6 %10
|
||||
%28 = OpConvertSToF %16 %27
|
||||
%102 = OpCompositeConstruct %17 %80 %28 %27
|
||||
%203 = OpCompositeExtract %17 %104 0
|
||||
%29 = OpAccessChain %23 %19 %26
|
||||
OpStore %29 %28
|
||||
%205 = OpCompositeExtract %6 %102 2
|
||||
OpBranch %15
|
||||
%15 = OpLabel
|
||||
%31 = OpAccessChain %23 %19 %20
|
||||
%32 = OpLoad %16 %31
|
||||
%33 = OpAccessChain %23 %19 %26
|
||||
%34 = OpLoad %16 %33
|
||||
%103 = OpCompositeConstruct %17 %34 %32 %9
|
||||
%35 = OpFAdd %16 %32 %34
|
||||
%201 = OpCompositeExtract %6 %100 2
|
||||
%36 = OpConvertFToS %6 %35
|
||||
%202 = OpCompositeExtract %6 %104 0 2
|
||||
%37 = OpAccessChain %7 %19 %30
|
||||
OpStore %37 %36
|
||||
%206 = OpCompositeExtract %16 %103 1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
TEST(TransformationCompositeExtractTest, IllegalInsertionPoints) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main" %51 %27
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
OpName %25 "buf"
|
||||
OpMemberName %25 0 "value"
|
||||
OpName %27 ""
|
||||
OpName %51 "color"
|
||||
OpMemberDecorate %25 0 Offset 0
|
||||
OpDecorate %25 Block
|
||||
OpDecorate %27 DescriptorSet 0
|
||||
OpDecorate %27 Binding 0
|
||||
OpDecorate %51 Location 0
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%7 = OpTypeVector %6 4
|
||||
%10 = OpConstant %6 0.300000012
|
||||
%11 = OpConstant %6 0.400000006
|
||||
%12 = OpConstant %6 0.5
|
||||
%13 = OpConstant %6 1
|
||||
%14 = OpConstantComposite %7 %10 %11 %12 %13
|
||||
%15 = OpTypeInt 32 1
|
||||
%18 = OpConstant %15 0
|
||||
%25 = OpTypeStruct %6
|
||||
%26 = OpTypePointer Uniform %25
|
||||
%27 = OpVariable %26 Uniform
|
||||
%28 = OpTypePointer Uniform %6
|
||||
%32 = OpTypeBool
|
||||
%103 = OpConstantTrue %32
|
||||
%34 = OpConstant %6 0.100000001
|
||||
%48 = OpConstant %15 1
|
||||
%50 = OpTypePointer Output %7
|
||||
%51 = OpVariable %50 Output
|
||||
%100 = OpTypePointer Function %6
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%101 = OpVariable %100 Function
|
||||
%102 = OpVariable %100 Function
|
||||
OpBranch %19
|
||||
%19 = OpLabel
|
||||
%60 = OpPhi %7 %14 %5 %58 %20
|
||||
%59 = OpPhi %15 %18 %5 %49 %20
|
||||
%29 = OpAccessChain %28 %27 %18
|
||||
%30 = OpLoad %6 %29
|
||||
%31 = OpConvertFToS %15 %30
|
||||
%33 = OpSLessThan %32 %59 %31
|
||||
OpLoopMerge %21 %20 None
|
||||
OpBranchConditional %33 %20 %21
|
||||
%20 = OpLabel
|
||||
%39 = OpCompositeExtract %6 %60 0
|
||||
%40 = OpFAdd %6 %39 %34
|
||||
%55 = OpCompositeInsert %7 %40 %60 0
|
||||
%44 = OpCompositeExtract %6 %60 1
|
||||
%45 = OpFSub %6 %44 %34
|
||||
%58 = OpCompositeInsert %7 %45 %55 1
|
||||
%49 = OpIAdd %15 %59 %48
|
||||
OpBranch %19
|
||||
%21 = OpLabel
|
||||
OpStore %51 %60
|
||||
OpSelectionMerge %105 None
|
||||
OpBranchConditional %103 %104 %105
|
||||
%104 = OpLabel
|
||||
OpBranch %105
|
||||
%105 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_4;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
|
||||
// Cannot insert before the OpVariables of a function.
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
// OK to insert right after the OpVariables.
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Cannot insert before the OpPhis of a block.
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
// OK to insert after the OpPhis.
|
||||
ASSERT_TRUE(
|
||||
TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Cannot insert before OpLoopMerge
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
|
||||
200, 14, {3})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Cannot insert before OpSelectionMerge
|
||||
ASSERT_FALSE(TransformationCompositeExtract(
|
||||
MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
|
||||
200, 14, {2})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
126
3rdparty/spirv-tools/test/opt/fold_test.cpp
vendored
126
3rdparty/spirv-tools/test/opt/fold_test.cpp
vendored
@@ -5763,6 +5763,132 @@ INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
|
||||
4, true)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
|
||||
::testing::Values(
|
||||
// Test case 0: merge of add of sub
|
||||
// (a - b) + b => a
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: %6 = OpCopyObject [[float]] %3\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%3 = OpLoad %float %var0\n" +
|
||||
"%4 = OpLoad %float %var1\n" +
|
||||
"%5 = OpFSub %float %3 %4\n" +
|
||||
"%6 = OpFAdd %float %5 %4\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
6, true),
|
||||
// Test case 1: merge of add of sub
|
||||
// b + (a - b) => a
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: %6 = OpCopyObject [[float]] %3\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%3 = OpLoad %float %var0\n" +
|
||||
"%4 = OpLoad %float %var1\n" +
|
||||
"%5 = OpFSub %float %3 %4\n" +
|
||||
"%6 = OpFAdd %float %4 %5\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
6, true)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
|
||||
::testing::Values(
|
||||
// Test case 0: factor of add of muls
|
||||
// (a * b) + (a * c) => a * (b + c)
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
|
||||
"; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%var2 = OpVariable %_ptr_float Function\n" +
|
||||
"%4 = OpLoad %float %var0\n" +
|
||||
"%5 = OpLoad %float %var1\n" +
|
||||
"%6 = OpLoad %float %var2\n" +
|
||||
"%7 = OpFMul %float %6 %4\n" +
|
||||
"%8 = OpFMul %float %6 %5\n" +
|
||||
"%9 = OpFAdd %float %7 %8\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true),
|
||||
// Test case 1: factor of add of muls
|
||||
// (b * a) + (a * c) => a * (b + c)
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
|
||||
"; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%var2 = OpVariable %_ptr_float Function\n" +
|
||||
"%4 = OpLoad %float %var0\n" +
|
||||
"%5 = OpLoad %float %var1\n" +
|
||||
"%6 = OpLoad %float %var2\n" +
|
||||
"%7 = OpFMul %float %4 %6\n" +
|
||||
"%8 = OpFMul %float %6 %5\n" +
|
||||
"%9 = OpFAdd %float %7 %8\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true),
|
||||
// Test case 2: factor of add of muls
|
||||
// (a * b) + (c * a) => a * (b + c)
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
|
||||
"; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%var2 = OpVariable %_ptr_float Function\n" +
|
||||
"%4 = OpLoad %float %var0\n" +
|
||||
"%5 = OpLoad %float %var1\n" +
|
||||
"%6 = OpLoad %float %var2\n" +
|
||||
"%7 = OpFMul %float %6 %4\n" +
|
||||
"%8 = OpFMul %float %5 %6\n" +
|
||||
"%9 = OpFAdd %float %7 %8\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true),
|
||||
// Test case 3: factor of add of muls
|
||||
// (b * a) + (c * a) => a * (b + c)
|
||||
InstructionFoldingCase<bool>(
|
||||
Header() +
|
||||
"; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
|
||||
"; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
|
||||
"; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
|
||||
"%main = OpFunction %void None %void_func\n" +
|
||||
"%main_lab = OpLabel\n" +
|
||||
"%var0 = OpVariable %_ptr_float Function\n" +
|
||||
"%var1 = OpVariable %_ptr_float Function\n" +
|
||||
"%var2 = OpVariable %_ptr_float Function\n" +
|
||||
"%4 = OpLoad %float %var0\n" +
|
||||
"%5 = OpLoad %float %var1\n" +
|
||||
"%6 = OpLoad %float %var2\n" +
|
||||
"%7 = OpFMul %float %4 %6\n" +
|
||||
"%8 = OpFMul %float %5 %6\n" +
|
||||
"%9 = OpFAdd %float %7 %8\n" +
|
||||
"OpReturn\n" +
|
||||
"OpFunctionEnd\n",
|
||||
9, true)
|
||||
));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
|
||||
::testing::Values(
|
||||
// Test case 0: merge sub of negate
|
||||
|
||||
@@ -71,6 +71,41 @@ TEST_F(SimplificationTest, StraightLineTest) {
|
||||
SinglePassRunAndMatch<SimplificationPass>(text, false);
|
||||
}
|
||||
|
||||
TEST_F(SimplificationTest, NewInstructionTest) {
|
||||
// Testing that new instructions are simplified. Specifically,
|
||||
// that the new add instruction generated by FactorAddMul is
|
||||
// further simplified by MergeGenericAddSub.
|
||||
const std::string text = R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 430
|
||||
OpName %main "main"
|
||||
%void = OpTypeVoid
|
||||
%4 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_int = OpTypePointer Function %int
|
||||
; CHECK: [[mul:%[a-zA-Z_\d]+]] = OpIMul %int %13 %11
|
||||
%main = OpFunction %void None %4
|
||||
%7 = OpLabel
|
||||
%8 = OpVariable %_ptr_int Function
|
||||
%9 = OpVariable %_ptr_int Function
|
||||
%10 = OpVariable %_ptr_int Function
|
||||
%11 = OpLoad %int %8
|
||||
%12 = OpLoad %int %9
|
||||
%13 = OpLoad %int %10
|
||||
%14 = OpISub %int %11 %12
|
||||
%15 = OpIMul %int %13 %11
|
||||
%16 = OpIMul %int %13 %12
|
||||
%17 = OpIAdd %int %14 %15
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndMatch<SimplificationPass>(text, false);
|
||||
}
|
||||
|
||||
TEST_F(SimplificationTest, AcrossBasicBlocks) {
|
||||
// Testing that folding rules are combined across basic blocks.
|
||||
const std::string text = R"(OpCapability Shader
|
||||
|
||||
1
3rdparty/spirv-tools/utils/vscode/.gitignore
vendored
Normal file
1
3rdparty/spirv-tools/utils/vscode/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cache/
|
||||
7
3rdparty/spirv-tools/utils/vscode/README.md
vendored
Normal file
7
3rdparty/spirv-tools/utils/vscode/README.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Visual Studio Code extension for SPIR-V disassembly files
|
||||
|
||||
This directory holds a Visual Studio Code extension adding syntax highlighting for SPIR-V disassembly files (.spirv)
|
||||
|
||||
## Installing (macOS / Linux)
|
||||
|
||||
Simply run `install.sh`
|
||||
26
3rdparty/spirv-tools/utils/vscode/install.sh
vendored
Executable file
26
3rdparty/spirv-tools/utils/vscode/install.sh
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2019 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -e # Fail on any error.
|
||||
|
||||
EXT_PATH=~/.vscode/extensions/google.spirvls-0.0.1
|
||||
ROOT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
go run ${ROOT_PATH}/src/tools/gen-grammar.go --cache ${ROOT_PATH}/cache --template ${ROOT_PATH}/spirv.json.tmpl --out ${ROOT_PATH}/spirv.json
|
||||
|
||||
mkdir -p ${EXT_PATH}
|
||||
cp ${ROOT_PATH}/package.json ${EXT_PATH}
|
||||
cp ${ROOT_PATH}/spirv.configuration.json ${EXT_PATH}
|
||||
cp ${ROOT_PATH}/spirv.json ${EXT_PATH}
|
||||
33
3rdparty/spirv-tools/utils/vscode/package.json
vendored
Normal file
33
3rdparty/spirv-tools/utils/vscode/package.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "spirv",
|
||||
"description": "Language support for SPIR-V disassembly files",
|
||||
"author": "Google",
|
||||
"license": "Apache-2.0",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"publisher": "Google",
|
||||
"engines": {
|
||||
"vscode": "^0.10.10"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"contributes": {
|
||||
"languages": [
|
||||
{
|
||||
"id": "spirv",
|
||||
"configuration": "spirv.configuration.json",
|
||||
"extensions": [
|
||||
"spirv"
|
||||
]
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "spirv",
|
||||
"scopeName": "source.spirv",
|
||||
"path": "spirv.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
6
3rdparty/spirv-tools/utils/vscode/spirv.configuration.json
vendored
Normal file
6
3rdparty/spirv-tools/utils/vscode/spirv.configuration.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": ";"
|
||||
},
|
||||
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)"
|
||||
}
|
||||
212
3rdparty/spirv-tools/utils/vscode/spirv.json
vendored
Normal file
212
3rdparty/spirv-tools/utils/vscode/spirv.json
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"scopeName": "source.spirv",
|
||||
"name": "SPIR-V",
|
||||
"comment": "Generated by gen-grammar.go --template=../../spirv.json.tmpl --out=../../spirv.json. Do not modify this file directly.",
|
||||
"patterns": [
|
||||
{ "include": "#BitEnum_ImageOperands" },
|
||||
{ "include": "#BitEnum_FPFastMathMode" },
|
||||
{ "include": "#BitEnum_SelectionControl" },
|
||||
{ "include": "#BitEnum_LoopControl" },
|
||||
{ "include": "#BitEnum_FunctionControl" },
|
||||
{ "include": "#BitEnum_MemorySemantics" },
|
||||
{ "include": "#BitEnum_MemoryAccess" },
|
||||
{ "include": "#BitEnum_KernelProfilingInfo" },
|
||||
{ "include": "#ValueEnum_SourceLanguage" },
|
||||
{ "include": "#ValueEnum_ExecutionModel" },
|
||||
{ "include": "#ValueEnum_AddressingModel" },
|
||||
{ "include": "#ValueEnum_MemoryModel" },
|
||||
{ "include": "#ValueEnum_ExecutionMode" },
|
||||
{ "include": "#ValueEnum_StorageClass" },
|
||||
{ "include": "#ValueEnum_Dim" },
|
||||
{ "include": "#ValueEnum_SamplerAddressingMode" },
|
||||
{ "include": "#ValueEnum_SamplerFilterMode" },
|
||||
{ "include": "#ValueEnum_ImageFormat" },
|
||||
{ "include": "#ValueEnum_ImageChannelOrder" },
|
||||
{ "include": "#ValueEnum_ImageChannelDataType" },
|
||||
{ "include": "#ValueEnum_FPRoundingMode" },
|
||||
{ "include": "#ValueEnum_LinkageType" },
|
||||
{ "include": "#ValueEnum_AccessQualifier" },
|
||||
{ "include": "#ValueEnum_FunctionParameterAttribute" },
|
||||
{ "include": "#ValueEnum_Decoration" },
|
||||
{ "include": "#ValueEnum_BuiltIn" },
|
||||
{ "include": "#ValueEnum_Scope" },
|
||||
{ "include": "#ValueEnum_GroupOperation" },
|
||||
{ "include": "#ValueEnum_KernelEnqueueFlags" },
|
||||
{ "include": "#ValueEnum_Capability" },
|
||||
{ "include": "#opcode" },
|
||||
{ "include": "#identifier" },
|
||||
{ "include": "#number" },
|
||||
{ "include": "#string" },
|
||||
{ "include": "#comment" },
|
||||
{ "include": "#operator" }
|
||||
],
|
||||
"repository": {
|
||||
"BitEnum_ImageOperands": {
|
||||
"match": "\\b(None|Bias|Lod|Grad|ConstOffset|Offset|ConstOffsets|Sample|MinLod|MakeTexelAvailable|MakeTexelAvailableKHR|MakeTexelVisible|MakeTexelVisibleKHR|NonPrivateTexel|NonPrivateTexelKHR|VolatileTexel|VolatileTexelKHR|SignExtend|ZeroExtend)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_FPFastMathMode": {
|
||||
"match": "\\b(None|NotNaN|NotInf|NSZ|AllowRecip|Fast)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_SelectionControl": {
|
||||
"match": "\\b(None|Flatten|DontFlatten)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_LoopControl": {
|
||||
"match": "\\b(None|Unroll|DontUnroll|DependencyInfinite|DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_FunctionControl": {
|
||||
"match": "\\b(None|Inline|DontInline|Pure|Const)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_MemorySemantics": {
|
||||
"match": "\\b(Relaxed|None|Acquire|Release|AcquireRelease|SequentiallyConsistent|UniformMemory|SubgroupMemory|WorkgroupMemory|CrossWorkgroupMemory|AtomicCounterMemory|ImageMemory|OutputMemory|OutputMemoryKHR|MakeAvailable|MakeAvailableKHR|MakeVisible|MakeVisibleKHR|Volatile)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_MemoryAccess": {
|
||||
"match": "\\b(None|Volatile|Aligned|Nontemporal|MakePointerAvailable|MakePointerAvailableKHR|MakePointerVisible|MakePointerVisibleKHR|NonPrivatePointer|NonPrivatePointerKHR)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"BitEnum_KernelProfilingInfo": {
|
||||
"match": "\\b(None|CmdExecTime)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_SourceLanguage": {
|
||||
"match": "\\b(Unknown|ESSL|GLSL|OpenCL_C|OpenCL_CPP|HLSL)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_ExecutionModel": {
|
||||
"match": "\\b(Vertex|TessellationControl|TessellationEvaluation|Geometry|Fragment|GLCompute|Kernel|TaskNV|MeshNV|RayGenerationNV|IntersectionNV|AnyHitNV|ClosestHitNV|MissNV|CallableNV)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_AddressingModel": {
|
||||
"match": "\\b(Logical|Physical32|Physical64|PhysicalStorageBuffer64|PhysicalStorageBuffer64EXT)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_MemoryModel": {
|
||||
"match": "\\b(Simple|GLSL450|OpenCL|Vulkan|VulkanKHR)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_ExecutionMode": {
|
||||
"match": "\\b(Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|StencilRefReplacingEXT|OutputLinesNV|OutputPrimitivesNV|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesNV|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_StorageClass": {
|
||||
"match": "\\b(UniformConstant|Input|Uniform|Output|Workgroup|CrossWorkgroup|Private|Function|Generic|PushConstant|AtomicCounter|Image|StorageBuffer|CallableDataNV|IncomingCallableDataNV|RayPayloadNV|HitAttributeNV|IncomingRayPayloadNV|ShaderRecordBufferNV|PhysicalStorageBuffer|PhysicalStorageBufferEXT)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_Dim": {
|
||||
"match": "\\b(1D|2D|3D|Cube|Rect|Buffer|SubpassData)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_SamplerAddressingMode": {
|
||||
"match": "\\b(None|ClampToEdge|Clamp|Repeat|RepeatMirrored)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_SamplerFilterMode": {
|
||||
"match": "\\b(Nearest|Linear)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_ImageFormat": {
|
||||
"match": "\\b(Unknown|Rgba32f|Rgba16f|R32f|Rgba8|Rgba8Snorm|Rg32f|Rg16f|R11fG11fB10f|R16f|Rgba16|Rgb10A2|Rg16|Rg8|R16|R8|Rgba16Snorm|Rg16Snorm|Rg8Snorm|R16Snorm|R8Snorm|Rgba32i|Rgba16i|Rgba8i|R32i|Rg32i|Rg16i|Rg8i|R16i|R8i|Rgba32ui|Rgba16ui|Rgba8ui|R32ui|Rgb10a2ui|Rg32ui|Rg16ui|Rg8ui|R16ui|R8ui)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_ImageChannelOrder": {
|
||||
"match": "\\b(R|A|RG|RA|RGB|RGBA|BGRA|ARGB|Intensity|Luminance|Rx|RGx|RGBx|Depth|DepthStencil|sRGB|sRGBx|sRGBA|sBGRA|ABGR)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_ImageChannelDataType": {
|
||||
"match": "\\b(SnormInt8|SnormInt16|UnormInt8|UnormInt16|UnormShort565|UnormShort555|UnormInt101010|SignedInt8|SignedInt16|SignedInt32|UnsignedInt8|UnsignedInt16|UnsignedInt32|HalfFloat|Float|UnormInt24|UnormInt101010_2)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_FPRoundingMode": {
|
||||
"match": "\\b(RTE|RTZ|RTP|RTN)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_LinkageType": {
|
||||
"match": "\\b(Export|Import)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_AccessQualifier": {
|
||||
"match": "\\b(ReadOnly|WriteOnly|ReadWrite)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_FunctionParameterAttribute": {
|
||||
"match": "\\b(Zext|Sext|ByVal|Sret|NoAlias|NoCapture|NoWrite|NoReadWrite)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_Decoration": {
|
||||
"match": "\\b(RelaxedPrecision|SpecId|Block|BufferBlock|RowMajor|ColMajor|ArrayStride|MatrixStride|GLSLShared|GLSLPacked|CPacked|BuiltIn|NoPerspective|Flat|Patch|Centroid|Sample|Invariant|Restrict|Aliased|Volatile|Constant|Coherent|NonWritable|NonReadable|Uniform|UniformId|SaturatedConversion|Stream|Location|Component|Index|Binding|DescriptorSet|Offset|XfbBuffer|XfbStride|FuncParamAttr|FPRoundingMode|FPFastMathMode|LinkageAttributes|NoContraction|InputAttachmentIndex|Alignment|MaxByteOffset|AlignmentId|MaxByteOffsetId|NoSignedWrap|NoUnsignedWrap|ExplicitInterpAMD|OverrideCoverageNV|PassthroughNV|ViewportRelativeNV|SecondaryViewportRelativeNV|PerPrimitiveNV|PerViewNV|PerTaskNV|PerVertexNV|NonUniform|NonUniformEXT|RestrictPointer|RestrictPointerEXT|AliasedPointer|AliasedPointerEXT|CounterBuffer|HlslCounterBufferGOOGLE|UserSemantic|HlslSemanticGOOGLE|UserTypeGOOGLE)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_BuiltIn": {
|
||||
"match": "\\b(Position|PointSize|ClipDistance|CullDistance|VertexId|InstanceId|PrimitiveId|InvocationId|Layer|ViewportIndex|TessLevelOuter|TessLevelInner|TessCoord|PatchVertices|FragCoord|PointCoord|FrontFacing|SampleId|SamplePosition|SampleMask|FragDepth|HelperInvocation|NumWorkgroups|WorkgroupSize|WorkgroupId|LocalInvocationId|GlobalInvocationId|LocalInvocationIndex|WorkDim|GlobalSize|EnqueuedWorkgroupSize|GlobalOffset|GlobalLinearId|SubgroupSize|SubgroupMaxSize|NumSubgroups|NumEnqueuedSubgroups|SubgroupId|SubgroupLocalInvocationId|VertexIndex|InstanceIndex|SubgroupEqMask|SubgroupGeMask|SubgroupGtMask|SubgroupLeMask|SubgroupLtMask|SubgroupEqMaskKHR|SubgroupGeMaskKHR|SubgroupGtMaskKHR|SubgroupLeMaskKHR|SubgroupLtMaskKHR|BaseVertex|BaseInstance|DrawIndex|DeviceIndex|ViewIndex|BaryCoordNoPerspAMD|BaryCoordNoPerspCentroidAMD|BaryCoordNoPerspSampleAMD|BaryCoordSmoothAMD|BaryCoordSmoothCentroidAMD|BaryCoordSmoothSampleAMD|BaryCoordPullModelAMD|FragStencilRefEXT|ViewportMaskNV|SecondaryPositionNV|SecondaryViewportMaskNV|PositionPerViewNV|ViewportMaskPerViewNV|FullyCoveredEXT|TaskCountNV|PrimitiveCountNV|PrimitiveIndicesNV|ClipDistancePerViewNV|CullDistancePerViewNV|LayerPerViewNV|MeshViewCountNV|MeshViewIndicesNV|BaryCoordNV|BaryCoordNoPerspNV|FragSizeEXT|FragmentSizeNV|FragInvocationCountEXT|InvocationsPerPixelNV|LaunchIdNV|LaunchSizeNV|WorldRayOriginNV|WorldRayDirectionNV|ObjectRayOriginNV|ObjectRayDirectionNV|RayTminNV|RayTmaxNV|InstanceCustomIndexNV|ObjectToWorldNV|WorldToObjectNV|HitTNV|HitKindNV|IncomingRayFlagsNV|WarpsPerSMNV|SMCountNV|WarpIDNV|SMIDNV)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_Scope": {
|
||||
"match": "\\b(CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|QueueFamilyKHR)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_GroupOperation": {
|
||||
"match": "\\b(Reduce|InclusiveScan|ExclusiveScan|ClusteredReduce|PartitionedReduceNV|PartitionedInclusiveScanNV|PartitionedExclusiveScanNV)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_KernelEnqueueFlags": {
|
||||
"match": "\\b(NoWait|WaitKernel|WaitWorkGroup)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"ValueEnum_Capability": {
|
||||
"match": "\\b(Matrix|Shader|Geometry|Tessellation|Addresses|Linkage|Kernel|Vector16|Float16Buffer|Float16|Float64|Int64|Int64Atomics|ImageBasic|ImageReadWrite|ImageMipmap|Pipes|Groups|DeviceEnqueue|LiteralSampler|AtomicStorage|Int16|TessellationPointSize|GeometryPointSize|ImageGatherExtended|StorageImageMultisample|UniformBufferArrayDynamicIndexing|SampledImageArrayDynamicIndexing|StorageBufferArrayDynamicIndexing|StorageImageArrayDynamicIndexing|ClipDistance|CullDistance|ImageCubeArray|SampleRateShading|ImageRect|SampledRect|GenericPointer|Int8|InputAttachment|SparseResidency|MinLod|Sampled1D|Image1D|SampledCubeArray|SampledBuffer|ImageBuffer|ImageMSArray|StorageImageExtendedFormats|ImageQuery|DerivativeControl|InterpolationFunction|TransformFeedback|GeometryStreams|StorageImageReadWithoutFormat|StorageImageWriteWithoutFormat|MultiViewport|SubgroupDispatch|NamedBarrier|PipeStorage|GroupNonUniform|GroupNonUniformVote|GroupNonUniformArithmetic|GroupNonUniformBallot|GroupNonUniformShuffle|GroupNonUniformShuffleRelative|GroupNonUniformClustered|GroupNonUniformQuad|ShaderLayer|ShaderViewportIndex|SubgroupBallotKHR|DrawParameters|SubgroupVoteKHR|StorageBuffer16BitAccess|StorageUniformBufferBlock16|UniformAndStorageBuffer16BitAccess|StorageUniform16|StoragePushConstant16|StorageInputOutput16|DeviceGroup|MultiView|VariablePointersStorageBuffer|VariablePointers|AtomicStorageOps|SampleMaskPostDepthCoverage|StorageBuffer8BitAccess|UniformAndStorageBuffer8BitAccess|StoragePushConstant8|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|Float16ImageAMD|ImageGatherBiasLodAMD|FragmentMaskAMD|StencilExportEXT|ImageReadWriteLodAMD|ShaderClockKHR|SampleMaskOverrideCoverageNV|GeometryShaderPassthroughNV|ShaderViewportIndexLayerEXT|ShaderViewportIndexLayerNV|ShaderViewportMaskNV|ShaderStereoViewNV|PerViewAttributesNV|FragmentFullyCoveredEXT|MeshShadingNV|ImageFootprintNV|FragmentBarycentricNV|ComputeDerivativeGroupQuadsNV|FragmentDensityEXT|ShadingRateNV|GroupNonUniformPartitionedNV|ShaderNonUniform|ShaderNonUniformEXT|RuntimeDescriptorArray|RuntimeDescriptorArrayEXT|InputAttachmentArrayDynamicIndexing|InputAttachmentArrayDynamicIndexingEXT|UniformTexelBufferArrayDynamicIndexing|UniformTexelBufferArrayDynamicIndexingEXT|StorageTexelBufferArrayDynamicIndexing|StorageTexelBufferArrayDynamicIndexingEXT|UniformBufferArrayNonUniformIndexing|UniformBufferArrayNonUniformIndexingEXT|SampledImageArrayNonUniformIndexing|SampledImageArrayNonUniformIndexingEXT|StorageBufferArrayNonUniformIndexing|StorageBufferArrayNonUniformIndexingEXT|StorageImageArrayNonUniformIndexing|StorageImageArrayNonUniformIndexingEXT|InputAttachmentArrayNonUniformIndexing|InputAttachmentArrayNonUniformIndexingEXT|UniformTexelBufferArrayNonUniformIndexing|UniformTexelBufferArrayNonUniformIndexingEXT|StorageTexelBufferArrayNonUniformIndexing|StorageTexelBufferArrayNonUniformIndexingEXT|RayTracingNV|VulkanMemoryModel|VulkanMemoryModelKHR|VulkanMemoryModelDeviceScope|VulkanMemoryModelDeviceScopeKHR|PhysicalStorageBufferAddresses|PhysicalStorageBufferAddressesEXT|ComputeDerivativeGroupLinearNV|CooperativeMatrixNV|FragmentShaderSampleInterlockEXT|FragmentShaderShadingRateInterlockEXT|ShaderSMBuiltinsNV|FragmentShaderPixelInterlockEXT|DemoteToHelperInvocationEXT|SubgroupShuffleINTEL|SubgroupBufferBlockIOINTEL|SubgroupImageBlockIOINTEL|SubgroupImageMediaBlockIOINTEL|IntegerFunctions2INTEL|SubgroupAvcMotionEstimationINTEL|SubgroupAvcMotionEstimationIntraINTEL|SubgroupAvcMotionEstimationChromaINTEL)\\b",
|
||||
"name": "keyword.spirv"
|
||||
},
|
||||
"opcode": {
|
||||
"match": "(Op[a-zA-Z]+)",
|
||||
"name": "entity.name.function.spirv"
|
||||
},
|
||||
"identifier": {
|
||||
"match": "%[a-zA-Z0-9_]+",
|
||||
"name": "variable.spirv"
|
||||
},
|
||||
"number": {
|
||||
"match": "\\b[0-9]+.?[0-9]*\\b",
|
||||
"name": "constant.numeric.spirv"
|
||||
},
|
||||
"comment": {
|
||||
"match": ";[^\n]*",
|
||||
"name": "comment.line.spirv"
|
||||
},
|
||||
"operator": {
|
||||
"match": "=",
|
||||
"name": "keyword.operator.spirv"
|
||||
},
|
||||
"string": {
|
||||
"begin": "\"",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.spirv"
|
||||
}
|
||||
},
|
||||
"end": "\"",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.end.spirv"
|
||||
}
|
||||
},
|
||||
"name": "string.quoted.double.spirv",
|
||||
"patterns": [ { "include": "#string_escaped_char" } ]
|
||||
},
|
||||
"string_escaped_char": {
|
||||
"patterns": [
|
||||
{
|
||||
"match": "\\\\([0-7]{3}|[abfnrtv\\\\'\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})",
|
||||
"name": "constant.character.escape.spirv"
|
||||
}, {
|
||||
"match": "\\\\[^0-7xuUabfnrtv\\'\"]",
|
||||
"name": "invalid.illegal.unknown-escape.spirv"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
67
3rdparty/spirv-tools/utils/vscode/spirv.json.tmpl
vendored
Normal file
67
3rdparty/spirv-tools/utils/vscode/spirv.json.tmpl
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"scopeName": "source.spirv",
|
||||
"name": "SPIR-V",
|
||||
"comment": "Generated by {{GenerateArguments}}. Do not modify this file directly.",
|
||||
"patterns": [
|
||||
{{range $o := .OperandKinds}}{{if len $o.Enumerants}} { "include": "#{{$o.Category}}_{{$o.Kind}}" },
|
||||
{{end}}{{end}} { "include": "#opcode" },
|
||||
{ "include": "#identifier" },
|
||||
{ "include": "#number" },
|
||||
{ "include": "#string" },
|
||||
{ "include": "#comment" },
|
||||
{ "include": "#operator" }
|
||||
],
|
||||
"repository": { {{range $o := .OperandKinds}}{{if len $o.Enumerants}}
|
||||
"{{$o.Category}}_{{$o.Kind}}": {
|
||||
"match": "\\b({{OperandKindsMatch $o}})\\b",
|
||||
"name": "keyword.spirv"
|
||||
},{{end}}{{end}}
|
||||
"opcode": {
|
||||
"match": "(Op[a-zA-Z]+)",
|
||||
"name": "entity.name.function.spirv"
|
||||
},
|
||||
"identifier": {
|
||||
"match": "%[a-zA-Z0-9_]+",
|
||||
"name": "variable.spirv"
|
||||
},
|
||||
"number": {
|
||||
"match": "\\b[0-9]+.?[0-9]*\\b",
|
||||
"name": "constant.numeric.spirv"
|
||||
},
|
||||
"comment": {
|
||||
"match": ";[^\n]*",
|
||||
"name": "comment.line.spirv"
|
||||
},
|
||||
"operator": {
|
||||
"match": "=",
|
||||
"name": "keyword.operator.spirv"
|
||||
},
|
||||
"string": {
|
||||
"begin": "\"",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.spirv"
|
||||
}
|
||||
},
|
||||
"end": "\"",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.end.spirv"
|
||||
}
|
||||
},
|
||||
"name": "string.quoted.double.spirv",
|
||||
"patterns": [ { "include": "#string_escaped_char" } ]
|
||||
},
|
||||
"string_escaped_char": {
|
||||
"patterns": [
|
||||
{
|
||||
"match": "\\\\([0-7]{3}|[abfnrtv\\\\'\"]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})",
|
||||
"name": "constant.character.escape.spirv"
|
||||
}, {
|
||||
"match": "\\\\[^0-7xuUabfnrtv\\'\"]",
|
||||
"name": "invalid.illegal.unknown-escape.spirv"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
75
3rdparty/spirv-tools/utils/vscode/src/grammar/grammar.go
vendored
Normal file
75
3rdparty/spirv-tools/utils/vscode/src/grammar/grammar.go
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2019 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package grammar holds the JSON type definitions for the SPIR-V grammar schema.
|
||||
//
|
||||
// See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html
|
||||
// for more information.
|
||||
package grammar
|
||||
|
||||
// Root is the top-level structure of the JSON grammar.
|
||||
type Root struct {
|
||||
MagicNumber string `json:"magic_number"`
|
||||
MajorVersion int `json:"major_version"`
|
||||
MinorVersion int `json:"minor_version"`
|
||||
Revision int `json:"revision"`
|
||||
Instructions []Instruction `json:"instructions"`
|
||||
OperandKinds []OperandKind `json:"operand_kinds"`
|
||||
}
|
||||
|
||||
// Instruction holds information about a specific SPIR-V instruction.
|
||||
type Instruction struct {
|
||||
Opname string `json:"opname"`
|
||||
Class string `json:"class"`
|
||||
Opcode int `json:"opcode"`
|
||||
Operands []Operand `json:"operands"`
|
||||
}
|
||||
|
||||
// Operand contains information about a logical operand for an instruction.
|
||||
type Operand struct {
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
Quantifier Quantifier `json:"quantifier"`
|
||||
}
|
||||
|
||||
// OperandKind contains information about a specific operand kind.
|
||||
type OperandKind struct {
|
||||
Category string `json:"category"`
|
||||
Kind string `json:"kind"`
|
||||
Enumerants []Enumerant `json:"enumerants"`
|
||||
Bases []string `json:"bases"`
|
||||
}
|
||||
|
||||
// Enumerant contains information about an enumerant in an enum.
|
||||
type Enumerant struct {
|
||||
Enumerant string `json:"enumerant"`
|
||||
Value interface{} `json:"value"`
|
||||
Capabilities []string `json:"capabilities"`
|
||||
Parameters []Parameter `json:"parameters"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// Parameter contains information about a logical parameter for an enumerant.
|
||||
type Parameter struct {
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Quantifier string
|
||||
|
||||
const (
|
||||
Once Quantifier = ""
|
||||
ZeroOrOnce Quantifier = "?"
|
||||
ZeroOrMany Quantifier = "*"
|
||||
)
|
||||
167
3rdparty/spirv-tools/utils/vscode/src/tools/gen-grammar.go
vendored
Normal file
167
3rdparty/spirv-tools/utils/vscode/src/tools/gen-grammar.go
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) 2019 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// gen-grammar generates the spirv.json grammar file from the official SPIR-V
|
||||
// grammar JSON file.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"../grammar"
|
||||
)
|
||||
|
||||
const (
|
||||
spirvGrammarURL = "https://raw.githubusercontent.com/KhronosGroup/SPIRV-Headers/master/include/spirv/unified1/spirv.core.grammar.json"
|
||||
spirvGrammarName = "spirv.core.grammar.json"
|
||||
)
|
||||
|
||||
var (
|
||||
templatePath = flag.String("template", "", "Path to input template file (required)")
|
||||
outputPath = flag.String("out", "", "Path to output generated file (required)")
|
||||
cachePath = flag.String("cache", "", "Cache directory for downloaded files (optional)")
|
||||
|
||||
thisDir = func() string {
|
||||
_, file, _, _ := runtime.Caller(1)
|
||||
return filepath.Dir(file)
|
||||
}()
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *templatePath == "" || *outputPath == "" {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := run(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
tf, err := ioutil.ReadFile(*templatePath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Could not open template file")
|
||||
}
|
||||
t, err := template.New("tmpl").
|
||||
Funcs(template.FuncMap{
|
||||
"GenerateArguments": func() string {
|
||||
relPath := func(path string) string {
|
||||
rel, err := filepath.Rel(thisDir, path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
return rel
|
||||
}
|
||||
args := []string{
|
||||
"--template=" + relPath(*templatePath),
|
||||
"--out=" + relPath(*outputPath),
|
||||
}
|
||||
return "gen-grammar.go " + strings.Join(args, " ")
|
||||
},
|
||||
"OperandKindsMatch": func(k grammar.OperandKind) string {
|
||||
sb := strings.Builder{}
|
||||
for i, e := range k.Enumerants {
|
||||
if i > 0 {
|
||||
sb.WriteString("|")
|
||||
}
|
||||
sb.WriteString(e.Enumerant)
|
||||
}
|
||||
return sb.String()
|
||||
},
|
||||
}).Parse(string(tf))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to parse template")
|
||||
}
|
||||
|
||||
file, err := getOrDownload(spirvGrammarName, spirvGrammarURL)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to load grammar file")
|
||||
}
|
||||
|
||||
g := grammar.Root{}
|
||||
if err := json.NewDecoder(bytes.NewReader(file)).Decode(&g); err != nil {
|
||||
return errors.Wrap(err, "Failed to parse grammar file")
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
if err := t.Execute(&buf, g); err != nil {
|
||||
return errors.Wrap(err, "Failed to execute template")
|
||||
}
|
||||
|
||||
out := buf.String()
|
||||
out = strings.ReplaceAll(out, "•", "")
|
||||
|
||||
if err := ioutil.WriteFile(*outputPath, []byte(out), 0777); err != nil {
|
||||
return errors.Wrap(err, "Failed to write output file")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getOrDownload loads the specific file from the cache, or downloads the file
|
||||
// from the given url.
|
||||
func getOrDownload(name, url string) ([]byte, error) {
|
||||
if *cachePath != "" {
|
||||
if err := os.MkdirAll(*cachePath, 0777); err == nil {
|
||||
path := filepath.Join(*cachePath, name)
|
||||
if isFile(path) {
|
||||
return ioutil.ReadFile(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if *cachePath != "" {
|
||||
ioutil.WriteFile(filepath.Join(*cachePath, name), data, 0777)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// isFile returns true if path is a file.
|
||||
func isFile(path string) bool {
|
||||
s, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return !s.IsDir()
|
||||
}
|
||||
|
||||
// isDir returns true if path is a directory.
|
||||
func isDir(path string) bool {
|
||||
s, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return s.IsDir()
|
||||
}
|
||||
Reference in New Issue
Block a user