blob: 246e2783c4f7bc935ff83e720dee1e444fb9fc85 [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 "VertexProcessor.hpp"
16
Nicolas Capens708c24b2017-10-26 13:07:10 -040017#include "Shader/VertexPipeline.hpp"
18#include "Shader/VertexProgram.hpp"
19#include "Shader/VertexShader.hpp"
20#include "Shader/PixelShader.hpp"
21#include "Shader/Constants.hpp"
22#include "Common/Math.hpp"
23#include "Common/Debug.hpp"
John Bauman89401822014-05-06 15:04:28 -040024
Nicolas Capens92eb0412019-08-20 14:13:17 -040025#include <cstring>
John Bauman89401822014-05-06 15:04:28 -040026
27namespace sw
28{
John Bauman66b8ab22014-05-06 15:57:45 -040029 bool precacheVertex = false;
30
John Bauman89401822014-05-06 15:04:28 -040031 void VertexCache::clear()
32 {
33 for(int i = 0; i < 16; i++)
34 {
35 tag[i] = 0x80000000;
36 }
37 }
38
Nicolas Capens92eb0412019-08-20 14:13:17 -040039 uint32_t VertexProcessor::States::computeHash()
John Bauman89401822014-05-06 15:04:28 -040040 {
Nicolas Capens92eb0412019-08-20 14:13:17 -040041 uint32_t *state = reinterpret_cast<uint32_t*>(this);
42 uint32_t hash = 0;
John Bauman89401822014-05-06 15:04:28 -040043
Nicolas Capens92eb0412019-08-20 14:13:17 -040044 for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
John Bauman89401822014-05-06 15:04:28 -040045 {
46 hash ^= state[i];
47 }
48
49 return hash;
50 }
51
John Bauman89401822014-05-06 15:04:28 -040052 bool VertexProcessor::State::operator==(const State &state) const
53 {
54 if(hash != state.hash)
55 {
56 return false;
57 }
58
Nicolas Capens92eb0412019-08-20 14:13:17 -040059 static_assert(is_memcmparable<State>::value, "Cannot memcmp States");
John Bauman89401822014-05-06 15:04:28 -040060 return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
61 }
62
Alexis Hetu772d2492016-04-04 16:14:58 -040063 VertexProcessor::TransformFeedbackInfo::TransformFeedbackInfo()
64 {
Alexis Hetu772d2492016-04-04 16:14:58 -040065 buffer = nullptr;
66 offset = 0;
67 reg = 0;
68 row = 0;
69 col = 0;
70 stride = 0;
71 }
72
Alexis Hetuc6a57cb2016-04-07 10:48:31 -040073 VertexProcessor::UniformBufferInfo::UniformBufferInfo()
74 {
75 buffer = nullptr;
76 offset = 0;
77 }
78
John Bauman89401822014-05-06 15:04:28 -040079 VertexProcessor::VertexProcessor(Context *context) : context(context)
80 {
81 for(int i = 0; i < 12; i++)
82 {
83 M[i] = 1;
84 }
85
86 V = 1;
87 B = 1;
88 P = 0;
89 PB = 0;
90 PBV = 0;
Nicolas Capens2ca19032016-01-15 16:54:13 -050091
John Bauman89401822014-05-06 15:04:28 -040092 for(int i = 0; i < 12; i++)
93 {
94 PBVM[i] = 0;
95 }
96
97 setLightingEnable(true);
98 setSpecularEnable(false);
99
100 for(int i = 0; i < 8; i++)
101 {
102 setLightEnable(i, false);
103 setLightPosition(i, 0);
104 }
105
106 updateMatrix = true;
107 updateViewMatrix = true;
108 updateBaseMatrix = true;
109 updateProjectionMatrix = true;
110 updateLighting = true;
111
112 for(int i = 0; i < 12; i++)
113 {
114 updateModelMatrix[i] = true;
115 }
116
Nicolas Capens92eb0412019-08-20 14:13:17 -0400117 routineCache = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400118 setRoutineCacheSize(1024);
119 }
120
121 VertexProcessor::~VertexProcessor()
122 {
123 delete routineCache;
Nicolas Capens92eb0412019-08-20 14:13:17 -0400124 routineCache = nullptr;
John Bauman89401822014-05-06 15:04:28 -0400125 }
126
127 void VertexProcessor::setInputStream(int index, const Stream &stream)
128 {
129 context->input[index] = stream;
130 }
131
John Bauman89401822014-05-06 15:04:28 -0400132 void VertexProcessor::resetInputStreams(bool preTransformed)
133 {
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400134 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400135 {
136 context->input[i].defaults();
137 }
138
139 context->preTransformed = preTransformed;
140 }
141
142 void VertexProcessor::setFloatConstant(unsigned int index, const float value[4])
143 {
Alexis Hetu028f41b2016-01-13 14:40:47 -0500144 if(index < VERTEX_UNIFORM_VECTORS)
John Bauman89401822014-05-06 15:04:28 -0400145 {
146 c[index][0] = value[0];
147 c[index][1] = value[1];
148 c[index][2] = value[2];
149 c[index][3] = value[3];
150 }
151 else ASSERT(false);
152 }
153
154 void VertexProcessor::setIntegerConstant(unsigned int index, const int integer[4])
155 {
156 if(index < 16)
157 {
158 i[index][0] = integer[0];
159 i[index][1] = integer[1];
160 i[index][2] = integer[2];
161 i[index][3] = integer[3];
162 }
163 else ASSERT(false);
164 }
165
166 void VertexProcessor::setBooleanConstant(unsigned int index, int boolean)
167 {
168 if(index < 16)
169 {
170 b[index] = boolean != 0;
171 }
172 else ASSERT(false);
173 }
174
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400175 void VertexProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset)
176 {
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400177 uniformBufferInfo[index].buffer = buffer;
178 uniformBufferInfo[index].offset = offset;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400179 }
180
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400181 void VertexProcessor::lockUniformBuffers(byte** u, sw::Resource* uniformBuffers[])
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400182 {
183 for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
184 {
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400185 u[i] = uniformBufferInfo[i].buffer ? static_cast<byte*>(uniformBufferInfo[i].buffer->lock(PUBLIC, PRIVATE)) + uniformBufferInfo[i].offset : nullptr;
186 uniformBuffers[i] = uniformBufferInfo[i].buffer;
Alexis Hetu2c2a7b22015-10-27 16:12:11 -0400187 }
188 }
189
Alexis Hetu1d672442016-06-23 11:24:00 -0400190 void VertexProcessor::setTransformFeedbackBuffer(int index, sw::Resource* buffer, int offset, unsigned int reg, unsigned int row, unsigned int col, unsigned int stride)
Alexis Hetu772d2492016-04-04 16:14:58 -0400191 {
192 transformFeedbackInfo[index].buffer = buffer;
193 transformFeedbackInfo[index].offset = offset;
194 transformFeedbackInfo[index].reg = reg;
195 transformFeedbackInfo[index].row = row;
196 transformFeedbackInfo[index].col = col;
197 transformFeedbackInfo[index].stride = stride;
198 }
199
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400200 void VertexProcessor::lockTransformFeedbackBuffers(byte** t, unsigned int* v, unsigned int* r, unsigned int* c, unsigned int* s, sw::Resource* transformFeedbackBuffers[])
Alexis Hetu772d2492016-04-04 16:14:58 -0400201 {
202 for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++i)
203 {
204 t[i] = transformFeedbackInfo[i].buffer ? static_cast<byte*>(transformFeedbackInfo[i].buffer->lock(PUBLIC, PRIVATE)) + transformFeedbackInfo[i].offset : nullptr;
Alexis Hetuc6a57cb2016-04-07 10:48:31 -0400205 transformFeedbackBuffers[i] = transformFeedbackInfo[i].buffer;
Alexis Hetu772d2492016-04-04 16:14:58 -0400206 v[i] = transformFeedbackInfo[i].reg;
207 r[i] = transformFeedbackInfo[i].row;
208 c[i] = transformFeedbackInfo[i].col;
209 s[i] = transformFeedbackInfo[i].stride;
210 }
211 }
212
John Bauman89401822014-05-06 15:04:28 -0400213 void VertexProcessor::setModelMatrix(const Matrix &M, int i)
214 {
215 if(i < 12)
216 {
217 this->M[i] = M;
218
219 updateMatrix = true;
220 updateModelMatrix[i] = true;
221 updateLighting = true;
222 }
223 else ASSERT(false);
224 }
225
226 void VertexProcessor::setViewMatrix(const Matrix &V)
227 {
228 this->V = V;
229
230 updateMatrix = true;
231 updateViewMatrix = true;
232 }
233
234 void VertexProcessor::setBaseMatrix(const Matrix &B)
235 {
236 this->B = B;
237
238 updateMatrix = true;
239 updateBaseMatrix = true;
240 }
241
242 void VertexProcessor::setProjectionMatrix(const Matrix &P)
243 {
244 this->P = P;
245 context->wBasedFog = (P[3][0] != 0.0f) || (P[3][1] != 0.0f) || (P[3][2] != 0.0f) || (P[3][3] != 1.0f);
246
247 updateMatrix = true;
248 updateProjectionMatrix = true;
249 }
250
251 void VertexProcessor::setLightingEnable(bool lightingEnable)
252 {
253 context->setLightingEnable(lightingEnable);
254
255 updateLighting = true;
256 }
257
258 void VertexProcessor::setLightEnable(unsigned int light, bool lightEnable)
259 {
260 if(light < 8)
261 {
262 context->setLightEnable(light, lightEnable);
263 }
264 else ASSERT(false);
265
266 updateLighting = true;
267 }
268
269 void VertexProcessor::setSpecularEnable(bool specularEnable)
270 {
271 context->setSpecularEnable(specularEnable);
272
273 updateLighting = true;
274 }
275
276 void VertexProcessor::setLightPosition(unsigned int light, const Point &lightPosition)
277 {
278 if(light < 8)
279 {
280 context->setLightPosition(light, lightPosition);
281 }
282 else ASSERT(false);
283
284 updateLighting = true;
285 }
286
287 void VertexProcessor::setLightDiffuse(unsigned int light, const Color<float> &lightDiffuse)
288 {
289 if(light < 8)
290 {
291 ff.lightDiffuse[light][0] = lightDiffuse.r;
292 ff.lightDiffuse[light][1] = lightDiffuse.g;
293 ff.lightDiffuse[light][2] = lightDiffuse.b;
294 ff.lightDiffuse[light][3] = lightDiffuse.a;
295 }
296 else ASSERT(false);
297 }
298
299 void VertexProcessor::setLightSpecular(unsigned int light, const Color<float> &lightSpecular)
300 {
301 if(light < 8)
302 {
303 ff.lightSpecular[light][0] = lightSpecular.r;
304 ff.lightSpecular[light][1] = lightSpecular.g;
305 ff.lightSpecular[light][2] = lightSpecular.b;
306 ff.lightSpecular[light][3] = lightSpecular.a;
307 }
308 else ASSERT(false);
309 }
310
311 void VertexProcessor::setLightAmbient(unsigned int light, const Color<float> &lightAmbient)
312 {
313 if(light < 8)
314 {
315 ff.lightAmbient[light][0] = lightAmbient.r;
316 ff.lightAmbient[light][1] = lightAmbient.g;
317 ff.lightAmbient[light][2] = lightAmbient.b;
318 ff.lightAmbient[light][3] = lightAmbient.a;
319 }
320 else ASSERT(false);
321 }
322
323 void VertexProcessor::setLightAttenuation(unsigned int light, float constant, float linear, float quadratic)
324 {
325 if(light < 8)
326 {
Nicolas Capens2ca19032016-01-15 16:54:13 -0500327 ff.attenuationConstant[light] = replicate(constant);
John Bauman89401822014-05-06 15:04:28 -0400328 ff.attenuationLinear[light] = replicate(linear);
329 ff.attenuationQuadratic[light] = replicate(quadratic);
330 }
331 else ASSERT(false);
332 }
333
334 void VertexProcessor::setLightRange(unsigned int light, float lightRange)
335 {
336 if(light < 8)
337 {
338 ff.lightRange[light] = lightRange;
339 }
340 else ASSERT(false);
341 }
342
343 void VertexProcessor::setFogEnable(bool fogEnable)
344 {
345 context->fogEnable = fogEnable;
346 }
347
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400348 void VertexProcessor::setVertexFogMode(FogMode fogMode)
John Bauman89401822014-05-06 15:04:28 -0400349 {
350 context->vertexFogMode = fogMode;
351 }
352
Alexis Hetu6743bbf2015-04-21 17:06:14 -0400353 void VertexProcessor::setInstanceID(int instanceID)
354 {
355 context->instanceID = instanceID;
356 }
357
John Bauman89401822014-05-06 15:04:28 -0400358 void VertexProcessor::setColorVertexEnable(bool colorVertexEnable)
359 {
360 context->setColorVertexEnable(colorVertexEnable);
361 }
362
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400363 void VertexProcessor::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
John Bauman89401822014-05-06 15:04:28 -0400364 {
365 context->setDiffuseMaterialSource(diffuseMaterialSource);
366 }
367
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400368 void VertexProcessor::setSpecularMaterialSource(MaterialSource specularMaterialSource)
John Bauman89401822014-05-06 15:04:28 -0400369 {
370 context->setSpecularMaterialSource(specularMaterialSource);
371 }
372
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400373 void VertexProcessor::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
John Bauman89401822014-05-06 15:04:28 -0400374 {
375 context->setAmbientMaterialSource(ambientMaterialSource);
376 }
377
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400378 void VertexProcessor::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
John Bauman89401822014-05-06 15:04:28 -0400379 {
380 context->setEmissiveMaterialSource(emissiveMaterialSource);
381 }
382
383 void VertexProcessor::setGlobalAmbient(const Color<float> &globalAmbient)
384 {
385 ff.globalAmbient[0] = globalAmbient.r;
386 ff.globalAmbient[1] = globalAmbient.g;
387 ff.globalAmbient[2] = globalAmbient.b;
388 ff.globalAmbient[3] = globalAmbient.a;
389 }
390
391 void VertexProcessor::setMaterialEmission(const Color<float> &emission)
392 {
393 ff.materialEmission[0] = emission.r;
394 ff.materialEmission[1] = emission.g;
395 ff.materialEmission[2] = emission.b;
396 ff.materialEmission[3] = emission.a;
397 }
398
399 void VertexProcessor::setMaterialAmbient(const Color<float> &materialAmbient)
400 {
401 ff.materialAmbient[0] = materialAmbient.r;
402 ff.materialAmbient[1] = materialAmbient.g;
403 ff.materialAmbient[2] = materialAmbient.b;
404 ff.materialAmbient[3] = materialAmbient.a;
405 }
406
407 void VertexProcessor::setMaterialDiffuse(const Color<float> &diffuseColor)
408 {
409 ff.materialDiffuse[0] = diffuseColor.r;
410 ff.materialDiffuse[1] = diffuseColor.g;
411 ff.materialDiffuse[2] = diffuseColor.b;
412 ff.materialDiffuse[3] = diffuseColor.a;
413 }
414
415 void VertexProcessor::setMaterialSpecular(const Color<float> &specularColor)
416 {
417 ff.materialSpecular[0] = specularColor.r;
418 ff.materialSpecular[1] = specularColor.g;
419 ff.materialSpecular[2] = specularColor.b;
420 ff.materialSpecular[3] = specularColor.a;
421 }
422
423 void VertexProcessor::setMaterialShininess(float specularPower)
424 {
425 ff.materialShininess = specularPower;
426 }
427
428 void VertexProcessor::setLightViewPosition(unsigned int light, const Point &P)
429 {
430 if(light < 8)
431 {
432 ff.lightPosition[light][0] = P.x;
433 ff.lightPosition[light][1] = P.y;
434 ff.lightPosition[light][2] = P.z;
435 ff.lightPosition[light][3] = 1;
436 }
437 else ASSERT(false);
438 }
439
440 void VertexProcessor::setRangeFogEnable(bool enable)
441 {
442 context->rangeFogEnable = enable;
443 }
444
445 void VertexProcessor::setIndexedVertexBlendEnable(bool indexedVertexBlendEnable)
446 {
447 context->indexedVertexBlendEnable = indexedVertexBlendEnable;
448 }
449
450 void VertexProcessor::setVertexBlendMatrixCount(unsigned int vertexBlendMatrixCount)
451 {
452 if(vertexBlendMatrixCount <= 4)
453 {
454 context->vertexBlendMatrixCount = vertexBlendMatrixCount;
455 }
456 else ASSERT(false);
457 }
458
459 void VertexProcessor::setTextureWrap(unsigned int stage, int mask)
460 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400461 if(stage < TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400462 {
463 context->textureWrap[stage] = mask;
464 }
465 else ASSERT(false);
466
467 context->textureWrapActive = false;
468
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400469 for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -0400470 {
471 context->textureWrapActive |= (context->textureWrap[i] != 0x00);
472 }
473 }
474
Nicolas Capensa0f4be82014-10-22 14:35:30 -0400475 void VertexProcessor::setTexGen(unsigned int stage, TexGen texGen)
John Bauman89401822014-05-06 15:04:28 -0400476 {
477 if(stage < 8)
478 {
479 context->texGen[stage] = texGen;
480 }
481 else ASSERT(false);
482 }
483
484 void VertexProcessor::setLocalViewer(bool localViewer)
485 {
486 context->localViewer = localViewer;
487 }
488
489 void VertexProcessor::setNormalizeNormals(bool normalizeNormals)
490 {
491 context->normalizeNormals = normalizeNormals;
492 }
493
494 void VertexProcessor::setTextureMatrix(int stage, const Matrix &T)
495 {
496 for(int i = 0; i < 4; i++)
497 {
498 for(int j = 0; j < 4; j++)
499 {
500 ff.textureTransform[stage][i][j] = T[i][j];
501 }
502 }
503 }
504
505 void VertexProcessor::setTextureTransform(int stage, int count, bool project)
506 {
507 context->textureTransformCount[stage] = count;
508 context->textureTransformProject[stage] = project;
509 }
510
511 void VertexProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
512 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400513 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400514 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400515 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setTextureFilter(textureFilter);
John Bauman89401822014-05-06 15:04:28 -0400516 }
517 else ASSERT(false);
518 }
519
520 void VertexProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
521 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400522 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400523 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400524 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMipmapFilter(mipmapFilter);
John Bauman89401822014-05-06 15:04:28 -0400525 }
526 else ASSERT(false);
527 }
528
529 void VertexProcessor::setGatherEnable(unsigned int sampler, bool enable)
530 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400531 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400532 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400533 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setGatherEnable(enable);
John Bauman89401822014-05-06 15:04:28 -0400534 }
535 else ASSERT(false);
536 }
537
538 void VertexProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
539 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400540 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400541 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400542 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeU(addressMode);
John Bauman89401822014-05-06 15:04:28 -0400543 }
544 else ASSERT(false);
545 }
546
547 void VertexProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
548 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400549 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400550 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400551 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeV(addressMode);
John Bauman89401822014-05-06 15:04:28 -0400552 }
553 else ASSERT(false);
554 }
555
556 void VertexProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
557 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400558 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400559 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400560 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeW(addressMode);
John Bauman89401822014-05-06 15:04:28 -0400561 }
562 else ASSERT(false);
563 }
564
565 void VertexProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
566 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400567 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400568 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400569 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setReadSRGB(sRGB);
John Bauman89401822014-05-06 15:04:28 -0400570 }
571 else ASSERT(false);
572 }
573
574 void VertexProcessor::setMipmapLOD(unsigned int sampler, float bias)
575 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400576 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400577 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400578 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMipmapLOD(bias);
John Bauman89401822014-05-06 15:04:28 -0400579 }
580 else ASSERT(false);
581 }
582
583 void VertexProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
584 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400585 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400586 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400587 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setBorderColor(borderColor);
John Bauman89401822014-05-06 15:04:28 -0400588 }
589 else ASSERT(false);
590 }
591
Alexis Hetu617a5d52014-11-13 10:56:20 -0500592 void VertexProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
John Bauman89401822014-05-06 15:04:28 -0400593 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400594 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
John Bauman89401822014-05-06 15:04:28 -0400595 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400596 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMaxAnisotropy(maxAnisotropy);
John Bauman89401822014-05-06 15:04:28 -0400597 }
598 else ASSERT(false);
599 }
600
Alexis Hetu010a4642017-07-18 14:33:04 -0400601 void VertexProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering)
602 {
603 if(sampler < TEXTURE_IMAGE_UNITS)
604 {
605 context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering);
606 }
607 else ASSERT(false);
608 }
609
Alexis Hetu1d01aa32015-09-29 11:50:05 -0400610 void VertexProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
611 {
612 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
613 {
614 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleR(swizzleR);
615 }
616 else ASSERT(false);
617 }
618
619 void VertexProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
620 {
621 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
622 {
623 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleG(swizzleG);
624 }
625 else ASSERT(false);
626 }
627
628 void VertexProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
629 {
630 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
631 {
632 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleB(swizzleB);
633 }
634 else ASSERT(false);
635 }
636
637 void VertexProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
638 {
639 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
640 {
641 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleA(swizzleA);
642 }
643 else ASSERT(false);
644 }
645
Nicolas Capensf878d502017-11-06 15:29:46 -0500646 void VertexProcessor::setCompareFunc(unsigned int sampler, CompareFunc compFunc)
647 {
648 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
649 {
650 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setCompareFunc(compFunc);
651 }
652 else ASSERT(false);
653 }
654
Alexis Hetu95ac1872016-06-06 13:26:52 -0400655 void VertexProcessor::setBaseLevel(unsigned int sampler, int baseLevel)
656 {
657 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
658 {
659 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setBaseLevel(baseLevel);
660 }
661 else ASSERT(false);
662 }
663
664 void VertexProcessor::setMaxLevel(unsigned int sampler, int maxLevel)
665 {
666 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
667 {
668 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMaxLevel(maxLevel);
669 }
670 else ASSERT(false);
671 }
672
Alexis Hetu112d81f2016-06-07 12:36:35 -0400673 void VertexProcessor::setMinLod(unsigned int sampler, float minLod)
674 {
675 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
676 {
677 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMinLod(minLod);
678 }
679 else ASSERT(false);
680 }
681
682 void VertexProcessor::setMaxLod(unsigned int sampler, float maxLod)
683 {
684 if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
685 {
686 context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMaxLod(maxLod);
687 }
688 else ASSERT(false);
689 }
690
Alexis Hetu88482c32018-06-05 17:05:17 -0400691 void VertexProcessor::setSyncRequired(unsigned int sampler, bool isSincRequired)
692 {
693 if(sampler < TEXTURE_IMAGE_UNITS)
694 {
695 context->sampler[sampler].setSyncRequired(isSincRequired);
696 }
697 else ASSERT(false);
698 }
699
John Bauman89401822014-05-06 15:04:28 -0400700 void VertexProcessor::setPointSize(float pointSize)
701 {
702 point.pointSize = replicate(pointSize);
703 }
704
705 void VertexProcessor::setPointSizeMin(float pointSizeMin)
706 {
707 point.pointSizeMin = pointSizeMin;
708 }
709
710 void VertexProcessor::setPointSizeMax(float pointSizeMax)
711 {
712 point.pointSizeMax = pointSizeMax;
713 }
714
715 void VertexProcessor::setPointScaleA(float pointScaleA)
716 {
717 point.pointScaleA = pointScaleA;
718 }
719
720 void VertexProcessor::setPointScaleB(float pointScaleB)
721 {
722 point.pointScaleB = pointScaleB;
723 }
724
725 void VertexProcessor::setPointScaleC(float pointScaleC)
726 {
727 point.pointScaleC = pointScaleC;
728 }
729
Alexis Hetu16116cb2016-03-02 15:59:51 -0500730 void VertexProcessor::setTransformFeedbackQueryEnabled(bool enable)
731 {
732 context->transformFeedbackQueryEnabled = enable;
733 }
734
735 void VertexProcessor::enableTransformFeedback(uint64_t enable)
736 {
737 context->transformFeedbackEnabled = enable;
738 }
739
John Bauman89401822014-05-06 15:04:28 -0400740 const Matrix &VertexProcessor::getModelTransform(int i)
741 {
742 updateTransform();
743 return PBVM[i];
744 }
745
746 const Matrix &VertexProcessor::getViewTransform()
747 {
748 updateTransform();
749 return PBV;
750 }
751
752 bool VertexProcessor::isFixedFunction()
753 {
754 return !context->vertexShader;
755 }
756
757 void VertexProcessor::setTransform(const Matrix &M, int i)
758 {
759 ff.transformT[i][0][0] = M[0][0];
760 ff.transformT[i][0][1] = M[1][0];
761 ff.transformT[i][0][2] = M[2][0];
762 ff.transformT[i][0][3] = M[3][0];
763
764 ff.transformT[i][1][0] = M[0][1];
765 ff.transformT[i][1][1] = M[1][1];
766 ff.transformT[i][1][2] = M[2][1];
767 ff.transformT[i][1][3] = M[3][1];
768
769 ff.transformT[i][2][0] = M[0][2];
770 ff.transformT[i][2][1] = M[1][2];
771 ff.transformT[i][2][2] = M[2][2];
772 ff.transformT[i][2][3] = M[3][2];
773
774 ff.transformT[i][3][0] = M[0][3];
775 ff.transformT[i][3][1] = M[1][3];
776 ff.transformT[i][3][2] = M[2][3];
777 ff.transformT[i][3][3] = M[3][3];
778 }
779
780 void VertexProcessor::setCameraTransform(const Matrix &M, int i)
781 {
782 ff.cameraTransformT[i][0][0] = M[0][0];
783 ff.cameraTransformT[i][0][1] = M[1][0];
784 ff.cameraTransformT[i][0][2] = M[2][0];
785 ff.cameraTransformT[i][0][3] = M[3][0];
786
787 ff.cameraTransformT[i][1][0] = M[0][1];
788 ff.cameraTransformT[i][1][1] = M[1][1];
789 ff.cameraTransformT[i][1][2] = M[2][1];
790 ff.cameraTransformT[i][1][3] = M[3][1];
791
792 ff.cameraTransformT[i][2][0] = M[0][2];
793 ff.cameraTransformT[i][2][1] = M[1][2];
794 ff.cameraTransformT[i][2][2] = M[2][2];
795 ff.cameraTransformT[i][2][3] = M[3][2];
796
797 ff.cameraTransformT[i][3][0] = M[0][3];
798 ff.cameraTransformT[i][3][1] = M[1][3];
799 ff.cameraTransformT[i][3][2] = M[2][3];
800 ff.cameraTransformT[i][3][3] = M[3][3];
801 }
802
803 void VertexProcessor::setNormalTransform(const Matrix &M, int i)
804 {
805 ff.normalTransformT[i][0][0] = M[0][0];
806 ff.normalTransformT[i][0][1] = M[1][0];
807 ff.normalTransformT[i][0][2] = M[2][0];
808 ff.normalTransformT[i][0][3] = M[3][0];
809
810 ff.normalTransformT[i][1][0] = M[0][1];
811 ff.normalTransformT[i][1][1] = M[1][1];
812 ff.normalTransformT[i][1][2] = M[2][1];
813 ff.normalTransformT[i][1][3] = M[3][1];
814
815 ff.normalTransformT[i][2][0] = M[0][2];
816 ff.normalTransformT[i][2][1] = M[1][2];
817 ff.normalTransformT[i][2][2] = M[2][2];
818 ff.normalTransformT[i][2][3] = M[3][2];
819
820 ff.normalTransformT[i][3][0] = M[0][3];
821 ff.normalTransformT[i][3][1] = M[1][3];
822 ff.normalTransformT[i][3][2] = M[2][3];
823 ff.normalTransformT[i][3][3] = M[3][3];
824 }
825
826 void VertexProcessor::updateTransform()
827 {
828 if(!updateMatrix) return;
829
830 int activeMatrices = context->indexedVertexBlendEnable ? 12 : max(context->vertexBlendMatrixCount, 1);
831
832 if(updateProjectionMatrix)
833 {
834 PB = P * B;
835 PBV = PB * V;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500836
John Bauman89401822014-05-06 15:04:28 -0400837 for(int i = 0; i < activeMatrices; i++)
838 {
839 PBVM[i] = PBV * M[i];
840 updateModelMatrix[i] = false;
841 }
842
843 updateProjectionMatrix = false;
844 updateBaseMatrix = false;
845 updateViewMatrix = false;
846 }
847
848 if(updateBaseMatrix)
849 {
850 PB = P * B;
851 PBV = PB * V;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500852
John Bauman89401822014-05-06 15:04:28 -0400853 for(int i = 0; i < activeMatrices; i++)
854 {
855 PBVM[i] = PBV * M[i];
856 updateModelMatrix[i] = false;
857 }
858
859 updateBaseMatrix = false;
860 updateViewMatrix = false;
861 }
862
863 if(updateViewMatrix)
864 {
865 PBV = PB * V;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500866
John Bauman89401822014-05-06 15:04:28 -0400867 for(int i = 0; i < activeMatrices; i++)
868 {
869 PBVM[i] = PBV * M[i];
870 updateModelMatrix[i] = false;
871 }
872
873 updateViewMatrix = false;
874 }
875
876 for(int i = 0; i < activeMatrices; i++)
877 {
878 if(updateModelMatrix[i])
879 {
880 PBVM[i] = PBV * M[i];
881 updateModelMatrix[i] = false;
882 }
883 }
884
885 for(int i = 0; i < activeMatrices; i++)
886 {
887 setTransform(PBVM[i], i);
888 setCameraTransform(B * V * M[i], i);
889 setNormalTransform(~!(B * V * M[i]), i);
890 }
891
892 updateMatrix = false;
893 }
894
895 void VertexProcessor::setRoutineCacheSize(int cacheSize)
896 {
897 delete routineCache;
Alexis Hetuf2878342019-03-12 16:32:04 -0400898 routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536));
John Bauman89401822014-05-06 15:04:28 -0400899 }
900
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400901 const VertexProcessor::State VertexProcessor::update(DrawType drawType)
John Bauman89401822014-05-06 15:04:28 -0400902 {
903 if(isFixedFunction())
904 {
905 updateTransform();
906
907 if(updateLighting)
908 {
909 for(int i = 0; i < 8; i++)
910 {
911 if(context->vertexLightActive(i))
912 {
913 // Light position in camera coordinates
914 setLightViewPosition(i, B * V * context->getLightPosition(i));
915 }
916 }
917
918 updateLighting = false;
919 }
920 }
921
922 State state;
923
924 if(context->vertexShader)
925 {
John Bauman19bac1e2014-05-06 15:23:49 -0400926 state.shaderID = context->vertexShader->getSerialID();
John Bauman89401822014-05-06 15:04:28 -0400927 }
928 else
929 {
John Bauman19bac1e2014-05-06 15:23:49 -0400930 state.shaderID = 0;
John Bauman89401822014-05-06 15:04:28 -0400931 }
932
Alexis Hetu53ad4af2017-12-06 14:49:07 -0500933 state.fixedFunction = !context->vertexShader && context->pixelShaderModel() < 0x0300;
Nicolas Capens6abe1cb2016-01-15 23:30:50 -0500934 state.textureSampling = context->vertexShader ? context->vertexShader->containsTextureSampling() : false;
Alexis Hetu02ad0aa2016-08-02 11:18:14 -0400935 state.positionRegister = context->vertexShader ? context->vertexShader->getPositionRegister() : Pos;
936 state.pointSizeRegister = context->vertexShader ? context->vertexShader->getPointSizeRegister() : Pts;
Nicolas Capens2ca19032016-01-15 16:54:13 -0500937
John Bauman89401822014-05-06 15:04:28 -0400938 state.vertexBlendMatrixCount = context->vertexBlendMatrixCountActive();
939 state.indexedVertexBlendEnable = context->indexedVertexBlendActive();
940 state.vertexNormalActive = context->vertexNormalActive();
941 state.normalizeNormals = context->normalizeNormalsActive();
942 state.vertexLightingActive = context->vertexLightingActive();
943 state.diffuseActive = context->diffuseActive();
944 state.specularActive = context->specularActive();
945 state.vertexSpecularActive = context->vertexSpecularActive();
946
947 state.vertexLightActive = context->vertexLightActive(0) << 0 |
948 context->vertexLightActive(1) << 1 |
949 context->vertexLightActive(2) << 2 |
950 context->vertexLightActive(3) << 3 |
951 context->vertexLightActive(4) << 4 |
952 context->vertexLightActive(5) << 5 |
953 context->vertexLightActive(6) << 6 |
954 context->vertexLightActive(7) << 7;
955
956 state.vertexDiffuseMaterialSourceActive = context->vertexDiffuseMaterialSourceActive();
957 state.vertexSpecularMaterialSourceActive = context->vertexSpecularMaterialSourceActive();
958 state.vertexAmbientMaterialSourceActive = context->vertexAmbientMaterialSourceActive();
959 state.vertexEmissiveMaterialSourceActive = context->vertexEmissiveMaterialSourceActive();
960 state.fogActive = context->fogActive();
961 state.vertexFogMode = context->vertexFogModeActive();
962 state.rangeFogActive = context->rangeFogActive();
963 state.localViewerActive = context->localViewerActive();
964 state.pointSizeActive = context->pointSizeActive();
965 state.pointScaleActive = context->pointScaleActive();
966
967 state.preTransformed = context->preTransformed;
John Bauman66b8ab22014-05-06 15:57:45 -0400968 state.superSampling = context->getSuperSampleCount() > 1;
John Bauman89401822014-05-06 15:04:28 -0400969
Alexis Hetu16116cb2016-03-02 15:59:51 -0500970 state.transformFeedbackQueryEnabled = context->transformFeedbackQueryEnabled;
971 state.transformFeedbackEnabled = context->transformFeedbackEnabled;
972
Alexis Hetua62a0ca2016-04-20 15:29:51 -0400973 // Note: Quads aren't handled for verticesPerPrimitive, but verticesPerPrimitive is used for transform feedback,
974 // which is an OpenGL ES 3.0 feature, and OpenGL ES 3.0 doesn't support quads as a primitive type.
975 DrawType type = static_cast<DrawType>(static_cast<unsigned int>(drawType) & 0xF);
976 state.verticesPerPrimitive = 1 + (type >= DRAW_LINELIST) + (type >= DRAW_TRIANGLELIST);
977
Nicolas Capensf0aef1a2016-05-18 14:44:21 -0400978 for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -0400979 {
980 state.input[i].type = context->input[i].type;
981 state.input[i].count = context->input[i].count;
982 state.input[i].normalized = context->input[i].normalized;
Alexis Hetub7508b82016-09-22 15:36:45 -0400983 state.input[i].attribType = context->vertexShader ? context->vertexShader->getAttribType(i) : VertexShader::ATTRIBTYPE_FLOAT;
John Bauman89401822014-05-06 15:04:28 -0400984 }
985
986 if(!context->vertexShader)
987 {
988 for(int i = 0; i < 8; i++)
989 {
990 // state.textureState[i].vertexTextureActive = context->vertexTextureActive(i, 0);
991 state.textureState[i].texGenActive = context->texGenActive(i);
992 state.textureState[i].textureTransformCountActive = context->textureTransformCountActive(i);
993 state.textureState[i].texCoordIndexActive = context->texCoordIndexActive(i);
994 }
995 }
996 else
997 {
Alexis Hetu0b65c5e2015-03-31 11:48:57 -0400998 for(unsigned int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
John Bauman89401822014-05-06 15:04:28 -0400999 {
1000 if(context->vertexShader->usesSampler(i))
1001 {
Nicolas Capensf878d502017-11-06 15:29:46 -05001002 state.sampler[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
John Bauman89401822014-05-06 15:04:28 -04001003 }
1004 }
1005 }
1006
1007 if(context->vertexShader) // FIXME: Also when pre-transformed?
1008 {
Nicolas Capensec0936c2016-05-18 12:32:02 -04001009 for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
John Bauman89401822014-05-06 15:04:28 -04001010 {
Alexis Hetu02ad0aa2016-08-02 11:18:14 -04001011 state.output[i].xWrite = context->vertexShader->getOutput(i, 0).active();
1012 state.output[i].yWrite = context->vertexShader->getOutput(i, 1).active();
1013 state.output[i].zWrite = context->vertexShader->getOutput(i, 2).active();
1014 state.output[i].wWrite = context->vertexShader->getOutput(i, 3).active();
John Bauman89401822014-05-06 15:04:28 -04001015 }
1016 }
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001017 else if(!context->preTransformed || context->pixelShaderModel() < 0x0300)
John Bauman89401822014-05-06 15:04:28 -04001018 {
1019 state.output[Pos].write = 0xF;
1020
1021 if(context->diffuseActive() && (context->lightingEnable || context->input[Color0]))
1022 {
Nicolas Capens995ddea2016-05-17 11:48:56 -04001023 state.output[C0].write = 0xF;
John Bauman89401822014-05-06 15:04:28 -04001024 }
Nicolas Capens2ca19032016-01-15 16:54:13 -05001025
John Bauman89401822014-05-06 15:04:28 -04001026 if(context->specularActive())
1027 {
Nicolas Capens995ddea2016-05-17 11:48:56 -04001028 state.output[C1].write = 0xF;
John Bauman89401822014-05-06 15:04:28 -04001029 }
1030
1031 for(int stage = 0; stage < 8; stage++)
1032 {
John Bauman19bac1e2014-05-06 15:23:49 -04001033 if(context->texCoordActive(stage, 0)) state.output[T0 + stage].write |= 0x01;
1034 if(context->texCoordActive(stage, 1)) state.output[T0 + stage].write |= 0x02;
1035 if(context->texCoordActive(stage, 2)) state.output[T0 + stage].write |= 0x04;
1036 if(context->texCoordActive(stage, 3)) state.output[T0 + stage].write |= 0x08;
John Bauman89401822014-05-06 15:04:28 -04001037 }
1038
1039 if(context->fogActive())
1040 {
1041 state.output[Fog].xWrite = true;
1042 }
1043
1044 if(context->pointSizeActive())
1045 {
1046 state.output[Pts].yWrite = true;
1047 }
1048 }
1049 else
1050 {
1051 state.output[Pos].write = 0xF;
1052
1053 for(int i = 0; i < 2; i++)
1054 {
1055 if(context->input[Color0 + i])
1056 {
Nicolas Capens995ddea2016-05-17 11:48:56 -04001057 state.output[C0 + i].write = 0xF;
John Bauman89401822014-05-06 15:04:28 -04001058 }
1059 }
1060
1061 for(int i = 0; i < 8; i++)
1062 {
1063 if(context->input[TexCoord0 + i])
1064 {
1065 state.output[T0 + i].write = 0xF;
1066 }
1067 }
1068
John Bauman66b8ab22014-05-06 15:57:45 -04001069 if(context->input[PointSize])
John Bauman89401822014-05-06 15:04:28 -04001070 {
1071 state.output[Pts].yWrite = true;
1072 }
1073 }
1074
Alexis Hetu53ad4af2017-12-06 14:49:07 -05001075 if(context->vertexShaderModel() < 0x0300)
John Bauman89401822014-05-06 15:04:28 -04001076 {
Nicolas Capens995ddea2016-05-17 11:48:56 -04001077 state.output[C0].clamp = 0xF;
1078 state.output[C1].clamp = 0xF;
John Bauman89401822014-05-06 15:04:28 -04001079 state.output[Fog].xClamp = true;
1080 }
1081
1082 state.hash = state.computeHash();
1083
1084 return state;
1085 }
1086
Ben Clayton6897e9b2019-07-16 17:27:27 +01001087 std::shared_ptr<Routine> VertexProcessor::routine(const State &state)
John Bauman89401822014-05-06 15:04:28 -04001088 {
Ben Clayton6897e9b2019-07-16 17:27:27 +01001089 auto routine = routineCache->query(state);
John Bauman89401822014-05-06 15:04:28 -04001090
1091 if(!routine) // Create one
1092 {
Nicolas Capensccd5ecb2017-01-14 12:52:55 -05001093 VertexRoutine *generator = nullptr;
John Bauman89401822014-05-06 15:04:28 -04001094
1095 if(state.fixedFunction)
1096 {
1097 generator = new VertexPipeline(state);
1098 }
1099 else
1100 {
1101 generator = new VertexProgram(state, context->vertexShader);
1102 }
1103
1104 generator->generate();
Chris Forbes878d4b02019-01-21 10:48:35 -08001105 routine = (*generator)("VertexRoutine_%0.8X", state.shaderID);
John Bauman89401822014-05-06 15:04:28 -04001106 delete generator;
1107
1108 routineCache->add(state, routine);
1109 }
1110
1111 return routine;
1112 }
1113}