blob: addaba7fcae3bbf2e1879ee8a2c5c8f050afe538 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman89401822014-05-06 15:04:28 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman89401822014-05-06 15:04:28 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
John Bauman89401822014-05-06 15:04:28 -04008//
Nicolas Capens0bac2852016-05-07 06:09:58 -04009// 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.
John Bauman89401822014-05-06 15:04:28 -040014
15#include "VertexRoutine.hpp"
16
17#include "VertexShader.hpp"
John Bauman89401822014-05-06 15:04:28 -040018#include "Constants.hpp"
Nicolas Capens708c24b2017-10-26 13:07:10 -040019#include "Renderer/Vertex.hpp"
20#include "Renderer/Renderer.hpp"
21#include "Common/Half.hpp"
22#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040023
24namespace sw
25{
John Bauman19bac1e2014-05-06 15:23:49 -040026 extern bool halfIntegerCoordinates; // Pixel centers are not at integer coordinates
27 extern bool symmetricNormalizedDepth; // [-1, 1] instead of [0, 1]
28
Nicolas Capens7551ac62016-01-20 17:11:53 -050029 VertexRoutine::VertexRoutine(const VertexProcessor::State &state, const VertexShader *shader)
Nicolas Capens5bff4052018-05-28 13:18:59 -040030 : v(shader && shader->indirectAddressableInput),
31 o(shader && shader->indirectAddressableOutput),
Nicolas Capens7551ac62016-01-20 17:11:53 -050032 state(state)
John Bauman89401822014-05-06 15:04:28 -040033 {
John Bauman89401822014-05-06 15:04:28 -040034 }
35
36 VertexRoutine::~VertexRoutine()
37 {
38 }
39
40 void VertexRoutine::generate()
41 {
Nicolas Capens6abe1cb2016-01-15 23:30:50 -050042 const bool textureSampling = state.textureSampling;
Nicolas Capens2ca19032016-01-15 16:54:13 -050043
44 Pointer<Byte> cache = task + OFFSET(VertexTask,vertexCache);
45 Pointer<Byte> vertexCache = cache + OFFSET(VertexCache,vertex);
46 Pointer<Byte> tagCache = cache + OFFSET(VertexCache,tag);
47
48 UInt vertexCount = *Pointer<UInt>(task + OFFSET(VertexTask,vertexCount));
Alexis Hetua62a0ca2016-04-20 15:29:51 -040049 UInt primitiveNumber = *Pointer<UInt>(task + OFFSET(VertexTask, primitiveStart));
50 UInt indexInPrimitive = 0;
Nicolas Capens2ca19032016-01-15 16:54:13 -050051
Nicolas Capens7551ac62016-01-20 17:11:53 -050052 constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
John Bauman89401822014-05-06 15:04:28 -040053
Nicolas Capens2ca19032016-01-15 16:54:13 -050054 Do
55 {
56 UInt index = *Pointer<UInt>(batch);
57 UInt tagIndex = index & 0x0000003C;
Nicolas Capens6abe1cb2016-01-15 23:30:50 -050058 UInt indexQ = !textureSampling ? UInt(index & 0xFFFFFFFC) : index; // FIXME: TEXLDL hack to have independent LODs, hurts performance.
John Bauman89401822014-05-06 15:04:28 -040059
Nicolas Capens2ca19032016-01-15 16:54:13 -050060 If(*Pointer<UInt>(tagCache + tagIndex) != indexQ)
61 {
62 *Pointer<UInt>(tagCache + tagIndex) = indexQ;
63
Nicolas Capensb4fb3672016-01-15 17:02:41 -050064 readInput(indexQ);
Alexis Hetu877ddfc2017-07-25 17:48:00 -040065 pipeline(indexQ);
Nicolas Capensb4fb3672016-01-15 17:02:41 -050066 postTransform();
67 computeClipFlags();
Nicolas Capens2ca19032016-01-15 16:54:13 -050068
69 Pointer<Byte> cacheLine0 = vertexCache + tagIndex * UInt((int)sizeof(Vertex));
Nicolas Capensb4fb3672016-01-15 17:02:41 -050070 writeCache(cacheLine0);
Nicolas Capens2ca19032016-01-15 16:54:13 -050071 }
72
73 UInt cacheIndex = index & 0x0000003F;
74 Pointer<Byte> cacheLine = vertexCache + cacheIndex * UInt((int)sizeof(Vertex));
Nicolas Capens00bfa182016-05-20 21:30:54 -070075 writeVertex(vertex, cacheLine);
Nicolas Capens2ca19032016-01-15 16:54:13 -050076
Alexis Hetua62a0ca2016-04-20 15:29:51 -040077 if(state.transformFeedbackEnabled != 0)
78 {
Nicolas Capens00bfa182016-05-20 21:30:54 -070079 transformFeedback(vertex, primitiveNumber, indexInPrimitive);
80
Alexis Hetua62a0ca2016-04-20 15:29:51 -040081 indexInPrimitive++;
82 If(indexInPrimitive == 3)
83 {
84 primitiveNumber++;
85 indexInPrimitive = 0;
86 }
87 }
Nicolas Capens00bfa182016-05-20 21:30:54 -070088
89 vertex += sizeof(Vertex);
90 batch += sizeof(unsigned int);
91 vertexCount--;
Nicolas Capens2ca19032016-01-15 16:54:13 -050092 }
Ben Clayton71af5932019-12-11 10:05:24 +000093 Until(vertexCount == 0);
Nicolas Capens2ca19032016-01-15 16:54:13 -050094
95 Return();
John Bauman89401822014-05-06 15:04:28 -040096 }
97
Nicolas Capensb4fb3672016-01-15 17:02:41 -050098 void VertexRoutine::readInput(UInt &index)
John Bauman89401822014-05-06 15:04:28 -040099 {
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400100 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400101 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500102 Pointer<Byte> input = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,input) + sizeof(void*) * i);
103 UInt stride = *Pointer<UInt>(data + OFFSET(DrawData,stride) + sizeof(unsigned int) * i);
John Bauman89401822014-05-06 15:04:28 -0400104
Nicolas Capens7551ac62016-01-20 17:11:53 -0500105 v[i] = readStream(input, stride, state.input[i], index);
John Bauman89401822014-05-06 15:04:28 -0400106 }
107 }
108
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500109 void VertexRoutine::computeClipFlags()
John Bauman89401822014-05-06 15:04:28 -0400110 {
111 int pos = state.positionRegister;
112
Nicolas Capens7551ac62016-01-20 17:11:53 -0500113 Int4 maxX = CmpLT(o[pos].w, o[pos].x);
114 Int4 maxY = CmpLT(o[pos].w, o[pos].y);
Nicolas Capens00bfa182016-05-20 21:30:54 -0700115 Int4 maxZ = CmpLT(o[pos].w, o[pos].z);
Nicolas Capens7551ac62016-01-20 17:11:53 -0500116 Int4 minX = CmpNLE(-o[pos].w, o[pos].x);
117 Int4 minY = CmpNLE(-o[pos].w, o[pos].y);
Nicolas Capens00bfa182016-05-20 21:30:54 -0700118 Int4 minZ = symmetricNormalizedDepth ? CmpNLE(-o[pos].w, o[pos].z) : CmpNLE(Float4(0.0f), o[pos].z);
John Bauman89401822014-05-06 15:04:28 -0400119
Nicolas Capens00bfa182016-05-20 21:30:54 -0700120 clipFlags = *Pointer<Int>(constants + OFFSET(Constants,maxX) + SignMask(maxX) * 4); // FIXME: Array indexing
121 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxY) + SignMask(maxY) * 4);
122 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,maxZ) + SignMask(maxZ) * 4);
123 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minX) + SignMask(minX) * 4);
124 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minY) + SignMask(minY) * 4);
125 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,minZ) + SignMask(minZ) * 4);
John Bauman89401822014-05-06 15:04:28 -0400126
Nicolas Capens7551ac62016-01-20 17:11:53 -0500127 Int4 finiteX = CmpLE(Abs(o[pos].x), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
128 Int4 finiteY = CmpLE(Abs(o[pos].y), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
Nicolas Capens00bfa182016-05-20 21:30:54 -0700129 Int4 finiteZ = CmpLE(Abs(o[pos].z), *Pointer<Float4>(constants + OFFSET(Constants,maxPos)));
John Bauman89401822014-05-06 15:04:28 -0400130
Nicolas Capens00bfa182016-05-20 21:30:54 -0700131 Int4 finiteXYZ = finiteX & finiteY & finiteZ;
132 clipFlags |= *Pointer<Int>(constants + OFFSET(Constants,fini) + SignMask(finiteXYZ) * 4);
John Bauman89401822014-05-06 15:04:28 -0400133
134 if(state.preTransformed)
135 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500136 clipFlags &= 0xFBFBFBFB; // Don't clip against far clip plane
John Bauman89401822014-05-06 15:04:28 -0400137 }
138 }
139
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500140 Vector4f VertexRoutine::readStream(Pointer<Byte> &buffer, UInt &stride, const Stream &stream, const UInt &index)
John Bauman89401822014-05-06 15:04:28 -0400141 {
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500142 const bool textureSampling = state.textureSampling;
John Bauman89401822014-05-06 15:04:28 -0400143
John Bauman19bac1e2014-05-06 15:23:49 -0400144 Vector4f v;
John Bauman89401822014-05-06 15:04:28 -0400145
146 Pointer<Byte> source0 = buffer + index * stride;
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500147 Pointer<Byte> source1 = source0 + (!textureSampling ? stride : 0);
148 Pointer<Byte> source2 = source1 + (!textureSampling ? stride : 0);
149 Pointer<Byte> source3 = source2 + (!textureSampling ? stride : 0);
John Bauman89401822014-05-06 15:04:28 -0400150
Alexis Hetub7508b82016-09-22 15:36:45 -0400151 bool isNativeFloatAttrib = (stream.attribType == VertexShader::ATTRIBTYPE_FLOAT) || stream.normalized;
152
John Bauman89401822014-05-06 15:04:28 -0400153 switch(stream.type)
154 {
155 case STREAMTYPE_FLOAT:
156 {
157 if(stream.count == 0)
158 {
159 // Null stream, all default components
160 }
John Bauman89401822014-05-06 15:04:28 -0400161 else
162 {
Alexis Hetub7508b82016-09-22 15:36:45 -0400163 if(stream.count == 1)
164 {
165 v.x.x = *Pointer<Float>(source0);
166 v.x.y = *Pointer<Float>(source1);
167 v.x.z = *Pointer<Float>(source2);
168 v.x.w = *Pointer<Float>(source3);
169 }
170 else
171 {
172 v.x = *Pointer<Float4>(source0);
173 v.y = *Pointer<Float4>(source1);
174 v.z = *Pointer<Float4>(source2);
175 v.w = *Pointer<Float4>(source3);
John Bauman89401822014-05-06 15:04:28 -0400176
Alexis Hetub7508b82016-09-22 15:36:45 -0400177 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
178 }
179
180 switch(stream.attribType)
181 {
182 case VertexShader::ATTRIBTYPE_INT:
183 if(stream.count >= 1) v.x = As<Float4>(Int4(v.x));
184 if(stream.count >= 2) v.x = As<Float4>(Int4(v.y));
185 if(stream.count >= 3) v.x = As<Float4>(Int4(v.z));
186 if(stream.count >= 4) v.x = As<Float4>(Int4(v.w));
187 break;
188 case VertexShader::ATTRIBTYPE_UINT:
189 if(stream.count >= 1) v.x = As<Float4>(UInt4(v.x));
190 if(stream.count >= 2) v.x = As<Float4>(UInt4(v.y));
191 if(stream.count >= 3) v.x = As<Float4>(UInt4(v.z));
192 if(stream.count >= 4) v.x = As<Float4>(UInt4(v.w));
193 break;
194 default:
195 break;
196 }
John Bauman89401822014-05-06 15:04:28 -0400197 }
198 }
199 break;
200 case STREAMTYPE_BYTE:
Alexis Hetub7508b82016-09-22 15:36:45 -0400201 if(isNativeFloatAttrib) // Stream: UByte, Shader attrib: Float
John Bauman89401822014-05-06 15:04:28 -0400202 {
203 v.x = Float4(*Pointer<Byte4>(source0));
204 v.y = Float4(*Pointer<Byte4>(source1));
205 v.z = Float4(*Pointer<Byte4>(source2));
206 v.w = Float4(*Pointer<Byte4>(source3));
207
208 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
209
210 if(stream.normalized)
211 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500212 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
213 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
214 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
215 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
John Bauman89401822014-05-06 15:04:28 -0400216 }
217 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400218 else // Stream: UByte, Shader attrib: Int / UInt
219 {
220 v.x = As<Float4>(Int4(*Pointer<Byte4>(source0)));
221 v.y = As<Float4>(Int4(*Pointer<Byte4>(source1)));
222 v.z = As<Float4>(Int4(*Pointer<Byte4>(source2)));
223 v.w = As<Float4>(Int4(*Pointer<Byte4>(source3)));
224
225 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
226 }
John Bauman89401822014-05-06 15:04:28 -0400227 break;
228 case STREAMTYPE_SBYTE:
Alexis Hetub7508b82016-09-22 15:36:45 -0400229 if(isNativeFloatAttrib) // Stream: SByte, Shader attrib: Float
John Bauman89401822014-05-06 15:04:28 -0400230 {
231 v.x = Float4(*Pointer<SByte4>(source0));
232 v.y = Float4(*Pointer<SByte4>(source1));
233 v.z = Float4(*Pointer<SByte4>(source2));
234 v.w = Float4(*Pointer<SByte4>(source3));
235
236 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
237
238 if(stream.normalized)
239 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500240 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
241 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
242 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
243 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleSByte));
John Bauman89401822014-05-06 15:04:28 -0400244 }
245 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400246 else // Stream: SByte, Shader attrib: Int / UInt
247 {
248 v.x = As<Float4>(Int4(*Pointer<SByte4>(source0)));
249 v.y = As<Float4>(Int4(*Pointer<SByte4>(source1)));
250 v.z = As<Float4>(Int4(*Pointer<SByte4>(source2)));
251 v.w = As<Float4>(Int4(*Pointer<SByte4>(source3)));
252
253 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
254 }
John Bauman89401822014-05-06 15:04:28 -0400255 break;
256 case STREAMTYPE_COLOR:
257 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500258 v.x = Float4(*Pointer<Byte4>(source0)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
259 v.y = Float4(*Pointer<Byte4>(source1)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
260 v.z = Float4(*Pointer<Byte4>(source2)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
261 v.w = Float4(*Pointer<Byte4>(source3)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleByte));
John Bauman89401822014-05-06 15:04:28 -0400262
263 transpose4x4(v.x, v.y, v.z, v.w);
264
265 // Swap red and blue
266 Float4 t = v.x;
267 v.x = v.z;
268 v.z = t;
269 }
270 break;
271 case STREAMTYPE_SHORT:
Alexis Hetub7508b82016-09-22 15:36:45 -0400272 if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
John Bauman89401822014-05-06 15:04:28 -0400273 {
274 v.x = Float4(*Pointer<Short4>(source0));
275 v.y = Float4(*Pointer<Short4>(source1));
276 v.z = Float4(*Pointer<Short4>(source2));
277 v.w = Float4(*Pointer<Short4>(source3));
Nicolas Capens2ca19032016-01-15 16:54:13 -0500278
John Bauman89401822014-05-06 15:04:28 -0400279 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
280
281 if(stream.normalized)
282 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500283 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
284 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
285 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
286 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleShort));
Nicolas Capens2ca19032016-01-15 16:54:13 -0500287 }
John Bauman89401822014-05-06 15:04:28 -0400288 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400289 else // Stream: Short, Shader attrib: Int/UInt, no type conversion
290 {
291 v.x = As<Float4>(Int4(*Pointer<Short4>(source0)));
292 v.y = As<Float4>(Int4(*Pointer<Short4>(source1)));
293 v.z = As<Float4>(Int4(*Pointer<Short4>(source2)));
294 v.w = As<Float4>(Int4(*Pointer<Short4>(source3)));
295
296 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
297 }
John Bauman89401822014-05-06 15:04:28 -0400298 break;
299 case STREAMTYPE_USHORT:
Alexis Hetub7508b82016-09-22 15:36:45 -0400300 if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
John Bauman89401822014-05-06 15:04:28 -0400301 {
302 v.x = Float4(*Pointer<UShort4>(source0));
303 v.y = Float4(*Pointer<UShort4>(source1));
304 v.z = Float4(*Pointer<UShort4>(source2));
305 v.w = Float4(*Pointer<UShort4>(source3));
Nicolas Capens2ca19032016-01-15 16:54:13 -0500306
John Bauman89401822014-05-06 15:04:28 -0400307 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
308
309 if(stream.normalized)
310 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500311 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
312 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
313 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
314 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants,unscaleUShort));
John Bauman89401822014-05-06 15:04:28 -0400315 }
316 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400317 else // Stream: UShort, Shader attrib: Int/UInt, no type conversion
318 {
319 v.x = As<Float4>(Int4(*Pointer<UShort4>(source0)));
320 v.y = As<Float4>(Int4(*Pointer<UShort4>(source1)));
321 v.z = As<Float4>(Int4(*Pointer<UShort4>(source2)));
322 v.w = As<Float4>(Int4(*Pointer<UShort4>(source3)));
323
324 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
325 }
John Bauman89401822014-05-06 15:04:28 -0400326 break;
Alexis Hetu25639ea2016-03-18 15:00:09 -0400327 case STREAMTYPE_INT:
Alexis Hetub7508b82016-09-22 15:36:45 -0400328 if(isNativeFloatAttrib) // Stream: Int, Shader attrib: Float
Alexis Hetu25639ea2016-03-18 15:00:09 -0400329 {
Alexis Hetub7508b82016-09-22 15:36:45 -0400330 v.x = Float4(*Pointer<Int4>(source0));
331 v.y = Float4(*Pointer<Int4>(source1));
332 v.z = Float4(*Pointer<Int4>(source2));
333 v.w = Float4(*Pointer<Int4>(source3));
334
335 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
336
Alexis Hetu25639ea2016-03-18 15:00:09 -0400337 if(stream.normalized)
338 {
Alexis Hetu25639ea2016-03-18 15:00:09 -0400339 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
340 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
341 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
342 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleInt));
343 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400344 }
345 else // Stream: Int, Shader attrib: Int/UInt, no type conversion
346 {
347 v.x = *Pointer<Float4>(source0);
348 v.y = *Pointer<Float4>(source1);
349 v.z = *Pointer<Float4>(source2);
350 v.w = *Pointer<Float4>(source3);
Alexis Hetu25639ea2016-03-18 15:00:09 -0400351
Alexis Hetub7508b82016-09-22 15:36:45 -0400352 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
Alexis Hetu25639ea2016-03-18 15:00:09 -0400353 }
354 break;
355 case STREAMTYPE_UINT:
Alexis Hetub7508b82016-09-22 15:36:45 -0400356 if(isNativeFloatAttrib) // Stream: UInt, Shader attrib: Float
Alexis Hetu25639ea2016-03-18 15:00:09 -0400357 {
Alexis Hetub7508b82016-09-22 15:36:45 -0400358 v.x = Float4(*Pointer<UInt4>(source0));
359 v.y = Float4(*Pointer<UInt4>(source1));
360 v.z = Float4(*Pointer<UInt4>(source2));
361 v.w = Float4(*Pointer<UInt4>(source3));
362
363 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
364
Alexis Hetu25639ea2016-03-18 15:00:09 -0400365 if(stream.normalized)
366 {
Alexis Hetu25639ea2016-03-18 15:00:09 -0400367 if(stream.count >= 1) v.x *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
368 if(stream.count >= 2) v.y *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
369 if(stream.count >= 3) v.z *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
370 if(stream.count >= 4) v.w *= *Pointer<Float4>(constants + OFFSET(Constants, unscaleUInt));
371 }
Alexis Hetub7508b82016-09-22 15:36:45 -0400372 }
373 else // Stream: UInt, Shader attrib: Int/UInt, no type conversion
374 {
375 v.x = *Pointer<Float4>(source0);
376 v.y = *Pointer<Float4>(source1);
377 v.z = *Pointer<Float4>(source2);
378 v.w = *Pointer<Float4>(source3);
Alexis Hetu25639ea2016-03-18 15:00:09 -0400379
Alexis Hetub7508b82016-09-22 15:36:45 -0400380 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
Alexis Hetu25639ea2016-03-18 15:00:09 -0400381 }
382 break;
John Bauman89401822014-05-06 15:04:28 -0400383 case STREAMTYPE_UDEC3:
384 {
385 // FIXME: Vectorize
386 {
387 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500388
John Bauman89401822014-05-06 15:04:28 -0400389 x = y = z = *Pointer<Int>(source0);
390
391 v.x.x = Float(x & 0x000003FF);
392 v.x.y = Float(y & 0x000FFC00);
393 v.x.z = Float(z & 0x3FF00000);
394 }
395
396 {
397 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500398
John Bauman89401822014-05-06 15:04:28 -0400399 x = y = z = *Pointer<Int>(source1);
400
401 v.y.x = Float(x & 0x000003FF);
402 v.y.y = Float(y & 0x000FFC00);
403 v.y.z = Float(z & 0x3FF00000);
404 }
405
406 {
407 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500408
John Bauman89401822014-05-06 15:04:28 -0400409 x = y = z = *Pointer<Int>(source2);
410
411 v.z.x = Float(x & 0x000003FF);
412 v.z.y = Float(y & 0x000FFC00);
413 v.z.z = Float(z & 0x3FF00000);
414 }
415
416 {
417 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500418
John Bauman89401822014-05-06 15:04:28 -0400419 x = y = z = *Pointer<Int>(source3);
420
421 v.w.x = Float(x & 0x000003FF);
422 v.w.y = Float(y & 0x000FFC00);
423 v.w.z = Float(z & 0x3FF00000);
424 }
425
426 transpose4x3(v.x, v.y, v.z, v.w);
427
John Bauman19bac1e2014-05-06 15:23:49 -0400428 v.y *= Float4(1.0f / 0x00000400);
429 v.z *= Float4(1.0f / 0x00100000);
John Bauman89401822014-05-06 15:04:28 -0400430 }
431 break;
432 case STREAMTYPE_DEC3N:
433 {
434 // FIXME: Vectorize
435 {
436 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500437
John Bauman89401822014-05-06 15:04:28 -0400438 x = y = z = *Pointer<Int>(source0);
439
440 v.x.x = Float((x << 22) & 0xFFC00000);
441 v.x.y = Float((y << 12) & 0xFFC00000);
442 v.x.z = Float((z << 2) & 0xFFC00000);
443 }
444
445 {
446 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500447
John Bauman89401822014-05-06 15:04:28 -0400448 x = y = z = *Pointer<Int>(source1);
449
450 v.y.x = Float((x << 22) & 0xFFC00000);
451 v.y.y = Float((y << 12) & 0xFFC00000);
452 v.y.z = Float((z << 2) & 0xFFC00000);
453 }
454
455 {
456 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500457
John Bauman89401822014-05-06 15:04:28 -0400458 x = y = z = *Pointer<Int>(source2);
459
460 v.z.x = Float((x << 22) & 0xFFC00000);
461 v.z.y = Float((y << 12) & 0xFFC00000);
462 v.z.z = Float((z << 2) & 0xFFC00000);
463 }
464
465 {
466 Int x, y, z;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500467
John Bauman89401822014-05-06 15:04:28 -0400468 x = y = z = *Pointer<Int>(source3);
469
470 v.w.x = Float((x << 22) & 0xFFC00000);
471 v.w.y = Float((y << 12) & 0xFFC00000);
472 v.w.z = Float((z << 2) & 0xFFC00000);
473 }
474
475 transpose4x3(v.x, v.y, v.z, v.w);
476
John Bauman19bac1e2014-05-06 15:23:49 -0400477 v.x *= Float4(1.0f / 0x00400000 / 511.0f);
478 v.y *= Float4(1.0f / 0x00400000 / 511.0f);
479 v.z *= Float4(1.0f / 0x00400000 / 511.0f);
John Bauman89401822014-05-06 15:04:28 -0400480 }
481 break;
482 case STREAMTYPE_FIXED:
483 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500484 v.x = Float4(*Pointer<Int4>(source0)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
485 v.y = Float4(*Pointer<Int4>(source1)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
486 v.z = Float4(*Pointer<Int4>(source2)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
487 v.w = Float4(*Pointer<Int4>(source3)) * *Pointer<Float4>(constants + OFFSET(Constants,unscaleFixed));
John Bauman89401822014-05-06 15:04:28 -0400488
489 transpose4xN(v.x, v.y, v.z, v.w, stream.count);
490 }
491 break;
492 case STREAMTYPE_HALF:
493 {
494 if(stream.count >= 1)
495 {
496 UShort x0 = *Pointer<UShort>(source0 + 0);
497 UShort x1 = *Pointer<UShort>(source1 + 0);
498 UShort x2 = *Pointer<UShort>(source2 + 0);
499 UShort x3 = *Pointer<UShort>(source3 + 0);
500
Nicolas Capens7551ac62016-01-20 17:11:53 -0500501 v.x.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x0) * 4);
502 v.x.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x1) * 4);
503 v.x.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x2) * 4);
504 v.x.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(x3) * 4);
John Bauman89401822014-05-06 15:04:28 -0400505 }
506
507 if(stream.count >= 2)
508 {
509 UShort y0 = *Pointer<UShort>(source0 + 2);
510 UShort y1 = *Pointer<UShort>(source1 + 2);
511 UShort y2 = *Pointer<UShort>(source2 + 2);
512 UShort y3 = *Pointer<UShort>(source3 + 2);
513
Nicolas Capens7551ac62016-01-20 17:11:53 -0500514 v.y.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y0) * 4);
515 v.y.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y1) * 4);
516 v.y.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y2) * 4);
517 v.y.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(y3) * 4);
John Bauman89401822014-05-06 15:04:28 -0400518 }
519
520 if(stream.count >= 3)
521 {
522 UShort z0 = *Pointer<UShort>(source0 + 4);
523 UShort z1 = *Pointer<UShort>(source1 + 4);
524 UShort z2 = *Pointer<UShort>(source2 + 4);
525 UShort z3 = *Pointer<UShort>(source3 + 4);
526
Nicolas Capens7551ac62016-01-20 17:11:53 -0500527 v.z.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z0) * 4);
528 v.z.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z1) * 4);
529 v.z.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z2) * 4);
530 v.z.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(z3) * 4);
John Bauman89401822014-05-06 15:04:28 -0400531 }
532
533 if(stream.count >= 4)
534 {
535 UShort w0 = *Pointer<UShort>(source0 + 6);
536 UShort w1 = *Pointer<UShort>(source1 + 6);
537 UShort w2 = *Pointer<UShort>(source2 + 6);
538 UShort w3 = *Pointer<UShort>(source3 + 6);
539
Nicolas Capens7551ac62016-01-20 17:11:53 -0500540 v.w.x = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w0) * 4);
541 v.w.y = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w1) * 4);
542 v.w.z = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w2) * 4);
543 v.w.w = *Pointer<Float>(constants + OFFSET(Constants,half2float) + Int(w3) * 4);
John Bauman89401822014-05-06 15:04:28 -0400544 }
545 }
546 break;
547 case STREAMTYPE_INDICES:
548 {
549 v.x.x = *Pointer<Float>(source0);
550 v.x.y = *Pointer<Float>(source1);
551 v.x.z = *Pointer<Float>(source2);
552 v.x.w = *Pointer<Float>(source3);
553 }
554 break;
Alexis Hetu70085ba2016-05-13 22:40:02 -0400555 case STREAMTYPE_2_10_10_10_INT:
556 {
557 Int4 src;
558 src = Insert(src, *Pointer<Int>(source0), 0);
559 src = Insert(src, *Pointer<Int>(source1), 1);
560 src = Insert(src, *Pointer<Int>(source2), 2);
561 src = Insert(src, *Pointer<Int>(source3), 3);
562
563 v.x = Float4((src << 22) >> 22);
564 v.y = Float4((src << 12) >> 22);
565 v.z = Float4((src << 02) >> 22);
566 v.w = Float4(src >> 30);
567
568 if(stream.normalized)
569 {
570 v.x = Max(v.x * Float4(1.0f / 0x1FF), Float4(-1.0f));
571 v.y = Max(v.y * Float4(1.0f / 0x1FF), Float4(-1.0f));
572 v.z = Max(v.z * Float4(1.0f / 0x1FF), Float4(-1.0f));
573 v.w = Max(v.w, Float4(-1.0f));
574 }
575 }
576 break;
577 case STREAMTYPE_2_10_10_10_UINT:
578 {
579 Int4 src;
580 src = Insert(src, *Pointer<Int>(source0), 0);
581 src = Insert(src, *Pointer<Int>(source1), 1);
582 src = Insert(src, *Pointer<Int>(source2), 2);
583 src = Insert(src, *Pointer<Int>(source3), 3);
584
585 v.x = Float4(src & Int4(0x3FF));
586 v.y = Float4((src >> 10) & Int4(0x3FF));
587 v.z = Float4((src >> 20) & Int4(0x3FF));
588 v.w = Float4((src >> 30) & Int4(0x3));
589
590 if(stream.normalized)
591 {
592 v.x *= Float4(1.0f / 0x3FF);
593 v.y *= Float4(1.0f / 0x3FF);
594 v.z *= Float4(1.0f / 0x3FF);
595 v.w *= Float4(1.0f / 0x3);
596 }
597 }
598 break;
John Bauman89401822014-05-06 15:04:28 -0400599 default:
600 ASSERT(false);
601 }
602
John Bauman19bac1e2014-05-06 15:23:49 -0400603 if(stream.count < 1) v.x = Float4(0.0f);
604 if(stream.count < 2) v.y = Float4(0.0f);
605 if(stream.count < 3) v.z = Float4(0.0f);
Alexis Hetu853e48d2016-09-28 14:16:44 -0400606 if(stream.count < 4) v.w = isNativeFloatAttrib ? As<Float4>(Float4(1.0f)) : As<Float4>(Int4(0));
John Bauman89401822014-05-06 15:04:28 -0400607
608 return v;
609 }
610
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500611 void VertexRoutine::postTransform()
John Bauman89401822014-05-06 15:04:28 -0400612 {
613 int pos = state.positionRegister;
614
Nicolas Capens35227c82015-07-21 01:28:04 -0400615 // Backtransform
616 if(state.preTransformed)
617 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500618 Float4 rhw = Float4(1.0f) / o[pos].w;
Nicolas Capens35227c82015-07-21 01:28:04 -0400619
Nicolas Capens7551ac62016-01-20 17:11:53 -0500620 Float4 W = *Pointer<Float4>(data + OFFSET(DrawData,Wx16)) * Float4(1.0f / 16.0f);
621 Float4 H = *Pointer<Float4>(data + OFFSET(DrawData,Hx16)) * Float4(1.0f / 16.0f);
622 Float4 L = *Pointer<Float4>(data + OFFSET(DrawData,X0x16)) * Float4(1.0f / 16.0f);
623 Float4 T = *Pointer<Float4>(data + OFFSET(DrawData,Y0x16)) * Float4(1.0f / 16.0f);
Nicolas Capens35227c82015-07-21 01:28:04 -0400624
Nicolas Capens7551ac62016-01-20 17:11:53 -0500625 o[pos].x = (o[pos].x - L) / W * rhw;
626 o[pos].y = (o[pos].y - T) / H * rhw;
627 o[pos].z = o[pos].z * rhw;
628 o[pos].w = rhw;
Nicolas Capens35227c82015-07-21 01:28:04 -0400629 }
630
Nicolas Capens887bc442015-07-21 01:29:49 -0400631 if(!halfIntegerCoordinates && !state.preTransformed)
John Bauman89401822014-05-06 15:04:28 -0400632 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500633 o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelX)) * o[pos].w;
634 o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,halfPixelY)) * o[pos].w;
John Bauman19bac1e2014-05-06 15:23:49 -0400635 }
John Bauman89401822014-05-06 15:04:28 -0400636
Nicolas Capens35227c82015-07-21 01:28:04 -0400637 if(state.superSampling)
638 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500639 o[pos].x = o[pos].x + *Pointer<Float4>(data + OFFSET(DrawData,XXXX)) * o[pos].w;
640 o[pos].y = o[pos].y + *Pointer<Float4>(data + OFFSET(DrawData,YYYY)) * o[pos].w;
Nicolas Capens35227c82015-07-21 01:28:04 -0400641 }
John Bauman89401822014-05-06 15:04:28 -0400642 }
643
Nicolas Capensb4fb3672016-01-15 17:02:41 -0500644 void VertexRoutine::writeCache(Pointer<Byte> &cacheLine)
John Bauman89401822014-05-06 15:04:28 -0400645 {
John Bauman19bac1e2014-05-06 15:23:49 -0400646 Vector4f v;
John Bauman89401822014-05-06 15:04:28 -0400647
Nicolas Capensec0936c2016-05-18 12:32:02 -0400648 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400649 {
650 if(state.output[i].write)
651 {
Nicolas Capens7551ac62016-01-20 17:11:53 -0500652 v.x = o[i].x;
653 v.y = o[i].y;
654 v.z = o[i].z;
655 v.w = o[i].w;
John Bauman89401822014-05-06 15:04:28 -0400656
657 if(state.output[i].xClamp)
658 {
John Bauman19bac1e2014-05-06 15:23:49 -0400659 v.x = Max(v.x, Float4(0.0f));
660 v.x = Min(v.x, Float4(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400661 }
662
663 if(state.output[i].yClamp)
664 {
John Bauman19bac1e2014-05-06 15:23:49 -0400665 v.y = Max(v.y, Float4(0.0f));
666 v.y = Min(v.y, Float4(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400667 }
668
669 if(state.output[i].zClamp)
670 {
John Bauman19bac1e2014-05-06 15:23:49 -0400671 v.z = Max(v.z, Float4(0.0f));
672 v.z = Min(v.z, Float4(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400673 }
674
675 if(state.output[i].wClamp)
676 {
John Bauman19bac1e2014-05-06 15:23:49 -0400677 v.w = Max(v.w, Float4(0.0f));
678 v.w = Min(v.w, Float4(1.0f));
John Bauman89401822014-05-06 15:04:28 -0400679 }
680
681 if(state.output[i].write == 0x01)
682 {
683 *Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 0) = v.x.x;
684 *Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 1) = v.x.y;
685 *Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 2) = v.x.z;
686 *Pointer<Float>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 3) = v.x.w;
687 }
688 else
689 {
Nicolas Capens54ac5e82016-12-09 14:07:50 -0500690 if(state.output[i].write == 0x03)
John Bauman89401822014-05-06 15:04:28 -0400691 {
692 transpose2x4(v.x, v.y, v.z, v.w);
693 }
694 else
695 {
696 transpose4x4(v.x, v.y, v.z, v.w);
697 }
698
699 *Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 0, 16) = v.x;
700 *Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 1, 16) = v.y;
701 *Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 2, 16) = v.z;
702 *Pointer<Float4>(cacheLine + OFFSET(Vertex,v[i]) + sizeof(Vertex) * 3, 16) = v.w;
703 }
704 }
705 }
706
Nicolas Capens2543bd72016-05-17 13:04:01 -0400707 *Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 0) = (clipFlags >> 0) & 0x0000000FF;
Nicolas Capens7551ac62016-01-20 17:11:53 -0500708 *Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 1) = (clipFlags >> 8) & 0x0000000FF;
709 *Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 2) = (clipFlags >> 16) & 0x0000000FF;
710 *Pointer<Int>(cacheLine + OFFSET(Vertex,clipFlags) + sizeof(Vertex) * 3) = (clipFlags >> 24) & 0x0000000FF;
John Bauman89401822014-05-06 15:04:28 -0400711
Nicolas Capens00bfa182016-05-20 21:30:54 -0700712 // Viewport transform
John Bauman89401822014-05-06 15:04:28 -0400713 int pos = state.positionRegister;
714
Nicolas Capens7551ac62016-01-20 17:11:53 -0500715 v.x = o[pos].x;
716 v.y = o[pos].y;
717 v.z = o[pos].z;
718 v.w = o[pos].w;
John Bauman89401822014-05-06 15:04:28 -0400719
Nicolas Capens00bfa182016-05-20 21:30:54 -0700720 if(symmetricNormalizedDepth)
721 {
722 v.z = (v.z + v.w) * Float4(0.5f); // [-1, 1] -> [0, 1]
723 }
724
John Bauman19bac1e2014-05-06 15:23:49 -0400725 Float4 w = As<Float4>(As<Int4>(v.w) | (As<Int4>(CmpEQ(v.w, Float4(0.0f))) & As<Int4>(Float4(1.0f))));
John Bauman89401822014-05-06 15:04:28 -0400726 Float4 rhw = Float4(1.0f) / w;
727
Nicolas Capens7551ac62016-01-20 17:11:53 -0500728 v.x = As<Float4>(RoundInt(*Pointer<Float4>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float4>(data + OFFSET(DrawData,Wx16))));
729 v.y = As<Float4>(RoundInt(*Pointer<Float4>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float4>(data + OFFSET(DrawData,Hx16))));
John Bauman89401822014-05-06 15:04:28 -0400730 v.z = v.z * rhw;
731 v.w = rhw;
732
733 transpose4x4(v.x, v.y, v.z, v.w);
734
735 *Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 0, 16) = v.x;
736 *Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 1, 16) = v.y;
737 *Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 2, 16) = v.z;
738 *Pointer<Float4>(cacheLine + OFFSET(Vertex,X) + sizeof(Vertex) * 3, 16) = v.w;
739 }
740
Nicolas Capens00bfa182016-05-20 21:30:54 -0700741 void VertexRoutine::writeVertex(const Pointer<Byte> &vertex, Pointer<Byte> &cache)
John Bauman89401822014-05-06 15:04:28 -0400742 {
Nicolas Capensec0936c2016-05-18 12:32:02 -0400743 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400744 {
745 if(state.output[i].write)
746 {
Nicolas Capens2543bd72016-05-17 13:04:01 -0400747 *Pointer<Int4>(vertex + OFFSET(Vertex,v[i]), 16) = *Pointer<Int4>(cache + OFFSET(Vertex,v[i]), 16);
John Bauman89401822014-05-06 15:04:28 -0400748 }
749 }
750
Nicolas Capens2543bd72016-05-17 13:04:01 -0400751 *Pointer<Int4>(vertex + OFFSET(Vertex,X)) = *Pointer<Int4>(cache + OFFSET(Vertex,X));
John Bauman89401822014-05-06 15:04:28 -0400752 *Pointer<Int>(vertex + OFFSET(Vertex,clipFlags)) = *Pointer<Int>(cache + OFFSET(Vertex,clipFlags));
Nicolas Capens00bfa182016-05-20 21:30:54 -0700753 }
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400754
Nicolas Capens00bfa182016-05-20 21:30:54 -0700755 void VertexRoutine::transformFeedback(const Pointer<Byte> &vertex, const UInt &primitiveNumber, const UInt &indexInPrimitive)
756 {
757 If(indexInPrimitive < state.verticesPerPrimitive)
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400758 {
Nicolas Capens00bfa182016-05-20 21:30:54 -0700759 UInt tOffset = primitiveNumber * state.verticesPerPrimitive + indexInPrimitive;
760
761 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; i++)
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400762 {
Nicolas Capens00bfa182016-05-20 21:30:54 -0700763 if(state.transformFeedbackEnabled & (1ULL << i))
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400764 {
Nicolas Capens00bfa182016-05-20 21:30:54 -0700765 UInt reg = *Pointer<UInt>(data + OFFSET(DrawData, vs.reg[i]));
766 UInt row = *Pointer<UInt>(data + OFFSET(DrawData, vs.row[i]));
767 UInt col = *Pointer<UInt>(data + OFFSET(DrawData, vs.col[i]));
768 UInt str = *Pointer<UInt>(data + OFFSET(DrawData, vs.str[i]));
769
770 Pointer<Byte> t = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, vs.t[i])) + (tOffset * str * sizeof(float));
771 Pointer<Byte> v = vertex + OFFSET(Vertex, v) + reg * sizeof(float);
772
773 For(UInt r = 0, r < row, r++)
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400774 {
Nicolas Capens00bfa182016-05-20 21:30:54 -0700775 UInt rOffsetX = r * col * sizeof(float);
776 UInt rOffset4 = r * sizeof(float4);
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400777
Nicolas Capens00bfa182016-05-20 21:30:54 -0700778 For(UInt c = 0, c < col, c++)
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400779 {
Nicolas Capens00bfa182016-05-20 21:30:54 -0700780 UInt cOffset = c * sizeof(float);
781 *Pointer<Float>(t + rOffsetX + cOffset) = *Pointer<Float>(v + rOffset4 + cOffset);
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400782 }
783 }
784 }
785 }
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400786 }
John Bauman89401822014-05-06 15:04:28 -0400787 }
788}