1 #include <utility> 2 3 // Copyright (c) 2019 Google LLC 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #ifndef SOURCE_FUZZ_TRANSFORMATION_REPLACE_CONSTANT_WITH_UNIFORM_H_ 18 #define SOURCE_FUZZ_TRANSFORMATION_REPLACE_CONSTANT_WITH_UNIFORM_H_ 19 20 #include "source/fuzz/id_use_descriptor.h" 21 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" 22 #include "source/fuzz/transformation.h" 23 #include "source/opt/ir_context.h" 24 25 namespace spvtools { 26 namespace fuzz { 27 28 class TransformationReplaceConstantWithUniform : public Transformation { 29 public: 30 explicit TransformationReplaceConstantWithUniform( 31 protobufs::TransformationReplaceConstantWithUniform message); 32 33 TransformationReplaceConstantWithUniform( 34 protobufs::IdUseDescriptor id_use, 35 protobufs::UniformBufferElementDescriptor uniform_descriptor, 36 uint32_t fresh_id_for_access_chain, uint32_t fresh_id_for_load); 37 38 // - |message_.fresh_id_for_access_chain| and |message_.fresh_id_for_load| 39 // must be distinct fresh ids. 40 // - |message_.uniform_descriptor| specifies a result id and a list of integer 41 // literal indices. 42 // As an example, suppose |message_.uniform_descriptor| is (18, [0, 1, 0]) 43 // It is required that: 44 // - the result id (18 in our example) is the id of some uniform variable 45 // - the module contains an integer constant instruction corresponding to 46 // each of the literal indices; in our example there must thus be 47 // OpConstant instructions %A and %B say for each of 0 and 1 48 // - it is legitimate to index into the uniform variable using the 49 // sequence of indices; in our example this means indexing into %18 50 // using the sequence %A %B %A 51 // - the module contains a uniform pointer type corresponding to the type 52 // of the uniform data element obtained by following these indices 53 // - |message_.id_use_descriptor| identifies the use of some id %C. It is 54 // required that: 55 // - this use does indeed exist in the module 56 // - %C is an OpConstant 57 // - According to the fact manager, the uniform data element specified by 58 // |message_.uniform_descriptor| holds a value with the same type and 59 // value as %C 60 bool IsApplicable( 61 opt::IRContext* ir_context, 62 const TransformationContext& transformation_context) const override; 63 64 // - Introduces two new instructions: 65 // - An access chain targeting the uniform data element specified by 66 // |message_.uniform_descriptor|, with result id 67 // |message_.fresh_id_for_access_chain| 68 // - A load from this access chain, with id |message_.fresh_id_for_load| 69 // - Replaces the id use specified by |message_.id_use_descriptor| with 70 // |message_.fresh_id_for_load| 71 void Apply(opt::IRContext* ir_context, 72 TransformationContext* transformation_context) const override; 73 74 std::unordered_set<uint32_t> GetFreshIds() const override; 75 76 protobufs::Transformation ToMessage() const override; 77 78 private: 79 // Helper method to create an access chain for the uniform element associated 80 // with the transformation. 81 std::unique_ptr<opt::Instruction> MakeAccessChainInstruction( 82 spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const; 83 84 // Helper to create a load instruction. 85 std::unique_ptr<opt::Instruction> MakeLoadInstruction( 86 spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const; 87 88 // OpAccessChain and OpLoad will be inserted above the instruction returned 89 // by this function. Returns nullptr if no such instruction is present. 90 opt::Instruction* GetInsertBeforeInstruction( 91 opt::IRContext* ir_context) const; 92 93 protobufs::TransformationReplaceConstantWithUniform message_; 94 }; 95 96 } // namespace fuzz 97 } // namespace spvtools 98 99 #endif // SOURCE_FUZZ_TRANSFORMATION_REPLACE_CONSTANT_WITH_UNIFORM_H_ 100