2019-05-27 13:34:55 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
// This file is specifically named spvtools_fuzz.proto so that the string
|
|
|
|
// 'spvtools_fuzz' appears in the names of global-scope symbols that protoc
|
|
|
|
// generates when targeting C++. This is to reduce the potential for name
|
|
|
|
// clashes with other globally-scoped symbols.
|
|
|
|
|
|
|
|
syntax = "proto3";
|
|
|
|
|
|
|
|
package spvtools.fuzz.protobufs;
|
|
|
|
|
2019-12-10 14:47:42 +00:00
|
|
|
message UInt32Pair {
|
|
|
|
|
|
|
|
// A pair of uint32s; useful for defining mappings.
|
|
|
|
|
|
|
|
uint32 first = 1;
|
|
|
|
|
|
|
|
uint32 second = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-11 09:13:06 +00:00
|
|
|
message InstructionDescriptor {
|
|
|
|
|
|
|
|
// Describes an instruction in some block of a function with respect to a
|
|
|
|
// base instruction.
|
|
|
|
|
|
|
|
// The id of an instruction after which the instruction being described is
|
|
|
|
// believed to be located. It might be the using instruction itself.
|
|
|
|
uint32 base_instruction_result_id = 1;
|
|
|
|
|
|
|
|
// The opcode for the instruction being described.
|
|
|
|
uint32 target_instruction_opcode = 2;
|
|
|
|
|
|
|
|
// The number of matching opcodes to skip over when searching from the base
|
|
|
|
// instruction to the instruction being described.
|
|
|
|
uint32 num_opcodes_to_ignore = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-06 21:22:35 +00:00
|
|
|
message IdUseDescriptor {
|
|
|
|
|
2019-10-10 12:34:38 +00:00
|
|
|
// Describes a use of an id as an input operand to an instruction in some
|
|
|
|
// block of a function.
|
2019-06-06 21:22:35 +00:00
|
|
|
|
|
|
|
// Example:
|
|
|
|
// - id_of_interest = 42
|
2019-10-11 09:13:06 +00:00
|
|
|
// - enclosing_instruction = (
|
|
|
|
// base_instruction_result_id = 50,
|
|
|
|
// target_instruction_opcode = OpStore
|
|
|
|
// num_opcodes_to_ignore = 7
|
|
|
|
// )
|
2019-06-06 21:22:35 +00:00
|
|
|
// - in_operand_index = 1
|
|
|
|
// represents a use of id 42 as input operand 1 to an OpStore instruction,
|
|
|
|
// such that the OpStore instruction can be found in the same basic block as
|
|
|
|
// the instruction with result id 50, and in particular is the 8th OpStore
|
|
|
|
// instruction found from instruction 50 onwards (i.e. 7 OpStore
|
|
|
|
// instructions are skipped).
|
|
|
|
|
|
|
|
// An id that we would like to be able to find a use of.
|
|
|
|
uint32 id_of_interest = 1;
|
|
|
|
|
|
|
|
// The input operand index at which the use is expected.
|
2019-10-11 09:13:06 +00:00
|
|
|
InstructionDescriptor enclosing_instruction = 2;
|
2019-06-06 21:22:35 +00:00
|
|
|
|
2019-10-11 09:13:06 +00:00
|
|
|
uint32 in_operand_index = 3;
|
2019-06-06 21:22:35 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-08-05 17:00:13 +00:00
|
|
|
message DataDescriptor {
|
|
|
|
|
|
|
|
// Represents a data element that can be accessed from an id, by walking the
|
|
|
|
// type hierarchy via a sequence of 0 or more indices.
|
|
|
|
//
|
|
|
|
// Very similar to a UniformBufferElementDescriptor, except that a
|
|
|
|
// DataDescriptor is rooted at the id of a scalar or composite.
|
|
|
|
|
|
|
|
// The object being accessed - a scalar or composite
|
|
|
|
uint32 object = 1;
|
|
|
|
|
|
|
|
// 0 or more indices, used to index into a composite object
|
|
|
|
repeated uint32 index = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-11 14:56:08 +00:00
|
|
|
message UniformBufferElementDescriptor {
|
|
|
|
|
|
|
|
// Represents a data element inside a uniform buffer. The element is
|
|
|
|
// specified via (a) the result id of a uniform variable in which the element
|
|
|
|
// is contained, and (b) a series of indices that need to be followed to get
|
|
|
|
// to the element (via fields and array/vector indices).
|
|
|
|
//
|
2019-06-19 19:45:14 +00:00
|
|
|
// Example: suppose there is a uniform variable with descriptor set 7 and
|
|
|
|
// binding 9, and that the uniform variable has the following type (using
|
|
|
|
// GLSL-like syntax):
|
2019-06-11 14:56:08 +00:00
|
|
|
//
|
|
|
|
// struct S {
|
|
|
|
// float f;
|
|
|
|
// vec3 g;
|
|
|
|
// int4 h[10];
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// Then:
|
2019-06-19 19:45:14 +00:00
|
|
|
// - (7, 9, [0]) describes the 'f' field.
|
|
|
|
// - (7, 9, [1,1]) describes the y component of the 'g' field.
|
|
|
|
// - (7, 9, [2,7,3]) describes the w component of element 7 of the 'h' field
|
2019-06-11 14:56:08 +00:00
|
|
|
|
2019-06-19 19:45:14 +00:00
|
|
|
// The descriptor set and binding associated with a uniform variable.
|
|
|
|
uint32 descriptor_set = 1;
|
|
|
|
uint32 binding = 2;
|
2019-06-11 14:56:08 +00:00
|
|
|
|
|
|
|
// An ordered sequence of indices through composite structures in the
|
|
|
|
// uniform buffer.
|
2019-06-19 19:45:14 +00:00
|
|
|
repeated uint32 index = 3;
|
2019-06-11 14:56:08 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-19 21:15:09 +00:00
|
|
|
message InstructionOperand {
|
|
|
|
|
|
|
|
// Represents an operand to a SPIR-V instruction.
|
|
|
|
|
|
|
|
// The type of the operand.
|
|
|
|
uint32 operand_type = 1;
|
|
|
|
|
|
|
|
// The data associated with the operand. For most operands (e.g. ids,
|
|
|
|
// storage classes and literals) this will be a single word.
|
|
|
|
repeated uint32 operand_data = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message Instruction {
|
|
|
|
|
|
|
|
// Represents a SPIR-V instruction.
|
|
|
|
|
|
|
|
// The instruction's opcode (e.g. OpLabel).
|
|
|
|
uint32 opcode = 1;
|
|
|
|
|
|
|
|
// The id of the instruction's result type; 0 if there is no result type.
|
|
|
|
uint32 result_type_id = 2;
|
|
|
|
|
|
|
|
// The id of the instruction's result; 0 if there is no result.
|
|
|
|
uint32 result_id = 3;
|
|
|
|
|
|
|
|
// Zero or more input operands.
|
|
|
|
repeated InstructionOperand input_operand = 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-27 13:34:55 +00:00
|
|
|
message FactSequence {
|
|
|
|
repeated Fact fact = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
message Fact {
|
2019-06-11 14:56:08 +00:00
|
|
|
oneof fact {
|
|
|
|
// Order the fact options by numeric id (rather than alphabetically).
|
|
|
|
FactConstantUniform constant_uniform_fact = 1;
|
2019-10-25 16:37:55 +00:00
|
|
|
FactDataSynonym data_synonym_fact = 2;
|
2020-01-13 22:04:01 +00:00
|
|
|
FactBlockIsDead block_is_dead_fact = 3;
|
2019-06-11 14:56:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep fact message types in alphabetical order:
|
|
|
|
|
|
|
|
message FactConstantUniform {
|
|
|
|
|
|
|
|
// Records the fact that a uniform buffer element is guaranteed to be equal
|
|
|
|
// to a particular constant value. spirv-fuzz can use such guarantees to
|
|
|
|
// obfuscate code, e.g. to manufacture an expression that will (due to the
|
|
|
|
// guarantee) evaluate to a particular value at runtime but in a manner that
|
|
|
|
// cannot be predicted at compile-time.
|
|
|
|
|
|
|
|
// An element of a uniform buffer
|
|
|
|
UniformBufferElementDescriptor uniform_buffer_element_descriptor = 1;
|
|
|
|
|
|
|
|
// The words of the associated constant
|
|
|
|
repeated uint32 constant_word = 2;
|
|
|
|
|
2019-05-27 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
2019-10-25 16:37:55 +00:00
|
|
|
message FactDataSynonym {
|
2019-08-05 17:00:13 +00:00
|
|
|
|
2019-10-25 16:37:55 +00:00
|
|
|
// Records the fact that the data held in two data descriptors are guaranteed
|
|
|
|
// to be equal. spirv-fuzz can use this to replace uses of one piece of data
|
|
|
|
// with a known-to-be-equal piece of data.
|
2019-08-05 17:00:13 +00:00
|
|
|
|
2019-10-25 16:37:55 +00:00
|
|
|
// Data descriptors guaranteed to hold identical data.
|
|
|
|
DataDescriptor data1 = 1;
|
2019-08-05 17:00:13 +00:00
|
|
|
|
2019-10-25 16:37:55 +00:00
|
|
|
DataDescriptor data2 = 2;
|
2019-08-05 17:00:13 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-13 22:04:01 +00:00
|
|
|
message FactBlockIsDead {
|
|
|
|
|
|
|
|
// Records the fact that a block is guaranteed to be dynamically unreachable.
|
|
|
|
// This is useful because it informs the fuzzer that rather arbitrary changes
|
|
|
|
// can be made to this block.
|
|
|
|
|
|
|
|
uint32 block_id = 1;
|
|
|
|
}
|
|
|
|
|
2019-05-27 13:34:55 +00:00
|
|
|
message TransformationSequence {
|
|
|
|
repeated Transformation transformation = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
message Transformation {
|
2019-05-29 15:42:46 +00:00
|
|
|
oneof transformation {
|
2019-06-04 13:55:00 +00:00
|
|
|
// Order the transformation options by numeric id (rather than
|
|
|
|
// alphabetically).
|
2019-05-31 08:59:06 +00:00
|
|
|
TransformationMoveBlockDown move_block_down = 1;
|
|
|
|
TransformationSplitBlock split_block = 2;
|
2019-06-04 13:55:00 +00:00
|
|
|
TransformationAddConstantBoolean add_constant_boolean = 3;
|
|
|
|
TransformationAddConstantScalar add_constant_scalar = 4;
|
|
|
|
TransformationAddTypeBoolean add_type_boolean = 5;
|
|
|
|
TransformationAddTypeFloat add_type_float = 6;
|
|
|
|
TransformationAddTypeInt add_type_int = 7;
|
2019-06-05 07:02:16 +00:00
|
|
|
TransformationAddDeadBreak add_dead_break = 8;
|
2019-10-10 12:34:38 +00:00
|
|
|
TransformationReplaceBooleanConstantWithConstantBinary
|
|
|
|
replace_boolean_constant_with_constant_binary = 9;
|
2019-06-18 17:41:08 +00:00
|
|
|
TransformationAddTypePointer add_type_pointer = 10;
|
|
|
|
TransformationReplaceConstantWithUniform replace_constant_with_uniform = 11;
|
2019-07-25 12:50:33 +00:00
|
|
|
TransformationAddDeadContinue add_dead_continue = 12;
|
2019-08-05 17:00:13 +00:00
|
|
|
TransformationCopyObject copy_object = 13;
|
2019-09-18 19:47:08 +00:00
|
|
|
TransformationReplaceIdWithSynonym replace_id_with_synonym = 14;
|
2019-10-08 10:25:34 +00:00
|
|
|
TransformationSetSelectionControl set_selection_control = 15;
|
2019-10-27 18:11:07 +00:00
|
|
|
TransformationCompositeConstruct composite_construct = 16;
|
2019-10-10 12:34:38 +00:00
|
|
|
TransformationSetLoopControl set_loop_control = 17;
|
2019-10-11 06:10:47 +00:00
|
|
|
TransformationSetFunctionControl set_function_control = 18;
|
2019-10-11 08:15:47 +00:00
|
|
|
TransformationAddNoContractionDecoration add_no_contraction_decoration = 19;
|
2019-10-22 17:05:35 +00:00
|
|
|
TransformationSetMemoryOperandsMask set_memory_operands_mask = 20;
|
2019-10-28 09:33:08 +00:00
|
|
|
TransformationCompositeExtract composite_extract = 21;
|
2019-11-06 17:11:54 +00:00
|
|
|
TransformationVectorShuffle vector_shuffle = 22;
|
2019-12-10 14:47:42 +00:00
|
|
|
TransformationOutlineFunction outline_function = 23;
|
2019-12-12 15:27:40 +00:00
|
|
|
TransformationMergeBlocks merge_blocks = 24;
|
2019-12-16 23:54:13 +00:00
|
|
|
TransformationAddTypeVector add_type_vector = 25;
|
|
|
|
TransformationAddTypeArray add_type_array = 26;
|
|
|
|
TransformationAddTypeMatrix add_type_matrix = 27;
|
|
|
|
TransformationAddTypeStruct add_type_struct = 28;
|
|
|
|
TransformationAddTypeFunction add_type_function = 29;
|
|
|
|
TransformationAddConstantComposite add_constant_composite = 30;
|
|
|
|
TransformationAddGlobalVariable add_global_variable = 31;
|
|
|
|
TransformationAddGlobalUndef add_global_undef = 32;
|
2019-12-19 21:15:09 +00:00
|
|
|
TransformationAddFunction add_function = 33;
|
2020-01-13 22:04:01 +00:00
|
|
|
TransformationAddDeadBlock add_dead_block = 34;
|
2019-06-04 13:55:00 +00:00
|
|
|
// Add additional option using the next available number.
|
2019-05-29 15:42:46 +00:00
|
|
|
}
|
2019-06-04 13:55:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Keep transformation message types in alphabetical order:
|
|
|
|
|
|
|
|
message TransformationAddConstantBoolean {
|
|
|
|
|
|
|
|
// Supports adding the constants true and false to a module, which may be
|
|
|
|
// necessary in order to enable other transformations if they are not present.
|
|
|
|
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
bool is_true = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddConstantComposite {
|
|
|
|
|
|
|
|
// Adds a constant of the given composite type to the module.
|
|
|
|
|
|
|
|
// Fresh id for the composite
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// A composite type id
|
|
|
|
uint32 type_id = 2;
|
|
|
|
|
|
|
|
// Constituent ids for the composite
|
|
|
|
repeated uint32 constituent_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-04 13:55:00 +00:00
|
|
|
message TransformationAddConstantScalar {
|
|
|
|
|
2020-01-13 22:04:01 +00:00
|
|
|
// Adds a constant of the given scalar type.
|
2019-06-04 13:55:00 +00:00
|
|
|
|
|
|
|
// Id for the constant
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// Id for the scalar type of the constant
|
|
|
|
uint32 type_id = 2;
|
|
|
|
|
|
|
|
// Value of the constant
|
|
|
|
repeated uint32 word = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-13 22:04:01 +00:00
|
|
|
message TransformationAddDeadBlock {
|
|
|
|
|
|
|
|
// Adds a new block to the module that is statically reachable from an
|
|
|
|
// existing block, but dynamically unreachable.
|
|
|
|
|
|
|
|
// Fresh id for the dead block
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// Id of an existing block terminated with OpBranch, such that this OpBranch
|
|
|
|
// can be replaced with an OpBranchConditional to its exiting successor or
|
|
|
|
// the dead block
|
|
|
|
uint32 existing_block = 2;
|
|
|
|
|
|
|
|
// Determines whether the condition associated with the OpBranchConditional
|
|
|
|
// is true or false
|
|
|
|
bool condition_value = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-05 07:02:16 +00:00
|
|
|
message TransformationAddDeadBreak {
|
|
|
|
|
|
|
|
// A transformation that turns a basic block that unconditionally branches to
|
|
|
|
// its successor into a block that potentially breaks out of a structured
|
|
|
|
// control flow construct, but in such a manner that the break cannot actually
|
|
|
|
// be taken.
|
|
|
|
|
|
|
|
// The block to break from
|
|
|
|
uint32 from_block = 1;
|
|
|
|
|
|
|
|
// The merge block to break to
|
|
|
|
uint32 to_block = 2;
|
|
|
|
|
|
|
|
// Determines whether the break condition is true or false
|
|
|
|
bool break_condition_value = 3;
|
|
|
|
|
|
|
|
// A sequence of ids suitable for extending OpPhi instructions as a result of
|
|
|
|
// the new break edge
|
|
|
|
repeated uint32 phi_id = 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-07-25 12:50:33 +00:00
|
|
|
message TransformationAddDeadContinue {
|
|
|
|
|
|
|
|
// A transformation that turns a basic block appearing in a loop and that
|
|
|
|
// unconditionally branches to its successor into a block that potentially
|
|
|
|
// branches to the continue target of the loop, but in such a manner that the
|
|
|
|
// continue branch cannot actually be taken.
|
|
|
|
|
|
|
|
// The block to continue from
|
|
|
|
uint32 from_block = 1;
|
|
|
|
|
|
|
|
// Determines whether the continue condition is true or false
|
|
|
|
bool continue_condition_value = 2;
|
|
|
|
|
|
|
|
// A sequence of ids suitable for extending OpPhi instructions as a result of
|
|
|
|
// the new break edge
|
|
|
|
repeated uint32 phi_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-19 21:15:09 +00:00
|
|
|
message TransformationAddFunction {
|
|
|
|
|
|
|
|
// Adds a SPIR-V function to the module.
|
|
|
|
|
|
|
|
// The series of instructions that comprise the function.
|
|
|
|
repeated Instruction instruction = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddGlobalUndef {
|
|
|
|
|
|
|
|
// Adds an undefined value of a given type to the module at global scope.
|
|
|
|
|
|
|
|
// Fresh id for the undefined value
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The type of the undefined value
|
|
|
|
uint32 type_id = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message TransformationAddGlobalVariable {
|
|
|
|
|
|
|
|
// Adds a global variable of the given type to the module, with Private
|
|
|
|
// storage class and optionally with an initializer.
|
|
|
|
|
|
|
|
// Fresh id for the global variable
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The type of the global variable
|
|
|
|
uint32 type_id = 2;
|
|
|
|
|
|
|
|
// Optional initializer; 0 if there is no initializer
|
|
|
|
uint32 initializer_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-11 08:15:47 +00:00
|
|
|
message TransformationAddNoContractionDecoration {
|
|
|
|
|
|
|
|
// Applies OpDecorate NoContraction to the given result id
|
|
|
|
|
|
|
|
// Result id to be decorated
|
|
|
|
uint32 result_id = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddTypeArray {
|
|
|
|
|
|
|
|
// Adds an array type of the given element type and size to the module
|
|
|
|
|
|
|
|
// Fresh id for the array type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The array's element type
|
|
|
|
uint32 element_type_id = 2;
|
|
|
|
|
|
|
|
// The array's size
|
|
|
|
uint32 size_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-04 13:55:00 +00:00
|
|
|
message TransformationAddTypeBoolean {
|
|
|
|
|
|
|
|
// Adds OpTypeBool to the module
|
|
|
|
|
|
|
|
// Id to be used for the type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message TransformationAddTypeFloat {
|
|
|
|
|
|
|
|
// Adds OpTypeFloat to the module with the given width
|
|
|
|
|
|
|
|
// Id to be used for the type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// Floating-point width
|
|
|
|
uint32 width = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddTypeFunction {
|
|
|
|
|
|
|
|
// Adds a function type to the module
|
|
|
|
|
|
|
|
// Fresh id for the function type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The function's return type
|
|
|
|
uint32 return_type_id = 2;
|
|
|
|
|
|
|
|
// The function's argument types
|
|
|
|
repeated uint32 argument_type_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-04 13:55:00 +00:00
|
|
|
message TransformationAddTypeInt {
|
|
|
|
|
|
|
|
// Adds OpTypeInt to the module with the given width and signedness
|
|
|
|
|
|
|
|
// Id to be used for the type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// Integer width
|
|
|
|
uint32 width = 2;
|
|
|
|
|
|
|
|
// True if and only if this is a signed type
|
|
|
|
bool is_signed = 3;
|
|
|
|
|
2019-05-27 13:34:55 +00:00
|
|
|
}
|
2019-05-29 15:42:46 +00:00
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddTypeMatrix {
|
|
|
|
|
|
|
|
// Adds a matrix type to the module
|
|
|
|
|
|
|
|
// Fresh id for the matrix type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The matrix's column type, which must be a floating-point vector (as per
|
|
|
|
// the "data rules" in the SPIR-V specification).
|
|
|
|
uint32 column_type_id = 2;
|
|
|
|
|
|
|
|
// The matrix's column count
|
|
|
|
uint32 column_count = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-18 17:41:08 +00:00
|
|
|
message TransformationAddTypePointer {
|
|
|
|
|
|
|
|
// Adds OpTypePointer to the module, with the given storage class and base
|
|
|
|
// type
|
|
|
|
|
|
|
|
// Id to be used for the type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// Pointer storage class
|
|
|
|
uint32 storage_class = 2;
|
|
|
|
|
|
|
|
// Id of the base type for the pointer
|
|
|
|
uint32 base_type_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-16 23:54:13 +00:00
|
|
|
message TransformationAddTypeStruct {
|
|
|
|
|
|
|
|
// Adds a struct type to the module
|
|
|
|
|
|
|
|
// Fresh id for the struct type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The struct's member types
|
|
|
|
repeated uint32 member_type_id = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message TransformationAddTypeVector {
|
|
|
|
|
|
|
|
// Adds a vector type to the module
|
|
|
|
|
|
|
|
// Fresh id for the vector type
|
|
|
|
uint32 fresh_id = 1;
|
|
|
|
|
|
|
|
// The vector's component type
|
|
|
|
uint32 component_type_id = 2;
|
|
|
|
|
|
|
|
// The vector's component count
|
|
|
|
uint32 component_count = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-27 18:11:07 +00:00
|
|
|
message TransformationCompositeConstruct {
|
2019-10-08 13:04:10 +00:00
|
|
|
|
|
|
|
// A transformation that introduces an OpCompositeConstruct instruction to
|
|
|
|
// make a composite object.
|
|
|
|
|
|
|
|
// Id of the type of the composite that is to be constructed
|
|
|
|
uint32 composite_type_id = 1;
|
|
|
|
|
|
|
|
// Ids of the objects that will form the components of the composite
|
|
|
|
repeated uint32 component = 2;
|
|
|
|
|
2019-10-15 19:00:17 +00:00
|
|
|
// A descriptor for an instruction in a block before which the new
|
|
|
|
// OpCompositeConstruct instruction should be inserted
|
|
|
|
InstructionDescriptor instruction_to_insert_before = 3;
|
2019-10-08 13:04:10 +00:00
|
|
|
|
|
|
|
// A fresh id for the composite object
|
2019-10-15 19:00:17 +00:00
|
|
|
uint32 fresh_id = 4;
|
2019-10-08 13:04:10 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-28 09:33:08 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-27 18:11:07 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-12-12 15:27:40 +00:00
|
|
|
message TransformationMergeBlocks {
|
|
|
|
|
|
|
|
// A transformation that merges a block with its predecessor.
|
|
|
|
|
|
|
|
// The id of the block that is to be merged with its predecessor; the merged
|
|
|
|
// block will have the *predecessor's* id.
|
|
|
|
uint32 block_id = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-31 08:59:06 +00:00
|
|
|
message TransformationMoveBlockDown {
|
2019-06-04 13:55:00 +00:00
|
|
|
|
2019-05-31 08:59:06 +00:00
|
|
|
// A transformation that moves a basic block to be one position lower in
|
|
|
|
// program order.
|
|
|
|
|
|
|
|
// The id of the block to move down.
|
|
|
|
uint32 block_id = 1;
|
2019-06-18 17:41:08 +00:00
|
|
|
}
|
|
|
|
|
2019-12-10 14:47:42 +00:00
|
|
|
message TransformationOutlineFunction {
|
|
|
|
|
|
|
|
// A transformation that outlines a single-entry single-exit region of a
|
|
|
|
// control flow graph into a separate function, and replaces the region with
|
|
|
|
// a call to that function.
|
|
|
|
|
|
|
|
// Id of the entry block of the single-entry single-exit region to be outlined
|
|
|
|
uint32 entry_block = 1;
|
|
|
|
|
|
|
|
// Id of the exit block of the single-entry single-exit region to be outlined
|
|
|
|
uint32 exit_block = 2;
|
|
|
|
|
|
|
|
// Id of a struct that will store the return values of the new function
|
|
|
|
uint32 new_function_struct_return_type_id = 3;
|
|
|
|
|
|
|
|
// A fresh id for the type of the outlined function
|
|
|
|
uint32 new_function_type_id = 4;
|
|
|
|
|
|
|
|
// A fresh id for the outlined function itself
|
|
|
|
uint32 new_function_id = 5;
|
|
|
|
|
|
|
|
// A fresh id to represent the block in the outlined function that represents
|
|
|
|
// the first block of the outlined region.
|
|
|
|
uint32 new_function_region_entry_block = 6;
|
|
|
|
|
|
|
|
// A fresh id for the result of the OpFunctionCall instruction that will call
|
|
|
|
// the outlined function
|
|
|
|
uint32 new_caller_result_id = 7;
|
|
|
|
|
|
|
|
// A fresh id to capture the return value of the outlined function - the
|
|
|
|
// argument to OpReturn
|
|
|
|
uint32 new_callee_result_id = 8;
|
|
|
|
|
|
|
|
// Ids defined outside the region and used inside the region will become
|
|
|
|
// parameters to the outlined function. This is a mapping from used ids to
|
|
|
|
// fresh parameter ids.
|
|
|
|
repeated UInt32Pair input_id_to_fresh_id = 9;
|
|
|
|
|
|
|
|
// Ids defined inside the region and used outside the region will become
|
|
|
|
// fresh ids defined by the outlined function, which get copied into the
|
|
|
|
// function's struct return value and then copied into their destination ids
|
|
|
|
// by the caller. This is a mapping from original ids to corresponding fresh
|
|
|
|
// ids.
|
|
|
|
repeated UInt32Pair output_id_to_fresh_id = 10;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-09-18 19:47:08 +00:00
|
|
|
message TransformationReplaceBooleanConstantWithConstantBinary {
|
|
|
|
|
|
|
|
// A transformation to capture replacing a use of a boolean constant with
|
|
|
|
// binary operation on two constant values
|
|
|
|
|
|
|
|
// A descriptor for the boolean constant id we would like to replace
|
|
|
|
IdUseDescriptor id_use_descriptor = 1;
|
|
|
|
|
|
|
|
// Id for the constant to be used on the LHS of the comparision
|
|
|
|
uint32 lhs_id = 2;
|
|
|
|
|
|
|
|
// Id for the constant to be used on the RHS of the comparision
|
|
|
|
uint32 rhs_id = 3;
|
|
|
|
|
|
|
|
// Opcode for binary operator
|
|
|
|
uint32 opcode = 4;
|
|
|
|
|
|
|
|
// Id that will store the result of the binary operation instruction
|
|
|
|
uint32 fresh_id_for_binary_operation = 5;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-06-18 17:41:08 +00:00
|
|
|
message TransformationReplaceConstantWithUniform {
|
|
|
|
|
2019-09-19 13:47:46 +00:00
|
|
|
// Replaces a use of a constant id with the result of a load from an
|
2019-06-18 17:41:08 +00:00
|
|
|
// element of uniform buffer known to hold the same value as the constant
|
|
|
|
|
|
|
|
// A descriptor for the id we would like to replace
|
|
|
|
IdUseDescriptor id_use_descriptor = 1;
|
|
|
|
|
|
|
|
// Uniform descriptor to identify which uniform value to choose
|
|
|
|
UniformBufferElementDescriptor uniform_descriptor = 2;
|
|
|
|
|
|
|
|
// Id that will store the result of an access chain
|
|
|
|
uint32 fresh_id_for_access_chain = 3;
|
|
|
|
|
|
|
|
// Id that will store the result of a load
|
|
|
|
uint32 fresh_id_for_load = 4;
|
2019-06-04 13:55:00 +00:00
|
|
|
|
2019-05-31 08:59:06 +00:00
|
|
|
}
|
|
|
|
|
2019-09-18 19:47:08 +00:00
|
|
|
message TransformationReplaceIdWithSynonym {
|
2019-08-05 17:00:13 +00:00
|
|
|
|
2019-11-07 16:19:06 +00:00
|
|
|
// Replaces a use of an id with an id that is known to be synonymous, e.g.
|
|
|
|
// because it was obtained via applying OpCopyObject
|
2019-06-06 21:22:35 +00:00
|
|
|
|
2019-11-07 16:19:06 +00:00
|
|
|
// The id use that is to be replaced
|
2019-06-06 21:22:35 +00:00
|
|
|
IdUseDescriptor id_use_descriptor = 1;
|
|
|
|
|
2019-11-07 16:19:06 +00:00
|
|
|
// The synonymous id
|
|
|
|
uint32 synonymous_id = 2;
|
2019-06-06 21:22:35 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-11 06:10:47 +00:00
|
|
|
message TransformationSetFunctionControl {
|
|
|
|
|
|
|
|
// A transformation that sets the function control operand of an OpFunction
|
|
|
|
// instruction.
|
|
|
|
|
|
|
|
// The result id of an OpFunction instruction
|
|
|
|
uint32 function_id = 1;
|
|
|
|
|
|
|
|
// The value to which the 'function control' operand should be set.
|
|
|
|
uint32 function_control = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-10 12:34:38 +00:00
|
|
|
message TransformationSetLoopControl {
|
|
|
|
|
|
|
|
// A transformation that sets the loop control operand of an OpLoopMerge
|
|
|
|
// instruction.
|
|
|
|
|
|
|
|
// The id of a basic block that should contain OpLoopMerge
|
|
|
|
uint32 block_id = 1;
|
|
|
|
|
|
|
|
// The value to which the 'loop control' operand should be set.
|
|
|
|
// This must be a legal loop control mask.
|
|
|
|
uint32 loop_control = 2;
|
|
|
|
|
|
|
|
// Provides a peel count value for the loop. Used if and only if the
|
|
|
|
// PeelCount bit is set. Must be zero if the PeelCount bit is not set (can
|
|
|
|
// still be zero if this bit is set).
|
|
|
|
uint32 peel_count = 3;
|
|
|
|
|
|
|
|
// Provides a partial count value for the loop. Used if and only if the
|
|
|
|
// PartialCount bit is set. Must be zero if the PartialCount bit is not set
|
|
|
|
// (can still be zero if this bit is set).
|
|
|
|
uint32 partial_count = 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-22 17:05:35 +00:00
|
|
|
message TransformationSetMemoryOperandsMask {
|
|
|
|
|
|
|
|
// A transformation that sets the memory operands mask of a memory access
|
|
|
|
// instruction.
|
|
|
|
|
|
|
|
// A descriptor for a memory access instruction, e.g. an OpLoad
|
|
|
|
InstructionDescriptor memory_access_instruction = 1;
|
|
|
|
|
|
|
|
// A mask of memory operands to be applied to the instruction. It must be the
|
|
|
|
// same as the original mask, except that Volatile can be added, and
|
|
|
|
// Nontemporal can be added or removed.
|
|
|
|
uint32 memory_operands_mask = 2;
|
|
|
|
|
|
|
|
// Some memory access instructions allow more than one mask to be specified;
|
|
|
|
// this field indicates which mask should be set
|
|
|
|
uint32 memory_operands_mask_index = 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-08 10:25:34 +00:00
|
|
|
message TransformationSetSelectionControl {
|
|
|
|
|
|
|
|
// A transformation that sets the selection control operand of an
|
|
|
|
// OpSelectionMerge instruction.
|
|
|
|
|
2019-10-10 12:34:38 +00:00
|
|
|
// The id of a basic block that should contain OpSelectionMerge
|
2019-10-08 10:25:34 +00:00
|
|
|
uint32 block_id = 1;
|
|
|
|
|
|
|
|
// The value to which the 'selection control' operand should be set.
|
|
|
|
// Although technically 'selection control' is a literal mask that can be
|
|
|
|
// some combination of 'None', 'Flatten' and 'DontFlatten', the combination
|
2019-10-10 12:34:38 +00:00
|
|
|
// 'Flatten | DontFlatten' does not make sense and is not allowed here.
|
2019-10-08 10:25:34 +00:00
|
|
|
uint32 selection_control = 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-29 15:42:46 +00:00
|
|
|
message TransformationSplitBlock {
|
|
|
|
|
2019-08-05 17:00:13 +00:00
|
|
|
// A transformation that splits a basic block into two basic blocks
|
2019-05-29 15:42:46 +00:00
|
|
|
|
2019-10-14 16:00:46 +00:00
|
|
|
// A descriptor for an instruction such that the block containing the
|
|
|
|
// described instruction should be split right before the instruction.
|
|
|
|
InstructionDescriptor instruction_to_split_before = 1;
|
2019-05-29 15:42:46 +00:00
|
|
|
|
|
|
|
// An id that must not yet be used by the module to which this transformation
|
|
|
|
// is applied. Rather than having the transformation choose a suitable id on
|
|
|
|
// application, we require the id to be given upfront in order to facilitate
|
|
|
|
// reducing fuzzed shaders by removing transformations. The reason is that
|
|
|
|
// future transformations may refer to the fresh id introduced by this
|
|
|
|
// transformation, and if we end up changing what that id is, due to removing
|
|
|
|
// earlier transformations, it may inhibit later transformations from
|
|
|
|
// applying.
|
2019-10-14 16:00:46 +00:00
|
|
|
uint32 fresh_id = 2;
|
2019-05-29 15:42:46 +00:00
|
|
|
|
|
|
|
}
|
2019-11-06 17:11:54 +00:00
|
|
|
|
|
|
|
message TransformationVectorShuffle {
|
|
|
|
|
|
|
|
// A transformation that adds a vector shuffle instruction.
|
|
|
|
|
|
|
|
// A descriptor for an instruction in a block before which the new
|
|
|
|
// OpVectorShuffle instruction should be inserted
|
|
|
|
InstructionDescriptor instruction_to_insert_before = 1;
|
|
|
|
|
|
|
|
// Result id for the shuffle operation.
|
|
|
|
uint32 fresh_id = 2;
|
|
|
|
|
|
|
|
// Id of the first vector operand.
|
|
|
|
uint32 vector1 = 3;
|
|
|
|
|
|
|
|
// Id of the second vector operand.
|
|
|
|
uint32 vector2 = 4;
|
|
|
|
|
|
|
|
// Indices that indicate which components of the input vectors should be used.
|
|
|
|
repeated uint32 component = 5;
|
|
|
|
|
|
|
|
}
|