| // Copyright 2020 The Tint Authors. | 
 | // | 
 | // 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 SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ | 
 | #define SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ | 
 |  | 
 | #include "src/transform/transform.h" | 
 |  | 
 | namespace tint { | 
 | namespace transform { | 
 |  | 
 | /// Adds firstVertex/Instance (injected via root constants) to | 
 | /// vertex/instance index builtins. | 
 | /// | 
 | /// This transform assumes that Name transform has been run before. | 
 | /// | 
 | /// Unlike other APIs, D3D always starts vertex and instance numbering at 0, | 
 | /// regardless of the firstVertex/Instance value specified. This transformer | 
 | /// adds the value of firstVertex/Instance to each builtin. This action is | 
 | /// performed by adding a new constant equal to original builtin + | 
 | /// firstVertex/Instance to each function that references one of these builtins. | 
 | /// | 
 | /// Note that D3D does not have any semantics for firstVertex/Instance. | 
 | /// Therefore, these values must by passed to the shader. | 
 | /// | 
 | /// Before: | 
 | ///   [[builtin(vertex_index)]] var<in> vert_idx : u32; | 
 | ///   fn func() -> u32 { | 
 | ///     return vert_idx; | 
 | ///   } | 
 | /// | 
 | /// After: | 
 | ///   [[block]] | 
 | ///   struct TintFirstIndexOffsetData { | 
 | ///     tint_first_vertex_index : u32; | 
 | ///     tint_first_instance_index : u32; | 
 | ///   }; | 
 | ///   [[builtin(vertex_index)]] var<in> tint_first_index_offset_vert_idx : u32; | 
 | ///   [[binding(N), group(M)]] var<uniform> tint_first_index_data : | 
 | ///                                                    TintFirstIndexOffsetData; | 
 | ///   fn func() -> u32 { | 
 | ///     const vert_idx = (tint_first_index_offset_vert_idx + | 
 | ///                       tint_first_index_data.tint_first_vertex_index); | 
 | ///     return vert_idx; | 
 | ///   } | 
 | /// | 
 | class FirstIndexOffset : public Transform { | 
 |  public: | 
 |   /// BindingPoint is consumed by the FirstIndexOffset transform. | 
 |   /// BindingPoint specifies the binding point of the first index uniform | 
 |   /// buffer. | 
 |   struct BindingPoint : public Castable<BindingPoint, transform::Data> { | 
 |     /// Constructor | 
 |     BindingPoint(); | 
 |  | 
 |     /// Constructor | 
 |     /// @param b the binding index | 
 |     /// @param g the binding group | 
 |     BindingPoint(uint32_t b, uint32_t g); | 
 |  | 
 |     /// Destructor | 
 |     ~BindingPoint() override; | 
 |  | 
 |     /// [[binding()]] for the first vertex / first instance uniform buffer | 
 |     uint32_t binding = 0; | 
 |     /// [[group()]] for the first vertex / first instance uniform buffer | 
 |     uint32_t group = 0; | 
 |   }; | 
 |  | 
 |   /// Data is outputted by the FirstIndexOffset transform. | 
 |   /// Data holds information about shader usage and constant buffer offsets. | 
 |   struct Data : public Castable<Data, transform::Data> { | 
 |     /// Constructor | 
 |     /// @param has_vtx_index True if the shader uses vertex_index | 
 |     /// @param has_inst_index True if the shader uses instance_index | 
 |     /// @param first_vtx_offset Offset of first vertex into constant buffer | 
 |     /// @param first_inst_offset Offset of first instance into constant buffer | 
 |     Data(bool has_vtx_index, | 
 |          bool has_inst_index, | 
 |          uint32_t first_vtx_offset, | 
 |          uint32_t first_inst_offset); | 
 |  | 
 |     /// Copy constructor | 
 |     Data(const Data&); | 
 |  | 
 |     /// Destructor | 
 |     ~Data() override; | 
 |  | 
 |     /// True if the shader uses vertex_index | 
 |     bool const has_vertex_index; | 
 |     /// True if the shader uses instance_index | 
 |     bool const has_instance_index; | 
 |     /// Offset of first vertex into constant buffer | 
 |     uint32_t const first_vertex_offset; | 
 |     /// Offset of first instance into constant buffer | 
 |     uint32_t const first_instance_offset; | 
 |   }; | 
 |  | 
 |   /// Constructor | 
 |   FirstIndexOffset(); | 
 |   /// Constructor | 
 |   /// [DEPRECATED] - pass BindingPoint as part of the `data` to Run() | 
 |   /// @param binding the binding() for firstVertex/Instance uniform | 
 |   /// @param group the group() for firstVertex/Instance uniform | 
 |   FirstIndexOffset(uint32_t binding, uint32_t group); | 
 |   ~FirstIndexOffset() override; | 
 |  | 
 |   /// Runs the transform on `program`, returning the transformation result. | 
 |   /// @param program the source program to transform | 
 |   /// @param data optional extra transform-specific input data | 
 |   /// @returns the transformation result | 
 |   Output Run(const Program* program, const DataMap& data = {}) override; | 
 |  | 
 |  private: | 
 |   uint32_t binding_ = 0; | 
 |   uint32_t group_ = 0; | 
 | }; | 
 |  | 
 | }  // namespace transform | 
 | }  // namespace tint | 
 |  | 
 | #endif  // SRC_TRANSFORM_FIRST_INDEX_OFFSET_H_ |