1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
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 #include "VertexProcessor.hpp"
16 
17 #include "Math.hpp"
18 #include "VertexPipeline.hpp"
19 #include "VertexProgram.hpp"
20 #include "VertexShader.hpp"
21 #include "PixelShader.hpp"
22 #include "Constants.hpp"
23 #include "Debug.hpp"
24 
25 #include <string.h>
26 
27 namespace sw
28 {
29 	bool precacheVertex = false;
30 
clear()31 	void VertexCache::clear()
32 	{
33 		for(int i = 0; i < 16; i++)
34 		{
35 			tag[i] = 0x80000000;
36 		}
37 	}
38 
computeHash()39 	unsigned int VertexProcessor::States::computeHash()
40 	{
41 		unsigned int *state = (unsigned int*)this;
42 		unsigned int hash = 0;
43 
44 		for(unsigned int i = 0; i < sizeof(States) / 4; i++)
45 		{
46 			hash ^= state[i];
47 		}
48 
49 		return hash;
50 	}
51 
State()52 	VertexProcessor::State::State()
53 	{
54 		memset(this, 0, sizeof(State));
55 	}
56 
operator ==(const State & state) const57 	bool VertexProcessor::State::operator==(const State &state) const
58 	{
59 		if(hash != state.hash)
60 		{
61 			return false;
62 		}
63 
64 		return memcmp(static_cast<const States*>(this), static_cast<const States*>(&state), sizeof(States)) == 0;
65 	}
66 
TransformFeedbackInfo()67 	VertexProcessor::TransformFeedbackInfo::TransformFeedbackInfo()
68 	{
69 		buffer = nullptr;
70 		offset = 0;
71 		reg = 0;
72 		row = 0;
73 		col = 0;
74 		stride = 0;
75 	}
76 
UniformBufferInfo()77 	VertexProcessor::UniformBufferInfo::UniformBufferInfo()
78 	{
79 		buffer = nullptr;
80 		offset = 0;
81 	}
82 
VertexProcessor(Context * context)83 	VertexProcessor::VertexProcessor(Context *context) : context(context)
84 	{
85 		for(int i = 0; i < 12; i++)
86 		{
87 			M[i] = 1;
88 		}
89 
90 		V = 1;
91 		B = 1;
92 		P = 0;
93 		PB = 0;
94 		PBV = 0;
95 
96 		for(int i = 0; i < 12; i++)
97 		{
98 			PBVM[i] = 0;
99 		}
100 
101 		setLightingEnable(true);
102 		setSpecularEnable(false);
103 
104 		for(int i = 0; i < 8; i++)
105 		{
106 			setLightEnable(i, false);
107 			setLightPosition(i, 0);
108 		}
109 
110 		updateMatrix = true;
111 		updateViewMatrix = true;
112 		updateBaseMatrix = true;
113 		updateProjectionMatrix = true;
114 		updateLighting = true;
115 
116 		for(int i = 0; i < 12; i++)
117 		{
118 			updateModelMatrix[i] = true;
119 		}
120 
121 		routineCache = 0;
122 		setRoutineCacheSize(1024);
123 	}
124 
~VertexProcessor()125 	VertexProcessor::~VertexProcessor()
126 	{
127 		delete routineCache;
128 		routineCache = 0;
129 	}
130 
setInputStream(int index,const Stream & stream)131 	void VertexProcessor::setInputStream(int index, const Stream &stream)
132 	{
133 		context->input[index] = stream;
134 	}
135 
resetInputStreams(bool preTransformed)136 	void VertexProcessor::resetInputStreams(bool preTransformed)
137 	{
138 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
139 		{
140 			context->input[i].defaults();
141 		}
142 
143 		context->preTransformed = preTransformed;
144 	}
145 
setFloatConstant(unsigned int index,const float value[4])146 	void VertexProcessor::setFloatConstant(unsigned int index, const float value[4])
147 	{
148 		if(index < VERTEX_UNIFORM_VECTORS)
149 		{
150 			c[index][0] = value[0];
151 			c[index][1] = value[1];
152 			c[index][2] = value[2];
153 			c[index][3] = value[3];
154 		}
155 		else ASSERT(false);
156 	}
157 
setIntegerConstant(unsigned int index,const int integer[4])158 	void VertexProcessor::setIntegerConstant(unsigned int index, const int integer[4])
159 	{
160 		if(index < 16)
161 		{
162 			i[index][0] = integer[0];
163 			i[index][1] = integer[1];
164 			i[index][2] = integer[2];
165 			i[index][3] = integer[3];
166 		}
167 		else ASSERT(false);
168 	}
169 
setBooleanConstant(unsigned int index,int boolean)170 	void VertexProcessor::setBooleanConstant(unsigned int index, int boolean)
171 	{
172 		if(index < 16)
173 		{
174 			b[index] = boolean != 0;
175 		}
176 		else ASSERT(false);
177 	}
178 
setUniformBuffer(int index,sw::Resource * buffer,int offset)179 	void VertexProcessor::setUniformBuffer(int index, sw::Resource* buffer, int offset)
180 	{
181 		uniformBufferInfo[index].buffer = buffer;
182 		uniformBufferInfo[index].offset = offset;
183 	}
184 
lockUniformBuffers(byte ** u,sw::Resource * uniformBuffers[])185 	void VertexProcessor::lockUniformBuffers(byte** u, sw::Resource* uniformBuffers[])
186 	{
187 		for(int i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
188 		{
189 			u[i] = uniformBufferInfo[i].buffer ? static_cast<byte*>(uniformBufferInfo[i].buffer->lock(PUBLIC, PRIVATE)) + uniformBufferInfo[i].offset : nullptr;
190 			uniformBuffers[i] = uniformBufferInfo[i].buffer;
191 		}
192 	}
193 
setTransformFeedbackBuffer(int index,sw::Resource * buffer,int offset,unsigned int reg,unsigned int row,unsigned int col,size_t stride)194 	void VertexProcessor::setTransformFeedbackBuffer(int index, sw::Resource* buffer, int offset, unsigned int reg, unsigned int row, unsigned int col, size_t stride)
195 	{
196 		transformFeedbackInfo[index].buffer = buffer;
197 		transformFeedbackInfo[index].offset = offset;
198 		transformFeedbackInfo[index].reg = reg;
199 		transformFeedbackInfo[index].row = row;
200 		transformFeedbackInfo[index].col = col;
201 		transformFeedbackInfo[index].stride = stride;
202 	}
203 
lockTransformFeedbackBuffers(byte ** t,unsigned int * v,unsigned int * r,unsigned int * c,unsigned int * s,sw::Resource * transformFeedbackBuffers[])204 	void VertexProcessor::lockTransformFeedbackBuffers(byte** t, unsigned int* v, unsigned int* r, unsigned int* c, unsigned int* s, sw::Resource* transformFeedbackBuffers[])
205 	{
206 		for(int i = 0; i < MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++i)
207 		{
208 			t[i] = transformFeedbackInfo[i].buffer ? static_cast<byte*>(transformFeedbackInfo[i].buffer->lock(PUBLIC, PRIVATE)) + transformFeedbackInfo[i].offset : nullptr;
209 			transformFeedbackBuffers[i] = transformFeedbackInfo[i].buffer;
210 			v[i] = transformFeedbackInfo[i].reg;
211 			r[i] = transformFeedbackInfo[i].row;
212 			c[i] = transformFeedbackInfo[i].col;
213 			s[i] = transformFeedbackInfo[i].stride;
214 		}
215 	}
216 
setModelMatrix(const Matrix & M,int i)217 	void VertexProcessor::setModelMatrix(const Matrix &M, int i)
218 	{
219 		if(i < 12)
220 		{
221 			this->M[i] = M;
222 
223 			updateMatrix = true;
224 			updateModelMatrix[i] = true;
225 			updateLighting = true;
226 		}
227 		else ASSERT(false);
228 	}
229 
setViewMatrix(const Matrix & V)230 	void VertexProcessor::setViewMatrix(const Matrix &V)
231 	{
232 		this->V = V;
233 
234 		updateMatrix = true;
235 		updateViewMatrix = true;
236 	}
237 
setBaseMatrix(const Matrix & B)238 	void VertexProcessor::setBaseMatrix(const Matrix &B)
239 	{
240 		this->B = B;
241 
242 		updateMatrix = true;
243 		updateBaseMatrix = true;
244 	}
245 
setProjectionMatrix(const Matrix & P)246 	void VertexProcessor::setProjectionMatrix(const Matrix &P)
247 	{
248 		this->P = P;
249 		context->wBasedFog = (P[3][0] != 0.0f) || (P[3][1] != 0.0f) || (P[3][2] != 0.0f) || (P[3][3] != 1.0f);
250 
251 		updateMatrix = true;
252 		updateProjectionMatrix = true;
253 	}
254 
setLightingEnable(bool lightingEnable)255 	void VertexProcessor::setLightingEnable(bool lightingEnable)
256 	{
257 		context->setLightingEnable(lightingEnable);
258 
259 		updateLighting = true;
260 	}
261 
setLightEnable(unsigned int light,bool lightEnable)262 	void VertexProcessor::setLightEnable(unsigned int light, bool lightEnable)
263 	{
264 		if(light < 8)
265 		{
266 			context->setLightEnable(light, lightEnable);
267 		}
268 		else ASSERT(false);
269 
270 		updateLighting = true;
271 	}
272 
setSpecularEnable(bool specularEnable)273 	void VertexProcessor::setSpecularEnable(bool specularEnable)
274 	{
275 		context->setSpecularEnable(specularEnable);
276 
277 		updateLighting = true;
278 	}
279 
setLightPosition(unsigned int light,const Point & lightPosition)280 	void VertexProcessor::setLightPosition(unsigned int light, const Point &lightPosition)
281 	{
282 		if(light < 8)
283 		{
284 			context->setLightPosition(light, lightPosition);
285 		}
286 		else ASSERT(false);
287 
288 		updateLighting = true;
289 	}
290 
setLightDiffuse(unsigned int light,const Color<float> & lightDiffuse)291 	void VertexProcessor::setLightDiffuse(unsigned int light, const Color<float> &lightDiffuse)
292 	{
293 		if(light < 8)
294 		{
295 			ff.lightDiffuse[light][0] = lightDiffuse.r;
296 			ff.lightDiffuse[light][1] = lightDiffuse.g;
297 			ff.lightDiffuse[light][2] = lightDiffuse.b;
298 			ff.lightDiffuse[light][3] = lightDiffuse.a;
299 		}
300 		else ASSERT(false);
301 	}
302 
setLightSpecular(unsigned int light,const Color<float> & lightSpecular)303 	void VertexProcessor::setLightSpecular(unsigned int light, const Color<float> &lightSpecular)
304 	{
305 		if(light < 8)
306 		{
307 			ff.lightSpecular[light][0] = lightSpecular.r;
308 			ff.lightSpecular[light][1] = lightSpecular.g;
309 			ff.lightSpecular[light][2] = lightSpecular.b;
310 			ff.lightSpecular[light][3] = lightSpecular.a;
311 		}
312 		else ASSERT(false);
313 	}
314 
setLightAmbient(unsigned int light,const Color<float> & lightAmbient)315 	void VertexProcessor::setLightAmbient(unsigned int light, const Color<float> &lightAmbient)
316 	{
317 		if(light < 8)
318 		{
319 			ff.lightAmbient[light][0] = lightAmbient.r;
320 			ff.lightAmbient[light][1] = lightAmbient.g;
321 			ff.lightAmbient[light][2] = lightAmbient.b;
322 			ff.lightAmbient[light][3] = lightAmbient.a;
323 		}
324 		else ASSERT(false);
325 	}
326 
setLightAttenuation(unsigned int light,float constant,float linear,float quadratic)327 	void VertexProcessor::setLightAttenuation(unsigned int light, float constant, float linear, float quadratic)
328 	{
329 		if(light < 8)
330 		{
331 			ff.attenuationConstant[light] = replicate(constant);
332 			ff.attenuationLinear[light] = replicate(linear);
333 			ff.attenuationQuadratic[light] = replicate(quadratic);
334 		}
335 		else ASSERT(false);
336 	}
337 
setLightRange(unsigned int light,float lightRange)338 	void VertexProcessor::setLightRange(unsigned int light, float lightRange)
339 	{
340 		if(light < 8)
341 		{
342 			ff.lightRange[light] = lightRange;
343 		}
344 		else ASSERT(false);
345 	}
346 
setFogEnable(bool fogEnable)347 	void VertexProcessor::setFogEnable(bool fogEnable)
348 	{
349 		context->fogEnable = fogEnable;
350 	}
351 
setVertexFogMode(FogMode fogMode)352 	void VertexProcessor::setVertexFogMode(FogMode fogMode)
353 	{
354 		context->vertexFogMode = fogMode;
355 	}
356 
setInstanceID(int instanceID)357 	void VertexProcessor::setInstanceID(int instanceID)
358 	{
359 		context->instanceID = instanceID;
360 	}
361 
setColorVertexEnable(bool colorVertexEnable)362 	void VertexProcessor::setColorVertexEnable(bool colorVertexEnable)
363 	{
364 		context->setColorVertexEnable(colorVertexEnable);
365 	}
366 
setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)367 	void VertexProcessor::setDiffuseMaterialSource(MaterialSource diffuseMaterialSource)
368 	{
369 		context->setDiffuseMaterialSource(diffuseMaterialSource);
370 	}
371 
setSpecularMaterialSource(MaterialSource specularMaterialSource)372 	void VertexProcessor::setSpecularMaterialSource(MaterialSource specularMaterialSource)
373 	{
374 		context->setSpecularMaterialSource(specularMaterialSource);
375 	}
376 
setAmbientMaterialSource(MaterialSource ambientMaterialSource)377 	void VertexProcessor::setAmbientMaterialSource(MaterialSource ambientMaterialSource)
378 	{
379 		context->setAmbientMaterialSource(ambientMaterialSource);
380 	}
381 
setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)382 	void VertexProcessor::setEmissiveMaterialSource(MaterialSource emissiveMaterialSource)
383 	{
384 		context->setEmissiveMaterialSource(emissiveMaterialSource);
385 	}
386 
setGlobalAmbient(const Color<float> & globalAmbient)387 	void VertexProcessor::setGlobalAmbient(const Color<float> &globalAmbient)
388 	{
389 		ff.globalAmbient[0] = globalAmbient.r;
390 		ff.globalAmbient[1] = globalAmbient.g;
391 		ff.globalAmbient[2] = globalAmbient.b;
392 		ff.globalAmbient[3] = globalAmbient.a;
393 	}
394 
setMaterialEmission(const Color<float> & emission)395 	void VertexProcessor::setMaterialEmission(const Color<float> &emission)
396 	{
397 		ff.materialEmission[0] = emission.r;
398 		ff.materialEmission[1] = emission.g;
399 		ff.materialEmission[2] = emission.b;
400 		ff.materialEmission[3] = emission.a;
401 	}
402 
setMaterialAmbient(const Color<float> & materialAmbient)403 	void VertexProcessor::setMaterialAmbient(const Color<float> &materialAmbient)
404 	{
405 		ff.materialAmbient[0] = materialAmbient.r;
406 		ff.materialAmbient[1] = materialAmbient.g;
407 		ff.materialAmbient[2] = materialAmbient.b;
408 		ff.materialAmbient[3] = materialAmbient.a;
409 	}
410 
setMaterialDiffuse(const Color<float> & diffuseColor)411 	void VertexProcessor::setMaterialDiffuse(const Color<float> &diffuseColor)
412 	{
413 		ff.materialDiffuse[0] = diffuseColor.r;
414 		ff.materialDiffuse[1] = diffuseColor.g;
415 		ff.materialDiffuse[2] = diffuseColor.b;
416 		ff.materialDiffuse[3] = diffuseColor.a;
417 	}
418 
setMaterialSpecular(const Color<float> & specularColor)419 	void VertexProcessor::setMaterialSpecular(const Color<float> &specularColor)
420 	{
421 		ff.materialSpecular[0] = specularColor.r;
422 		ff.materialSpecular[1] = specularColor.g;
423 		ff.materialSpecular[2] = specularColor.b;
424 		ff.materialSpecular[3] = specularColor.a;
425 	}
426 
setMaterialShininess(float specularPower)427 	void VertexProcessor::setMaterialShininess(float specularPower)
428 	{
429 		ff.materialShininess = specularPower;
430 	}
431 
setLightViewPosition(unsigned int light,const Point & P)432 	void VertexProcessor::setLightViewPosition(unsigned int light, const Point &P)
433 	{
434 		if(light < 8)
435 		{
436 			ff.lightPosition[light][0] = P.x;
437 			ff.lightPosition[light][1] = P.y;
438 			ff.lightPosition[light][2] = P.z;
439 			ff.lightPosition[light][3] = 1;
440 		}
441 		else ASSERT(false);
442 	}
443 
setRangeFogEnable(bool enable)444 	void VertexProcessor::setRangeFogEnable(bool enable)
445 	{
446 		context->rangeFogEnable = enable;
447 	}
448 
setIndexedVertexBlendEnable(bool indexedVertexBlendEnable)449 	void VertexProcessor::setIndexedVertexBlendEnable(bool indexedVertexBlendEnable)
450 	{
451 		context->indexedVertexBlendEnable = indexedVertexBlendEnable;
452 	}
453 
setVertexBlendMatrixCount(unsigned int vertexBlendMatrixCount)454 	void VertexProcessor::setVertexBlendMatrixCount(unsigned int vertexBlendMatrixCount)
455 	{
456 		if(vertexBlendMatrixCount <= 4)
457 		{
458 			context->vertexBlendMatrixCount = vertexBlendMatrixCount;
459 		}
460 		else ASSERT(false);
461 	}
462 
setTextureWrap(unsigned int stage,int mask)463 	void VertexProcessor::setTextureWrap(unsigned int stage, int mask)
464 	{
465 		if(stage < TEXTURE_IMAGE_UNITS)
466 		{
467 			context->textureWrap[stage] = mask;
468 		}
469 		else ASSERT(false);
470 
471 		context->textureWrapActive = false;
472 
473 		for(int i = 0; i < TEXTURE_IMAGE_UNITS; i++)
474 		{
475 			context->textureWrapActive |= (context->textureWrap[i] != 0x00);
476 		}
477 	}
478 
setTexGen(unsigned int stage,TexGen texGen)479 	void VertexProcessor::setTexGen(unsigned int stage, TexGen texGen)
480 	{
481 		if(stage < 8)
482 		{
483 			context->texGen[stage] = texGen;
484 		}
485 		else ASSERT(false);
486 	}
487 
setLocalViewer(bool localViewer)488 	void VertexProcessor::setLocalViewer(bool localViewer)
489 	{
490 		context->localViewer = localViewer;
491 	}
492 
setNormalizeNormals(bool normalizeNormals)493 	void VertexProcessor::setNormalizeNormals(bool normalizeNormals)
494 	{
495 		context->normalizeNormals = normalizeNormals;
496 	}
497 
setTextureMatrix(int stage,const Matrix & T)498 	void VertexProcessor::setTextureMatrix(int stage, const Matrix &T)
499 	{
500 		for(int i = 0; i < 4; i++)
501 		{
502 			for(int j = 0; j < 4; j++)
503 			{
504 				ff.textureTransform[stage][i][j] = T[i][j];
505 			}
506 		}
507 	}
508 
setTextureTransform(int stage,int count,bool project)509 	void VertexProcessor::setTextureTransform(int stage, int count, bool project)
510 	{
511 		context->textureTransformCount[stage] = count;
512 		context->textureTransformProject[stage] = project;
513 	}
514 
setTextureFilter(unsigned int sampler,FilterType textureFilter)515 	void VertexProcessor::setTextureFilter(unsigned int sampler, FilterType textureFilter)
516 	{
517 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
518 		{
519 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setTextureFilter(textureFilter);
520 		}
521 		else ASSERT(false);
522 	}
523 
setMipmapFilter(unsigned int sampler,MipmapType mipmapFilter)524 	void VertexProcessor::setMipmapFilter(unsigned int sampler, MipmapType mipmapFilter)
525 	{
526 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
527 		{
528 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMipmapFilter(mipmapFilter);
529 		}
530 		else ASSERT(false);
531 	}
532 
setGatherEnable(unsigned int sampler,bool enable)533 	void VertexProcessor::setGatherEnable(unsigned int sampler, bool enable)
534 	{
535 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
536 		{
537 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setGatherEnable(enable);
538 		}
539 		else ASSERT(false);
540 	}
541 
setAddressingModeU(unsigned int sampler,AddressingMode addressMode)542 	void VertexProcessor::setAddressingModeU(unsigned int sampler, AddressingMode addressMode)
543 	{
544 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
545 		{
546 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeU(addressMode);
547 		}
548 		else ASSERT(false);
549 	}
550 
setAddressingModeV(unsigned int sampler,AddressingMode addressMode)551 	void VertexProcessor::setAddressingModeV(unsigned int sampler, AddressingMode addressMode)
552 	{
553 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
554 		{
555 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeV(addressMode);
556 		}
557 		else ASSERT(false);
558 	}
559 
setAddressingModeW(unsigned int sampler,AddressingMode addressMode)560 	void VertexProcessor::setAddressingModeW(unsigned int sampler, AddressingMode addressMode)
561 	{
562 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
563 		{
564 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setAddressingModeW(addressMode);
565 		}
566 		else ASSERT(false);
567 	}
568 
setReadSRGB(unsigned int sampler,bool sRGB)569 	void VertexProcessor::setReadSRGB(unsigned int sampler, bool sRGB)
570 	{
571 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
572 		{
573 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setReadSRGB(sRGB);
574 		}
575 		else ASSERT(false);
576 	}
577 
setMipmapLOD(unsigned int sampler,float bias)578 	void VertexProcessor::setMipmapLOD(unsigned int sampler, float bias)
579 	{
580 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
581 		{
582 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMipmapLOD(bias);
583 		}
584 		else ASSERT(false);
585 	}
586 
setBorderColor(unsigned int sampler,const Color<float> & borderColor)587 	void VertexProcessor::setBorderColor(unsigned int sampler, const Color<float> &borderColor)
588 	{
589 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
590 		{
591 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setBorderColor(borderColor);
592 		}
593 		else ASSERT(false);
594 	}
595 
setMaxAnisotropy(unsigned int sampler,float maxAnisotropy)596 	void VertexProcessor::setMaxAnisotropy(unsigned int sampler, float maxAnisotropy)
597 	{
598 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
599 		{
600 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setMaxAnisotropy(maxAnisotropy);
601 		}
602 		else ASSERT(false);
603 	}
604 
setSwizzleR(unsigned int sampler,SwizzleType swizzleR)605 	void VertexProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
606 	{
607 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
608 		{
609 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleR(swizzleR);
610 		}
611 		else ASSERT(false);
612 	}
613 
setSwizzleG(unsigned int sampler,SwizzleType swizzleG)614 	void VertexProcessor::setSwizzleG(unsigned int sampler, SwizzleType swizzleG)
615 	{
616 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
617 		{
618 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleG(swizzleG);
619 		}
620 		else ASSERT(false);
621 	}
622 
setSwizzleB(unsigned int sampler,SwizzleType swizzleB)623 	void VertexProcessor::setSwizzleB(unsigned int sampler, SwizzleType swizzleB)
624 	{
625 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
626 		{
627 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleB(swizzleB);
628 		}
629 		else ASSERT(false);
630 	}
631 
setSwizzleA(unsigned int sampler,SwizzleType swizzleA)632 	void VertexProcessor::setSwizzleA(unsigned int sampler, SwizzleType swizzleA)
633 	{
634 		if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
635 		{
636 			context->sampler[TEXTURE_IMAGE_UNITS + sampler].setSwizzleA(swizzleA);
637 		}
638 		else ASSERT(false);
639 	}
640 
setPointSize(float pointSize)641 	void VertexProcessor::setPointSize(float pointSize)
642 	{
643 		point.pointSize = replicate(pointSize);
644 	}
645 
setPointSizeMin(float pointSizeMin)646 	void VertexProcessor::setPointSizeMin(float pointSizeMin)
647 	{
648 		point.pointSizeMin = pointSizeMin;
649 	}
650 
setPointSizeMax(float pointSizeMax)651 	void VertexProcessor::setPointSizeMax(float pointSizeMax)
652 	{
653 		point.pointSizeMax = pointSizeMax;
654 	}
655 
setPointScaleA(float pointScaleA)656 	void VertexProcessor::setPointScaleA(float pointScaleA)
657 	{
658 		point.pointScaleA = pointScaleA;
659 	}
660 
setPointScaleB(float pointScaleB)661 	void VertexProcessor::setPointScaleB(float pointScaleB)
662 	{
663 		point.pointScaleB = pointScaleB;
664 	}
665 
setPointScaleC(float pointScaleC)666 	void VertexProcessor::setPointScaleC(float pointScaleC)
667 	{
668 		point.pointScaleC = pointScaleC;
669 	}
670 
setTransformFeedbackQueryEnabled(bool enable)671 	void VertexProcessor::setTransformFeedbackQueryEnabled(bool enable)
672 	{
673 		context->transformFeedbackQueryEnabled = enable;
674 	}
675 
enableTransformFeedback(uint64_t enable)676 	void VertexProcessor::enableTransformFeedback(uint64_t enable)
677 	{
678 		context->transformFeedbackEnabled = enable;
679 	}
680 
getModelTransform(int i)681 	const Matrix &VertexProcessor::getModelTransform(int i)
682 	{
683 		updateTransform();
684 		return PBVM[i];
685 	}
686 
getViewTransform()687 	const Matrix &VertexProcessor::getViewTransform()
688 	{
689 		updateTransform();
690 		return PBV;
691 	}
692 
isFixedFunction()693 	bool VertexProcessor::isFixedFunction()
694 	{
695 		return !context->vertexShader;
696 	}
697 
setTransform(const Matrix & M,int i)698 	void VertexProcessor::setTransform(const Matrix &M, int i)
699 	{
700 		ff.transformT[i][0][0] = M[0][0];
701 		ff.transformT[i][0][1] = M[1][0];
702 		ff.transformT[i][0][2] = M[2][0];
703 		ff.transformT[i][0][3] = M[3][0];
704 
705 		ff.transformT[i][1][0] = M[0][1];
706 		ff.transformT[i][1][1] = M[1][1];
707 		ff.transformT[i][1][2] = M[2][1];
708 		ff.transformT[i][1][3] = M[3][1];
709 
710 		ff.transformT[i][2][0] = M[0][2];
711 		ff.transformT[i][2][1] = M[1][2];
712 		ff.transformT[i][2][2] = M[2][2];
713 		ff.transformT[i][2][3] = M[3][2];
714 
715 		ff.transformT[i][3][0] = M[0][3];
716 		ff.transformT[i][3][1] = M[1][3];
717 		ff.transformT[i][3][2] = M[2][3];
718 		ff.transformT[i][3][3] = M[3][3];
719 	}
720 
setCameraTransform(const Matrix & M,int i)721 	void VertexProcessor::setCameraTransform(const Matrix &M, int i)
722 	{
723 		ff.cameraTransformT[i][0][0] = M[0][0];
724 		ff.cameraTransformT[i][0][1] = M[1][0];
725 		ff.cameraTransformT[i][0][2] = M[2][0];
726 		ff.cameraTransformT[i][0][3] = M[3][0];
727 
728 		ff.cameraTransformT[i][1][0] = M[0][1];
729 		ff.cameraTransformT[i][1][1] = M[1][1];
730 		ff.cameraTransformT[i][1][2] = M[2][1];
731 		ff.cameraTransformT[i][1][3] = M[3][1];
732 
733 		ff.cameraTransformT[i][2][0] = M[0][2];
734 		ff.cameraTransformT[i][2][1] = M[1][2];
735 		ff.cameraTransformT[i][2][2] = M[2][2];
736 		ff.cameraTransformT[i][2][3] = M[3][2];
737 
738 		ff.cameraTransformT[i][3][0] = M[0][3];
739 		ff.cameraTransformT[i][3][1] = M[1][3];
740 		ff.cameraTransformT[i][3][2] = M[2][3];
741 		ff.cameraTransformT[i][3][3] = M[3][3];
742 	}
743 
setNormalTransform(const Matrix & M,int i)744 	void VertexProcessor::setNormalTransform(const Matrix &M, int i)
745 	{
746 		ff.normalTransformT[i][0][0] = M[0][0];
747 		ff.normalTransformT[i][0][1] = M[1][0];
748 		ff.normalTransformT[i][0][2] = M[2][0];
749 		ff.normalTransformT[i][0][3] = M[3][0];
750 
751 		ff.normalTransformT[i][1][0] = M[0][1];
752 		ff.normalTransformT[i][1][1] = M[1][1];
753 		ff.normalTransformT[i][1][2] = M[2][1];
754 		ff.normalTransformT[i][1][3] = M[3][1];
755 
756 		ff.normalTransformT[i][2][0] = M[0][2];
757 		ff.normalTransformT[i][2][1] = M[1][2];
758 		ff.normalTransformT[i][2][2] = M[2][2];
759 		ff.normalTransformT[i][2][3] = M[3][2];
760 
761 		ff.normalTransformT[i][3][0] = M[0][3];
762 		ff.normalTransformT[i][3][1] = M[1][3];
763 		ff.normalTransformT[i][3][2] = M[2][3];
764 		ff.normalTransformT[i][3][3] = M[3][3];
765 	}
766 
updateTransform()767 	void VertexProcessor::updateTransform()
768 	{
769 		if(!updateMatrix) return;
770 
771 		int activeMatrices = context->indexedVertexBlendEnable ? 12 : max(context->vertexBlendMatrixCount, 1);
772 
773 		if(updateProjectionMatrix)
774 		{
775 			PB = P * B;
776 			PBV = PB * V;
777 
778 			for(int i = 0; i < activeMatrices; i++)
779 			{
780 				PBVM[i] = PBV * M[i];
781 				updateModelMatrix[i] = false;
782 			}
783 
784 			updateProjectionMatrix = false;
785 			updateBaseMatrix = false;
786 			updateViewMatrix = false;
787 		}
788 
789 		if(updateBaseMatrix)
790 		{
791 			PB = P * B;
792 			PBV = PB * V;
793 
794 			for(int i = 0; i < activeMatrices; i++)
795 			{
796 				PBVM[i] = PBV * M[i];
797 				updateModelMatrix[i] = false;
798 			}
799 
800 			updateBaseMatrix = false;
801 			updateViewMatrix = false;
802 		}
803 
804 		if(updateViewMatrix)
805 		{
806 			PBV = PB * V;
807 
808 			for(int i = 0; i < activeMatrices; i++)
809 			{
810 				PBVM[i] = PBV * M[i];
811 				updateModelMatrix[i] = false;
812 			}
813 
814 			updateViewMatrix = false;
815 		}
816 
817 		for(int i = 0; i < activeMatrices; i++)
818 		{
819 			if(updateModelMatrix[i])
820 			{
821 				PBVM[i] = PBV * M[i];
822 				updateModelMatrix[i] = false;
823 			}
824 		}
825 
826 		for(int i = 0; i < activeMatrices; i++)
827 		{
828 			setTransform(PBVM[i], i);
829 			setCameraTransform(B * V * M[i], i);
830 			setNormalTransform(~!(B * V * M[i]), i);
831 		}
832 
833 		updateMatrix = false;
834 	}
835 
setRoutineCacheSize(int cacheSize)836 	void VertexProcessor::setRoutineCacheSize(int cacheSize)
837 	{
838 		delete routineCache;
839 		routineCache = new RoutineCache<State>(clamp(cacheSize, 1, 65536), precacheVertex ? "sw-vertex" : 0);
840 	}
841 
update(DrawType drawType)842 	const VertexProcessor::State VertexProcessor::update(DrawType drawType)
843 	{
844 		if(isFixedFunction())
845 		{
846 			updateTransform();
847 
848 			if(updateLighting)
849 			{
850 				for(int i = 0; i < 8; i++)
851 				{
852 					if(context->vertexLightActive(i))
853 					{
854 						// Light position in camera coordinates
855 						setLightViewPosition(i, B * V * context->getLightPosition(i));
856 					}
857 				}
858 
859 				updateLighting = false;
860 			}
861 		}
862 
863 		State state;
864 
865 		if(context->vertexShader)
866 		{
867 			state.shaderID = context->vertexShader->getSerialID();
868 		}
869 		else
870 		{
871 			state.shaderID = 0;
872 		}
873 
874 		state.fixedFunction = !context->vertexShader && context->pixelShaderVersion() < 0x0300;
875 		state.textureSampling = context->vertexShader ? context->vertexShader->containsTextureSampling() : false;
876 		state.positionRegister = context->vertexShader ? context->vertexShader->positionRegister : Pos;
877 		state.pointSizeRegister = context->vertexShader ? context->vertexShader->pointSizeRegister : Pts;
878 
879 		state.vertexBlendMatrixCount = context->vertexBlendMatrixCountActive();
880 		state.indexedVertexBlendEnable = context->indexedVertexBlendActive();
881 		state.vertexNormalActive = context->vertexNormalActive();
882 		state.normalizeNormals = context->normalizeNormalsActive();
883 		state.vertexLightingActive = context->vertexLightingActive();
884 		state.diffuseActive = context->diffuseActive();
885 		state.specularActive = context->specularActive();
886 		state.vertexSpecularActive = context->vertexSpecularActive();
887 
888 		state.vertexLightActive = context->vertexLightActive(0) << 0 |
889 		                          context->vertexLightActive(1) << 1 |
890 		                          context->vertexLightActive(2) << 2 |
891 		                          context->vertexLightActive(3) << 3 |
892 		                          context->vertexLightActive(4) << 4 |
893 		                          context->vertexLightActive(5) << 5 |
894 		                          context->vertexLightActive(6) << 6 |
895 		                          context->vertexLightActive(7) << 7;
896 
897 		state.vertexDiffuseMaterialSourceActive = context->vertexDiffuseMaterialSourceActive();
898 		state.vertexSpecularMaterialSourceActive = context->vertexSpecularMaterialSourceActive();
899 		state.vertexAmbientMaterialSourceActive = context->vertexAmbientMaterialSourceActive();
900 		state.vertexEmissiveMaterialSourceActive = context->vertexEmissiveMaterialSourceActive();
901 		state.fogActive = context->fogActive();
902 		state.vertexFogMode = context->vertexFogModeActive();
903 		state.rangeFogActive = context->rangeFogActive();
904 		state.localViewerActive = context->localViewerActive();
905 		state.pointSizeActive = context->pointSizeActive();
906 		state.pointScaleActive = context->pointScaleActive();
907 
908 		state.preTransformed = context->preTransformed;
909 		state.superSampling = context->getSuperSampleCount() > 1;
910 		state.multiSampling = context->getMultiSampleCount() > 1;
911 
912 		state.transformFeedbackQueryEnabled = context->transformFeedbackQueryEnabled;
913 		state.transformFeedbackEnabled = context->transformFeedbackEnabled;
914 
915 		// Note: Quads aren't handled for verticesPerPrimitive, but verticesPerPrimitive is used for transform feedback,
916 		//       which is an OpenGL ES 3.0 feature, and OpenGL ES 3.0 doesn't support quads as a primitive type.
917 		DrawType type = static_cast<DrawType>(static_cast<unsigned int>(drawType) & 0xF);
918 		state.verticesPerPrimitive = 1 + (type >= DRAW_LINELIST) + (type >= DRAW_TRIANGLELIST);
919 
920 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
921 		{
922 			state.input[i].type = context->input[i].type;
923 			state.input[i].count = context->input[i].count;
924 			state.input[i].normalized = context->input[i].normalized;
925 		}
926 
927 		if(!context->vertexShader)
928 		{
929 			for(int i = 0; i < 8; i++)
930 			{
931 			//	state.textureState[i].vertexTextureActive = context->vertexTextureActive(i, 0);
932 				state.textureState[i].texGenActive = context->texGenActive(i);
933 				state.textureState[i].textureTransformCountActive = context->textureTransformCountActive(i);
934 				state.textureState[i].texCoordIndexActive = context->texCoordIndexActive(i);
935 			}
936 		}
937 		else
938 		{
939 			for(unsigned int i = 0; i < VERTEX_TEXTURE_IMAGE_UNITS; i++)
940 			{
941 				if(context->vertexShader->usesSampler(i))
942 				{
943 					state.samplerState[i] = context->sampler[TEXTURE_IMAGE_UNITS + i].samplerState();
944 				}
945 			}
946 		}
947 
948 		if(context->vertexShader)   // FIXME: Also when pre-transformed?
949 		{
950 			for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
951 			{
952 				state.output[i].xWrite = context->vertexShader->output[i][0].active();
953 				state.output[i].yWrite = context->vertexShader->output[i][1].active();
954 				state.output[i].zWrite = context->vertexShader->output[i][2].active();
955 				state.output[i].wWrite = context->vertexShader->output[i][3].active();
956 			}
957 		}
958 		else if(!context->preTransformed || context->pixelShaderVersion() < 0x0300)
959 		{
960 			state.output[Pos].write = 0xF;
961 
962 			if(context->diffuseActive() && (context->lightingEnable || context->input[Color0]))
963 			{
964 				state.output[C0].write = 0xF;
965 			}
966 
967 			if(context->specularActive())
968 			{
969 				state.output[C1].write = 0xF;
970 			}
971 
972 			for(int stage = 0; stage < 8; stage++)
973 			{
974 				if(context->texCoordActive(stage, 0)) state.output[T0 + stage].write |= 0x01;
975 				if(context->texCoordActive(stage, 1)) state.output[T0 + stage].write |= 0x02;
976 				if(context->texCoordActive(stage, 2)) state.output[T0 + stage].write |= 0x04;
977 				if(context->texCoordActive(stage, 3)) state.output[T0 + stage].write |= 0x08;
978 			}
979 
980 			if(context->fogActive())
981 			{
982 				state.output[Fog].xWrite = true;
983 			}
984 
985 			if(context->pointSizeActive())
986 			{
987 				state.output[Pts].yWrite = true;
988 			}
989 		}
990 		else
991 		{
992 			state.output[Pos].write = 0xF;
993 
994 			for(int i = 0; i < 2; i++)
995 			{
996 				if(context->input[Color0 + i])
997 				{
998 					state.output[C0 + i].write = 0xF;
999 				}
1000 			}
1001 
1002 			for(int i = 0; i < 8; i++)
1003 			{
1004 				if(context->input[TexCoord0 + i])
1005 				{
1006 					state.output[T0 + i].write = 0xF;
1007 				}
1008 			}
1009 
1010 			if(context->input[PointSize])
1011 			{
1012 				state.output[Pts].yWrite = true;
1013 			}
1014 		}
1015 
1016 		if(context->vertexShaderVersion() < 0x0300)
1017 		{
1018 			state.output[C0].clamp = 0xF;
1019 			state.output[C1].clamp = 0xF;
1020 			state.output[Fog].xClamp = true;
1021 		}
1022 
1023 		state.hash = state.computeHash();
1024 
1025 		return state;
1026 	}
1027 
routine(const State & state)1028 	Routine *VertexProcessor::routine(const State &state)
1029 	{
1030 		Routine *routine = routineCache->query(state);
1031 
1032 		if(!routine)   // Create one
1033 		{
1034 			VertexRoutine *generator = 0;
1035 
1036 			if(state.fixedFunction)
1037 			{
1038 				generator = new VertexPipeline(state);
1039 			}
1040 			else
1041 			{
1042 				generator = new VertexProgram(state, context->vertexShader);
1043 			}
1044 
1045 			generator->generate();
1046 			routine = (*generator)(L"VertexRoutine_%0.8X", state.shaderID);
1047 			delete generator;
1048 
1049 			routineCache->add(state, routine);
1050 		}
1051 
1052 		return routine;
1053 	}
1054 }
1055