1 // Copyright 2020 The Tint Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ 16 #define SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ 17 18 #include "src/transform/transform.h" 19 20 namespace tint { 21 namespace transform { 22 23 /// Adds firstVertex/Instance (injected via root constants) to 24 /// vertex/instance index builtins. 25 /// 26 /// This transform assumes that Name transform has been run before. 27 /// 28 /// Unlike other APIs, D3D always starts vertex and instance numbering at 0, 29 /// regardless of the firstVertex/Instance value specified. This transformer 30 /// adds the value of firstVertex/Instance to each builtin. This action is 31 /// performed by adding a new constant equal to original builtin + 32 /// firstVertex/Instance to each function that references one of these builtins. 33 /// 34 /// Note that D3D does not have any semantics for firstVertex/Instance. 35 /// Therefore, these values must by passed to the shader. 36 /// 37 /// Before: 38 /// [[builtin(vertex_index)]] var<in> vert_idx : u32; 39 /// fn func() -> u32 { 40 /// return vert_idx; 41 /// } 42 /// 43 /// After: 44 /// [[block]] 45 /// struct TintFirstIndexOffsetData { 46 /// tint_first_vertex_index : u32; 47 /// tint_first_instance_index : u32; 48 /// }; 49 /// [[builtin(vertex_index)]] var<in> tint_first_index_offset_vert_idx : u32; 50 /// [[binding(N), group(M)]] var<uniform> tint_first_index_data : 51 /// TintFirstIndexOffsetData; 52 /// fn func() -> u32 { 53 /// const vert_idx = (tint_first_index_offset_vert_idx + 54 /// tint_first_index_data.tint_first_vertex_index); 55 /// return vert_idx; 56 /// } 57 /// 58 class FirstIndexOffset : public Castable<FirstIndexOffset, Transform> { 59 public: 60 /// BindingPoint is consumed by the FirstIndexOffset transform. 61 /// BindingPoint specifies the binding point of the first index uniform 62 /// buffer. 63 struct BindingPoint : public Castable<BindingPoint, transform::Data> { 64 /// Constructor 65 BindingPoint(); 66 67 /// Constructor 68 /// @param b the binding index 69 /// @param g the binding group 70 BindingPoint(uint32_t b, uint32_t g); 71 72 /// Destructor 73 ~BindingPoint() override; 74 75 /// [[binding()]] for the first vertex / first instance uniform buffer 76 uint32_t binding = 0; 77 /// [[group()]] for the first vertex / first instance uniform buffer 78 uint32_t group = 0; 79 }; 80 81 /// Data is outputted by the FirstIndexOffset transform. 82 /// Data holds information about shader usage and constant buffer offsets. 83 struct Data : public Castable<Data, transform::Data> { 84 /// Constructor 85 /// @param has_vtx_index True if the shader uses vertex_index 86 /// @param has_inst_index True if the shader uses instance_index 87 /// @param first_vtx_offset Offset of first vertex into constant buffer 88 /// @param first_inst_offset Offset of first instance into constant buffer 89 Data(bool has_vtx_index, 90 bool has_inst_index, 91 uint32_t first_vtx_offset, 92 uint32_t first_inst_offset); 93 94 /// Copy constructor 95 Data(const Data&); 96 97 /// Destructor 98 ~Data() override; 99 100 /// True if the shader uses vertex_index 101 const bool has_vertex_index; 102 /// True if the shader uses instance_index 103 const bool has_instance_index; 104 /// Offset of first vertex into constant buffer 105 const uint32_t first_vertex_offset; 106 /// Offset of first instance into constant buffer 107 const uint32_t first_instance_offset; 108 }; 109 110 /// Constructor 111 FirstIndexOffset(); 112 /// Destructor 113 ~FirstIndexOffset() override; 114 115 protected: 116 /// Runs the transform using the CloneContext built for transforming a 117 /// program. Run() is responsible for calling Clone() on the CloneContext. 118 /// @param ctx the CloneContext primed with the input program and 119 /// ProgramBuilder 120 /// @param inputs optional extra transform-specific input data 121 /// @param outputs optional extra transform-specific output data 122 void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) override; 123 124 private: 125 uint32_t binding_ = 0; 126 uint32_t group_ = 0; 127 }; 128 129 } // namespace transform 130 } // namespace tint 131 132 #endif // SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ 133