• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_VERTEX_PULLING_H_
16 #define SRC_TRANSFORM_VERTEX_PULLING_H_
17 
18 #include <memory>
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22 
23 #include "src/transform/transform.h"
24 
25 namespace tint {
26 namespace transform {
27 
28 /// Describes the format of data in a vertex buffer
29 enum class VertexFormat {
30   kUint8x2,    // uint8x2
31   kUint8x4,    // uint8x4
32   kSint8x2,    // sint8x2
33   kSint8x4,    // sint8x4
34   kUnorm8x2,   // unorm8x2
35   kUnorm8x4,   // unorm8x4
36   kSnorm8x2,   // snorm8x2
37   kSnorm8x4,   // snorm8x4
38   kUint16x2,   // uint16x2
39   kUint16x4,   // uint16x4
40   kSint16x2,   // sint16x2
41   kSint16x4,   // sint16x4
42   kUnorm16x2,  // unorm16x2
43   kUnorm16x4,  // unorm16x4
44   kSnorm16x2,  // snorm16x2
45   kSnorm16x4,  // snorm16x4
46   kFloat16x2,  // float16x2
47   kFloat16x4,  // float16x4
48   kFloat32,    // float32
49   kFloat32x2,  // float32x2
50   kFloat32x3,  // float32x3
51   kFloat32x4,  // float32x4
52   kUint32,     // uint32
53   kUint32x2,   // uint32x2
54   kUint32x3,   // uint32x3
55   kUint32x4,   // uint32x4
56   kSint32,     // sint32
57   kSint32x2,   // sint32x2
58   kSint32x3,   // sint32x3
59   kSint32x4,   // sint32x4
60 
61   kLastEntry = kSint32x4,
62 };
63 
64 /// Describes if a vertex attributes increments with vertex index or instance
65 /// index
66 enum class VertexStepMode { kVertex, kInstance, kLastEntry = kInstance };
67 
68 /// Describes a vertex attribute within a buffer
69 struct VertexAttributeDescriptor {
70   /// The format of the attribute
71   VertexFormat format;
72   /// The byte offset of the attribute in the buffer
73   uint32_t offset;
74   /// The shader location used for the attribute
75   uint32_t shader_location;
76 };
77 
78 /// Describes a buffer containing multiple vertex attributes
79 struct VertexBufferLayoutDescriptor {
80   /// Constructor
81   VertexBufferLayoutDescriptor();
82   /// Constructor
83   /// @param in_array_stride the array stride of the in buffer
84   /// @param in_step_mode the step mode of the in buffer
85   /// @param in_attributes the in attributes
86   VertexBufferLayoutDescriptor(
87       uint32_t in_array_stride,
88       VertexStepMode in_step_mode,
89       std::vector<VertexAttributeDescriptor> in_attributes);
90   /// Copy constructor
91   /// @param other the struct to copy
92   VertexBufferLayoutDescriptor(const VertexBufferLayoutDescriptor& other);
93 
94   /// Assignment operator
95   /// @param other the struct to copy
96   /// @returns this struct
97   VertexBufferLayoutDescriptor& operator=(
98       const VertexBufferLayoutDescriptor& other);
99 
100   ~VertexBufferLayoutDescriptor();
101 
102   /// The array stride used in the in buffer
103   uint32_t array_stride = 0u;
104   /// The input step mode used
105   VertexStepMode step_mode = VertexStepMode::kVertex;
106   /// The vertex attributes
107   std::vector<VertexAttributeDescriptor> attributes;
108 };
109 
110 /// Describes vertex state, which consists of many buffers containing vertex
111 /// attributes
112 using VertexStateDescriptor = std::vector<VertexBufferLayoutDescriptor>;
113 
114 /// Converts a program to use vertex pulling
115 ///
116 /// Variables which accept vertex input are var<in> with a location decoration.
117 /// This transform will convert those to be assigned from storage buffers
118 /// instead. The intention is to allow vertex input to rely on a storage buffer
119 /// clamping pass for out of bounds reads. We bind the storage buffers as arrays
120 /// of u32, so any read to byte position `p` will actually need to read position
121 /// `p / 4`, since `sizeof(u32) == 4`.
122 ///
123 /// `VertexFormat` represents the input type of the attribute. This isn't
124 /// related to the type of the variable in the shader. For example,
125 /// `VertexFormat::kVec2F16` tells us that the buffer will contain `f16`
126 /// elements, to be read as vec2. In the shader, a user would make a `vec2<f32>`
127 /// to be able to use them. The conversion between `f16` and `f32` will need to
128 /// be handled by us (using unpack functions).
129 ///
130 /// To be clear, there won't be types such as `f16` or `u8` anywhere in WGSL
131 /// code, but these are types that the data may arrive as. We need to convert
132 /// these smaller types into the base types such as `f32` and `u32` for the
133 /// shader to use.
134 class VertexPulling : public Castable<VertexPulling, Transform> {
135  public:
136   /// Configuration options for the transform
137   struct Config : public Castable<Config, Data> {
138     /// Constructor
139     Config();
140 
141     /// Copy constructor
142     Config(const Config&);
143 
144     /// Destructor
145     ~Config() override;
146 
147     /// Assignment operator
148     /// @returns this Config
149     Config& operator=(const Config&);
150 
151     /// The entry point to add assignments into
152     std::string entry_point_name;
153 
154     /// The vertex state descriptor, containing info about attributes
155     VertexStateDescriptor vertex_state;
156 
157     /// The "group" we will put all our vertex buffers into (as storage buffers)
158     /// Default to 4 as it is past the limits of user-accessible groups
159     uint32_t pulling_group = 4u;
160   };
161 
162   /// Constructor
163   VertexPulling();
164 
165   /// Destructor
166   ~VertexPulling() override;
167 
168  protected:
169   /// Runs the transform using the CloneContext built for transforming a
170   /// program. Run() is responsible for calling Clone() on the CloneContext.
171   /// @param ctx the CloneContext primed with the input program and
172   /// ProgramBuilder
173   /// @param inputs optional extra transform-specific input data
174   /// @param outputs optional extra transform-specific output data
175   void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) override;
176 
177  private:
178   Config cfg_;
179 };
180 
181 }  // namespace transform
182 }  // namespace tint
183 
184 #endif  // SRC_TRANSFORM_VERTEX_PULLING_H_
185