blob: b5fb4e598c9dd7112055598c8c447969a2fe9675 [file] [log] [blame]
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001//
2// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Program.cpp: Implements the gl::Program class. Implements GL program objects
8// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
apatrick@chromium.org90080e32012-07-09 22:15:33 +000010#include <sstream>
11
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000012#include "libGLESv2/Program.h"
13#include "libGLESv2/ProgramBinary.h"
14
15#include "common/debug.h"
apatrick@chromium.org90080e32012-07-09 22:15:33 +000016#include "common/version.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000017
18#include "libGLESv2/main.h"
19#include "libGLESv2/Shader.h"
20#include "libGLESv2/utilities.h"
21
22#include <string>
23
24#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
25#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
26#endif
27
28namespace gl
29{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000030std::string str(int i)
31{
32 char buffer[20];
33 snprintf(buffer, sizeof(buffer), "%d", i);
34 return buffer;
35}
36
37Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
38 : type(type), _name(_name), name(ProgramBinary::undecorateUniform(_name)), arraySize(arraySize)
39{
40 int bytes = UniformInternalSize(type) * arraySize;
41 data = new unsigned char[bytes];
42 memset(data, 0, bytes);
43 dirty = true;
44}
45
46Uniform::~Uniform()
47{
48 delete[] data;
49}
50
51bool Uniform::isArray()
52{
53 return _name.compare(0, 3, "ar_") == 0;
54}
55
56UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index)
57 : name(ProgramBinary::undecorateUniform(_name)), element(element), index(index)
58{
59}
60
61ProgramBinary::ProgramBinary()
62{
63 mDevice = getDevice();
64
65 mPixelExecutable = NULL;
66 mVertexExecutable = NULL;
67 mConstantTablePS = NULL;
68 mConstantTableVS = NULL;
69
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000070 mValidated = false;
71
72 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
73 {
74 mSemanticIndex[index] = -1;
75 }
76
77 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
78 {
79 mSamplersPS[index].active = false;
80 }
81
82 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
83 {
84 mSamplersVS[index].active = false;
85 }
86
87 mUsedVertexSamplerRange = 0;
88 mUsedPixelSamplerRange = 0;
89
90 mDxDepthRangeLocation = -1;
91 mDxDepthLocation = -1;
92 mDxCoordLocation = -1;
93 mDxHalfPixelSizeLocation = -1;
94 mDxFrontCCWLocation = -1;
95 mDxPointsOrLinesLocation = -1;
96}
97
98ProgramBinary::~ProgramBinary()
99{
100 if (mPixelExecutable)
101 {
102 mPixelExecutable->Release();
103 }
104
105 if (mVertexExecutable)
106 {
107 mVertexExecutable->Release();
108 }
109
110 if (mConstantTablePS)
111 {
112 mConstantTablePS->Release();
113 }
114
115 if (mConstantTableVS)
116 {
117 mConstantTableVS->Release();
118 }
119
120 while (!mUniforms.empty())
121 {
122 delete mUniforms.back();
123 mUniforms.pop_back();
124 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000125}
126
127IDirect3DPixelShader9 *ProgramBinary::getPixelShader()
128{
129 return mPixelExecutable;
130}
131
132IDirect3DVertexShader9 *ProgramBinary::getVertexShader()
133{
134 return mVertexExecutable;
135}
136
137GLuint ProgramBinary::getAttributeLocation(const char *name)
138{
139 if (name)
140 {
141 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
142 {
143 if (mLinkedAttribute[index].name == std::string(name))
144 {
145 return index;
146 }
147 }
148 }
149
150 return -1;
151}
152
153int ProgramBinary::getSemanticIndex(int attributeIndex)
154{
155 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
156
157 return mSemanticIndex[attributeIndex];
158}
159
160// Returns one more than the highest sampler index used.
161GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
162{
163 switch (type)
164 {
165 case SAMPLER_PIXEL:
166 return mUsedPixelSamplerRange;
167 case SAMPLER_VERTEX:
168 return mUsedVertexSamplerRange;
169 default:
170 UNREACHABLE();
171 return 0;
172 }
173}
174
175// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
176// index (0-15 for the pixel shader and 0-3 for the vertex shader).
177GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
178{
179 GLint logicalTextureUnit = -1;
180
181 switch (type)
182 {
183 case SAMPLER_PIXEL:
184 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
185
186 if (mSamplersPS[samplerIndex].active)
187 {
188 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
189 }
190 break;
191 case SAMPLER_VERTEX:
192 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
193
194 if (mSamplersVS[samplerIndex].active)
195 {
196 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
197 }
198 break;
199 default: UNREACHABLE();
200 }
201
202 if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
203 {
204 return logicalTextureUnit;
205 }
206
207 return -1;
208}
209
210// Returns the texture type for a given Direct3D 9 sampler type and
211// index (0-15 for the pixel shader and 0-3 for the vertex shader).
212TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
213{
214 switch (type)
215 {
216 case SAMPLER_PIXEL:
217 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
218 ASSERT(mSamplersPS[samplerIndex].active);
219 return mSamplersPS[samplerIndex].textureType;
220 case SAMPLER_VERTEX:
221 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
222 ASSERT(mSamplersVS[samplerIndex].active);
223 return mSamplersVS[samplerIndex].textureType;
224 default: UNREACHABLE();
225 }
226
227 return TEXTURE_2D;
228}
229
230GLint ProgramBinary::getUniformLocation(std::string name)
231{
232 unsigned int subscript = 0;
233
234 // Strip any trailing array operator and retrieve the subscript
235 size_t open = name.find_last_of('[');
236 size_t close = name.find_last_of(']');
237 if (open != std::string::npos && close == name.length() - 1)
238 {
239 subscript = atoi(name.substr(open + 1).c_str());
240 name.erase(open);
241 }
242
243 unsigned int numUniforms = mUniformIndex.size();
244 for (unsigned int location = 0; location < numUniforms; location++)
245 {
246 if (mUniformIndex[location].name == name &&
247 mUniformIndex[location].element == subscript)
248 {
249 return location;
250 }
251 }
252
253 return -1;
254}
255
256bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
257{
258 if (location < 0 || location >= (int)mUniformIndex.size())
259 {
260 return false;
261 }
262
263 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
264 targetUniform->dirty = true;
265
266 if (targetUniform->type == GL_FLOAT)
267 {
268 int arraySize = targetUniform->arraySize;
269
270 if (arraySize == 1 && count > 1)
271 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
272
273 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
274
275 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
276
277 for (int i = 0; i < count; i++)
278 {
279 target[0] = v[0];
280 target[1] = 0;
281 target[2] = 0;
282 target[3] = 0;
283 target += 4;
284 v += 1;
285 }
286 }
287 else if (targetUniform->type == GL_BOOL)
288 {
289 int arraySize = targetUniform->arraySize;
290
291 if (arraySize == 1 && count > 1)
292 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
293
294 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
295 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
296
297 for (int i = 0; i < count; ++i)
298 {
299 if (v[i] == 0.0f)
300 {
301 boolParams[i] = GL_FALSE;
302 }
303 else
304 {
305 boolParams[i] = GL_TRUE;
306 }
307 }
308 }
309 else
310 {
311 return false;
312 }
313
314 return true;
315}
316
317bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
318{
319 if (location < 0 || location >= (int)mUniformIndex.size())
320 {
321 return false;
322 }
323
324 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
325 targetUniform->dirty = true;
326
327 if (targetUniform->type == GL_FLOAT_VEC2)
328 {
329 int arraySize = targetUniform->arraySize;
330
331 if (arraySize == 1 && count > 1)
332 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
333
334 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
335
336 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
337
338 for (int i = 0; i < count; i++)
339 {
340 target[0] = v[0];
341 target[1] = v[1];
342 target[2] = 0;
343 target[3] = 0;
344 target += 4;
345 v += 2;
346 }
347 }
348 else if (targetUniform->type == GL_BOOL_VEC2)
349 {
350 int arraySize = targetUniform->arraySize;
351
352 if (arraySize == 1 && count > 1)
353 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
354
355 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
356
357 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
358
359 for (int i = 0; i < count * 2; ++i)
360 {
361 if (v[i] == 0.0f)
362 {
363 boolParams[i] = GL_FALSE;
364 }
365 else
366 {
367 boolParams[i] = GL_TRUE;
368 }
369 }
370 }
371 else
372 {
373 return false;
374 }
375
376 return true;
377}
378
379bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
380{
381 if (location < 0 || location >= (int)mUniformIndex.size())
382 {
383 return false;
384 }
385
386 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
387 targetUniform->dirty = true;
388
389 if (targetUniform->type == GL_FLOAT_VEC3)
390 {
391 int arraySize = targetUniform->arraySize;
392
393 if (arraySize == 1 && count > 1)
394 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
395
396 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
397
398 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
399
400 for (int i = 0; i < count; i++)
401 {
402 target[0] = v[0];
403 target[1] = v[1];
404 target[2] = v[2];
405 target[3] = 0;
406 target += 4;
407 v += 3;
408 }
409 }
410 else if (targetUniform->type == GL_BOOL_VEC3)
411 {
412 int arraySize = targetUniform->arraySize;
413
414 if (arraySize == 1 && count > 1)
415 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
416
417 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
418 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
419
420 for (int i = 0; i < count * 3; ++i)
421 {
422 if (v[i] == 0.0f)
423 {
424 boolParams[i] = GL_FALSE;
425 }
426 else
427 {
428 boolParams[i] = GL_TRUE;
429 }
430 }
431 }
432 else
433 {
434 return false;
435 }
436
437 return true;
438}
439
440bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
441{
442 if (location < 0 || location >= (int)mUniformIndex.size())
443 {
444 return false;
445 }
446
447 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
448 targetUniform->dirty = true;
449
450 if (targetUniform->type == GL_FLOAT_VEC4)
451 {
452 int arraySize = targetUniform->arraySize;
453
454 if (arraySize == 1 && count > 1)
455 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
456
457 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
458
459 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
460 v, 4 * sizeof(GLfloat) * count);
461 }
462 else if (targetUniform->type == GL_BOOL_VEC4)
463 {
464 int arraySize = targetUniform->arraySize;
465
466 if (arraySize == 1 && count > 1)
467 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
468
469 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
470 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
471
472 for (int i = 0; i < count * 4; ++i)
473 {
474 if (v[i] == 0.0f)
475 {
476 boolParams[i] = GL_FALSE;
477 }
478 else
479 {
480 boolParams[i] = GL_TRUE;
481 }
482 }
483 }
484 else
485 {
486 return false;
487 }
488
489 return true;
490}
491
492template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
493void transposeMatrix(T *target, const GLfloat *value)
494{
495 int copyWidth = std::min(targetWidth, srcWidth);
496 int copyHeight = std::min(targetHeight, srcHeight);
497
498 for (int x = 0; x < copyWidth; x++)
499 {
500 for (int y = 0; y < copyHeight; y++)
501 {
502 target[x * targetWidth + y] = (T)value[y * srcWidth + x];
503 }
504 }
505 // clear unfilled right side
506 for (int y = 0; y < copyHeight; y++)
507 {
508 for (int x = srcWidth; x < targetWidth; x++)
509 {
510 target[y * targetWidth + x] = (T)0;
511 }
512 }
513 // clear unfilled bottom.
514 for (int y = srcHeight; y < targetHeight; y++)
515 {
516 for (int x = 0; x < targetWidth; x++)
517 {
518 target[y * targetWidth + x] = (T)0;
519 }
520 }
521}
522
523bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
524{
525 if (location < 0 || location >= (int)mUniformIndex.size())
526 {
527 return false;
528 }
529
530 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
531 targetUniform->dirty = true;
532
533 if (targetUniform->type != GL_FLOAT_MAT2)
534 {
535 return false;
536 }
537
538 int arraySize = targetUniform->arraySize;
539
540 if (arraySize == 1 && count > 1)
541 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
542
543 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
544
545 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
546 for (int i = 0; i < count; i++)
547 {
548 transposeMatrix<GLfloat,4,2,2,2>(target, value);
549 target += 8;
550 value += 4;
551 }
552
553 return true;
554}
555
556bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
557{
558 if (location < 0 || location >= (int)mUniformIndex.size())
559 {
560 return false;
561 }
562
563 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
564 targetUniform->dirty = true;
565
566 if (targetUniform->type != GL_FLOAT_MAT3)
567 {
568 return false;
569 }
570
571 int arraySize = targetUniform->arraySize;
572
573 if (arraySize == 1 && count > 1)
574 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
575
576 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
577
578 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
579 for (int i = 0; i < count; i++)
580 {
581 transposeMatrix<GLfloat,4,3,3,3>(target, value);
582 target += 12;
583 value += 9;
584 }
585
586 return true;
587}
588
589
590bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
591{
592 if (location < 0 || location >= (int)mUniformIndex.size())
593 {
594 return false;
595 }
596
597 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
598 targetUniform->dirty = true;
599
600 if (targetUniform->type != GL_FLOAT_MAT4)
601 {
602 return false;
603 }
604
605 int arraySize = targetUniform->arraySize;
606
607 if (arraySize == 1 && count > 1)
608 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
609
610 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
611
612 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
613 for (int i = 0; i < count; i++)
614 {
615 transposeMatrix<GLfloat,4,4,4,4>(target, value);
616 target += 16;
617 value += 16;
618 }
619
620 return true;
621}
622
623bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
624{
625 if (location < 0 || location >= (int)mUniformIndex.size())
626 {
627 return false;
628 }
629
630 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
631 targetUniform->dirty = true;
632
633 if (targetUniform->type == GL_INT ||
634 targetUniform->type == GL_SAMPLER_2D ||
635 targetUniform->type == GL_SAMPLER_CUBE)
636 {
637 int arraySize = targetUniform->arraySize;
638
639 if (arraySize == 1 && count > 1)
640 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
641
642 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
643
644 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
645 v, sizeof(GLint) * count);
646 }
647 else if (targetUniform->type == GL_BOOL)
648 {
649 int arraySize = targetUniform->arraySize;
650
651 if (arraySize == 1 && count > 1)
652 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
653
654 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
655 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
656
657 for (int i = 0; i < count; ++i)
658 {
659 if (v[i] == 0)
660 {
661 boolParams[i] = GL_FALSE;
662 }
663 else
664 {
665 boolParams[i] = GL_TRUE;
666 }
667 }
668 }
669 else
670 {
671 return false;
672 }
673
674 return true;
675}
676
677bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
678{
679 if (location < 0 || location >= (int)mUniformIndex.size())
680 {
681 return false;
682 }
683
684 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
685 targetUniform->dirty = true;
686
687 if (targetUniform->type == GL_INT_VEC2)
688 {
689 int arraySize = targetUniform->arraySize;
690
691 if (arraySize == 1 && count > 1)
692 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
693
694 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
695
696 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
697 v, 2 * sizeof(GLint) * count);
698 }
699 else if (targetUniform->type == GL_BOOL_VEC2)
700 {
701 int arraySize = targetUniform->arraySize;
702
703 if (arraySize == 1 && count > 1)
704 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
705
706 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
707 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
708
709 for (int i = 0; i < count * 2; ++i)
710 {
711 if (v[i] == 0)
712 {
713 boolParams[i] = GL_FALSE;
714 }
715 else
716 {
717 boolParams[i] = GL_TRUE;
718 }
719 }
720 }
721 else
722 {
723 return false;
724 }
725
726 return true;
727}
728
729bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
730{
731 if (location < 0 || location >= (int)mUniformIndex.size())
732 {
733 return false;
734 }
735
736 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
737 targetUniform->dirty = true;
738
739 if (targetUniform->type == GL_INT_VEC3)
740 {
741 int arraySize = targetUniform->arraySize;
742
743 if (arraySize == 1 && count > 1)
744 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
745
746 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
747
748 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
749 v, 3 * sizeof(GLint) * count);
750 }
751 else if (targetUniform->type == GL_BOOL_VEC3)
752 {
753 int arraySize = targetUniform->arraySize;
754
755 if (arraySize == 1 && count > 1)
756 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
757
758 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
759 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
760
761 for (int i = 0; i < count * 3; ++i)
762 {
763 if (v[i] == 0)
764 {
765 boolParams[i] = GL_FALSE;
766 }
767 else
768 {
769 boolParams[i] = GL_TRUE;
770 }
771 }
772 }
773 else
774 {
775 return false;
776 }
777
778 return true;
779}
780
781bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
782{
783 if (location < 0 || location >= (int)mUniformIndex.size())
784 {
785 return false;
786 }
787
788 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
789 targetUniform->dirty = true;
790
791 if (targetUniform->type == GL_INT_VEC4)
792 {
793 int arraySize = targetUniform->arraySize;
794
795 if (arraySize == 1 && count > 1)
796 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
797
798 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
799
800 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
801 v, 4 * sizeof(GLint) * count);
802 }
803 else if (targetUniform->type == GL_BOOL_VEC4)
804 {
805 int arraySize = targetUniform->arraySize;
806
807 if (arraySize == 1 && count > 1)
808 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
809
810 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
811 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
812
813 for (int i = 0; i < count * 4; ++i)
814 {
815 if (v[i] == 0)
816 {
817 boolParams[i] = GL_FALSE;
818 }
819 else
820 {
821 boolParams[i] = GL_TRUE;
822 }
823 }
824 }
825 else
826 {
827 return false;
828 }
829
830 return true;
831}
832
833bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
834{
835 if (location < 0 || location >= (int)mUniformIndex.size())
836 {
837 return false;
838 }
839
840 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
841
842 // sized queries -- ensure the provided buffer is large enough
843 if (bufSize)
844 {
845 int requiredBytes = UniformExternalSize(targetUniform->type);
846 if (*bufSize < requiredBytes)
847 {
848 return false;
849 }
850 }
851
852 switch (targetUniform->type)
853 {
854 case GL_FLOAT_MAT2:
855 transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
856 break;
857 case GL_FLOAT_MAT3:
858 transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
859 break;
860 case GL_FLOAT_MAT4:
861 transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
862 break;
863 default:
864 {
865 unsigned int count = UniformExternalComponentCount(targetUniform->type);
866 unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
867
868 switch (UniformComponentType(targetUniform->type))
869 {
870 case GL_BOOL:
871 {
872 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
873
874 for (unsigned int i = 0; i < count; ++i)
875 {
876 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
877 }
878 }
879 break;
880 case GL_FLOAT:
881 memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat),
882 count * sizeof(GLfloat));
883 break;
884 case GL_INT:
885 {
886 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount;
887
888 for (unsigned int i = 0; i < count; ++i)
889 {
890 params[i] = (float)intParams[i];
891 }
892 }
893 break;
894 default: UNREACHABLE();
895 }
896 }
897 }
898
899 return true;
900}
901
902bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
903{
904 if (location < 0 || location >= (int)mUniformIndex.size())
905 {
906 return false;
907 }
908
909 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
910
911 // sized queries -- ensure the provided buffer is large enough
912 if (bufSize)
913 {
914 int requiredBytes = UniformExternalSize(targetUniform->type);
915 if (*bufSize < requiredBytes)
916 {
917 return false;
918 }
919 }
920
921 switch (targetUniform->type)
922 {
923 case GL_FLOAT_MAT2:
924 {
925 transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
926 }
927 break;
928 case GL_FLOAT_MAT3:
929 {
930 transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
931 }
932 break;
933 case GL_FLOAT_MAT4:
934 {
935 transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
936 }
937 break;
938 default:
939 {
940 unsigned int count = UniformExternalComponentCount(targetUniform->type);
941 unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
942
943 switch (UniformComponentType(targetUniform->type))
944 {
945 case GL_BOOL:
946 {
947 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
948
949 for (unsigned int i = 0; i < count; ++i)
950 {
951 params[i] = (GLint)boolParams[i];
952 }
953 }
954 break;
955 case GL_FLOAT:
956 {
957 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount;
958
959 for (unsigned int i = 0; i < count; ++i)
960 {
961 params[i] = (GLint)floatParams[i];
962 }
963 }
964 break;
965 case GL_INT:
966 memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint),
967 count * sizeof(GLint));
968 break;
969 default: UNREACHABLE();
970 }
971 }
972 }
973
974 return true;
975}
976
977void ProgramBinary::dirtyAllUniforms()
978{
979 unsigned int numUniforms = mUniforms.size();
980 for (unsigned int index = 0; index < numUniforms; index++)
981 {
982 mUniforms[index]->dirty = true;
983 }
984}
985
986// Applies all the uniforms set for this program object to the Direct3D 9 device
987void ProgramBinary::applyUniforms()
988{
989 for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
990 Uniform *targetUniform = *ub;
991
992 if (targetUniform->dirty)
993 {
994 int arraySize = targetUniform->arraySize;
995 GLfloat *f = (GLfloat*)targetUniform->data;
996 GLint *i = (GLint*)targetUniform->data;
997 GLboolean *b = (GLboolean*)targetUniform->data;
998
999 switch (targetUniform->type)
1000 {
1001 case GL_BOOL: applyUniformnbv(targetUniform, arraySize, 1, b); break;
1002 case GL_BOOL_VEC2: applyUniformnbv(targetUniform, arraySize, 2, b); break;
1003 case GL_BOOL_VEC3: applyUniformnbv(targetUniform, arraySize, 3, b); break;
1004 case GL_BOOL_VEC4: applyUniformnbv(targetUniform, arraySize, 4, b); break;
1005 case GL_FLOAT:
1006 case GL_FLOAT_VEC2:
1007 case GL_FLOAT_VEC3:
1008 case GL_FLOAT_VEC4:
1009 case GL_FLOAT_MAT2:
1010 case GL_FLOAT_MAT3:
1011 case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break;
1012 case GL_SAMPLER_2D:
1013 case GL_SAMPLER_CUBE:
1014 case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break;
1015 case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break;
1016 case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break;
1017 case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break;
1018 default:
1019 UNREACHABLE();
1020 }
1021
1022 targetUniform->dirty = false;
1023 }
1024 }
1025}
1026
1027// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001028ID3D10Blob *ProgramBinary::compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001029{
1030 if (!hlsl)
1031 {
1032 return NULL;
1033 }
1034
1035 DWORD result;
1036 UINT flags = 0;
1037 std::string sourceText;
1038 if (perfActive())
1039 {
1040 flags |= D3DCOMPILE_DEBUG;
1041#ifdef NDEBUG
1042 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1043#else
1044 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
1045#endif
1046
1047 std::string sourcePath = getTempPath();
1048 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
1049 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
1050 }
1051 else
1052 {
1053 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1054 sourceText = hlsl;
1055 }
1056
1057 ID3D10Blob *binary = NULL;
1058 ID3D10Blob *errorMessage = NULL;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001059 result = D3DCompile(hlsl, strlen(hlsl), g_fakepath, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001060
1061 if (errorMessage)
1062 {
1063 const char *message = (const char*)errorMessage->GetBufferPointer();
1064
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001065 infoLog.appendSanitized(message);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001066 TRACE("\n%s", hlsl);
1067 TRACE("\n%s", message);
1068
1069 errorMessage->Release();
1070 errorMessage = NULL;
1071 }
1072
1073 if (FAILED(result))
1074 {
1075 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1076 {
1077 error(GL_OUT_OF_MEMORY);
1078 }
1079
1080 return NULL;
1081 }
1082
1083 result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
1084
1085 if (FAILED(result))
1086 {
1087 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1088 {
1089 error(GL_OUT_OF_MEMORY);
1090 }
1091
1092 binary->Release();
1093
1094 return NULL;
1095 }
1096
1097 return binary;
1098}
1099
1100// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
1101// Returns the number of used varying registers, or -1 if unsuccesful
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001102int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001103{
1104 Context *context = getContext();
1105 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1106
1107 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
1108 {
1109 int n = VariableRowCount(varying->type) * varying->size;
1110 int m = VariableColumnCount(varying->type);
1111 bool success = false;
1112
1113 if (m == 2 || m == 3 || m == 4)
1114 {
1115 for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
1116 {
1117 bool available = true;
1118
1119 for (int y = 0; y < n && available; y++)
1120 {
1121 for (int x = 0; x < m && available; x++)
1122 {
1123 if (packing[r + y][x])
1124 {
1125 available = false;
1126 }
1127 }
1128 }
1129
1130 if (available)
1131 {
1132 varying->reg = r;
1133 varying->col = 0;
1134
1135 for (int y = 0; y < n; y++)
1136 {
1137 for (int x = 0; x < m; x++)
1138 {
1139 packing[r + y][x] = &*varying;
1140 }
1141 }
1142
1143 success = true;
1144 }
1145 }
1146
1147 if (!success && m == 2)
1148 {
1149 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
1150 {
1151 bool available = true;
1152
1153 for (int y = 0; y < n && available; y++)
1154 {
1155 for (int x = 2; x < 4 && available; x++)
1156 {
1157 if (packing[r + y][x])
1158 {
1159 available = false;
1160 }
1161 }
1162 }
1163
1164 if (available)
1165 {
1166 varying->reg = r;
1167 varying->col = 2;
1168
1169 for (int y = 0; y < n; y++)
1170 {
1171 for (int x = 2; x < 4; x++)
1172 {
1173 packing[r + y][x] = &*varying;
1174 }
1175 }
1176
1177 success = true;
1178 }
1179 }
1180 }
1181 }
1182 else if (m == 1)
1183 {
1184 int space[4] = {0};
1185
1186 for (int y = 0; y < maxVaryingVectors; y++)
1187 {
1188 for (int x = 0; x < 4; x++)
1189 {
1190 space[x] += packing[y][x] ? 0 : 1;
1191 }
1192 }
1193
1194 int column = 0;
1195
1196 for (int x = 0; x < 4; x++)
1197 {
1198 if (space[x] >= n && space[x] < space[column])
1199 {
1200 column = x;
1201 }
1202 }
1203
1204 if (space[column] >= n)
1205 {
1206 for (int r = 0; r < maxVaryingVectors; r++)
1207 {
1208 if (!packing[r][column])
1209 {
1210 varying->reg = r;
1211
1212 for (int y = r; y < r + n; y++)
1213 {
1214 packing[y][column] = &*varying;
1215 }
1216
1217 break;
1218 }
1219 }
1220
1221 varying->col = column;
1222
1223 success = true;
1224 }
1225 }
1226 else UNREACHABLE();
1227
1228 if (!success)
1229 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001230 infoLog.append("Could not pack varying %s", varying->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001231
1232 return -1;
1233 }
1234 }
1235
1236 // Return the number of used registers
1237 int registers = 0;
1238
1239 for (int r = 0; r < maxVaryingVectors; r++)
1240 {
1241 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1242 {
1243 registers++;
1244 }
1245 }
1246
1247 return registers;
1248}
1249
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001250bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001251{
1252 if (pixelHLSL.empty() || vertexHLSL.empty())
1253 {
1254 return false;
1255 }
1256
1257 // Reset the varying register assignments
1258 for (VaryingList::iterator fragVar = fragmentShader->mVaryings.begin(); fragVar != fragmentShader->mVaryings.end(); fragVar++)
1259 {
1260 fragVar->reg = -1;
1261 fragVar->col = -1;
1262 }
1263
1264 for (VaryingList::iterator vtxVar = vertexShader->mVaryings.begin(); vtxVar != vertexShader->mVaryings.end(); vtxVar++)
1265 {
1266 vtxVar->reg = -1;
1267 vtxVar->col = -1;
1268 }
1269
1270 // Map the varyings to the register file
1271 const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001272 int registers = packVaryings(infoLog, packing, fragmentShader);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001273
1274 if (registers < 0)
1275 {
1276 return false;
1277 }
1278
1279 // Write the HLSL input/output declarations
1280 Context *context = getContext();
1281 const bool sm3 = context->supportsShaderModel3();
1282 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1283
1284 if (registers == maxVaryingVectors && fragmentShader->mUsesFragCoord)
1285 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001286 infoLog.append("No varying registers left to support gl_FragCoord");
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001287
1288 return false;
1289 }
1290
1291 for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
1292 {
1293 bool matched = false;
1294
1295 for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
1296 {
1297 if (output->name == input->name)
1298 {
1299 if (output->type != input->type || output->size != input->size)
1300 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001301 infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001302
1303 return false;
1304 }
1305
1306 output->reg = input->reg;
1307 output->col = input->col;
1308
1309 matched = true;
1310 break;
1311 }
1312 }
1313
1314 if (!matched)
1315 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001316 infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001317
1318 return false;
1319 }
1320 }
1321
daniel@transgaming.com08b3e402012-07-04 19:16:35 +00001322 std::string varyingSemantic = (vertexShader->mUsesPointSize && sm3 ? "COLOR" : "TEXCOORD");
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001323
1324 vertexHLSL += "struct VS_INPUT\n"
1325 "{\n";
1326
1327 int semanticIndex = 0;
1328 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
1329 {
1330 switch (attribute->type)
1331 {
1332 case GL_FLOAT: vertexHLSL += " float "; break;
1333 case GL_FLOAT_VEC2: vertexHLSL += " float2 "; break;
1334 case GL_FLOAT_VEC3: vertexHLSL += " float3 "; break;
1335 case GL_FLOAT_VEC4: vertexHLSL += " float4 "; break;
1336 case GL_FLOAT_MAT2: vertexHLSL += " float2x2 "; break;
1337 case GL_FLOAT_MAT3: vertexHLSL += " float3x3 "; break;
1338 case GL_FLOAT_MAT4: vertexHLSL += " float4x4 "; break;
1339 default: UNREACHABLE();
1340 }
1341
1342 vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
1343
1344 semanticIndex += VariableRowCount(attribute->type);
1345 }
1346
1347 vertexHLSL += "};\n"
1348 "\n"
1349 "struct VS_OUTPUT\n"
1350 "{\n"
1351 " float4 gl_Position : POSITION;\n";
1352
1353 for (int r = 0; r < registers; r++)
1354 {
1355 int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
1356
1357 vertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
1358 }
1359
1360 if (fragmentShader->mUsesFragCoord)
1361 {
1362 vertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
1363 }
1364
1365 if (vertexShader->mUsesPointSize && sm3)
1366 {
1367 vertexHLSL += " float gl_PointSize : PSIZE;\n";
1368 }
1369
1370 vertexHLSL += "};\n"
1371 "\n"
1372 "VS_OUTPUT main(VS_INPUT input)\n"
1373 "{\n";
1374
1375 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
1376 {
1377 vertexHLSL += " " + decorateAttribute(attribute->name) + " = ";
1378
1379 if (VariableRowCount(attribute->type) > 1) // Matrix
1380 {
1381 vertexHLSL += "transpose";
1382 }
1383
1384 vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
1385 }
1386
1387 vertexHLSL += "\n"
1388 " gl_main();\n"
1389 "\n"
1390 " VS_OUTPUT output;\n"
1391 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001392 " output.gl_Position.y = -(gl_Position.y + dx_HalfPixelSize.y * gl_Position.w);\n"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001393 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1394 " output.gl_Position.w = gl_Position.w;\n";
1395
1396 if (vertexShader->mUsesPointSize && sm3)
1397 {
daniel@transgaming.com13be3e42012-07-04 19:16:24 +00001398 vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001399 }
1400
1401 if (fragmentShader->mUsesFragCoord)
1402 {
1403 vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
1404 }
1405
1406 for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
1407 {
1408 if (varying->reg >= 0)
1409 {
1410 for (int i = 0; i < varying->size; i++)
1411 {
1412 int rows = VariableRowCount(varying->type);
1413
1414 for (int j = 0; j < rows; j++)
1415 {
1416 int r = varying->reg + i * rows + j;
1417 vertexHLSL += " output.v" + str(r);
1418
1419 bool sharedRegister = false; // Register used by multiple varyings
1420
1421 for (int x = 0; x < 4; x++)
1422 {
1423 if (packing[r][x] && packing[r][x] != packing[r][0])
1424 {
1425 sharedRegister = true;
1426 break;
1427 }
1428 }
1429
1430 if(sharedRegister)
1431 {
1432 vertexHLSL += ".";
1433
1434 for (int x = 0; x < 4; x++)
1435 {
1436 if (packing[r][x] == &*varying)
1437 {
1438 switch(x)
1439 {
1440 case 0: vertexHLSL += "x"; break;
1441 case 1: vertexHLSL += "y"; break;
1442 case 2: vertexHLSL += "z"; break;
1443 case 3: vertexHLSL += "w"; break;
1444 }
1445 }
1446 }
1447 }
1448
1449 vertexHLSL += " = " + varying->name;
1450
1451 if (varying->array)
1452 {
1453 vertexHLSL += "[" + str(i) + "]";
1454 }
1455
1456 if (rows > 1)
1457 {
1458 vertexHLSL += "[" + str(j) + "]";
1459 }
1460
1461 vertexHLSL += ";\n";
1462 }
1463 }
1464 }
1465 }
1466
1467 vertexHLSL += "\n"
1468 " return output;\n"
1469 "}\n";
1470
1471 pixelHLSL += "struct PS_INPUT\n"
1472 "{\n";
1473
1474 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
1475 {
1476 if (varying->reg >= 0)
1477 {
1478 for (int i = 0; i < varying->size; i++)
1479 {
1480 int rows = VariableRowCount(varying->type);
1481 for (int j = 0; j < rows; j++)
1482 {
1483 std::string n = str(varying->reg + i * rows + j);
1484 pixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
1485 }
1486 }
1487 }
1488 else UNREACHABLE();
1489 }
1490
1491 if (fragmentShader->mUsesFragCoord)
1492 {
1493 pixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
1494 if (sm3) {
1495 pixelHLSL += " float2 dx_VPos : VPOS;\n";
1496 }
1497 }
1498
1499 if (fragmentShader->mUsesPointCoord && sm3)
1500 {
1501 pixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
1502 }
1503
1504 if (fragmentShader->mUsesFrontFacing)
1505 {
1506 pixelHLSL += " float vFace : VFACE;\n";
1507 }
1508
1509 pixelHLSL += "};\n"
1510 "\n"
1511 "struct PS_OUTPUT\n"
1512 "{\n"
1513 " float4 gl_Color[1] : COLOR;\n"
1514 "};\n"
1515 "\n"
1516 "PS_OUTPUT main(PS_INPUT input)\n"
1517 "{\n";
1518
1519 if (fragmentShader->mUsesFragCoord)
1520 {
1521 pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
1522
1523 if (sm3)
1524 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001525 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001526 " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001527 }
1528 else
1529 {
1530 // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget()
1531 pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n"
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001532 " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001533 }
1534
1535 pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
1536 " gl_FragCoord.w = rhw;\n";
1537 }
1538
1539 if (fragmentShader->mUsesPointCoord && sm3)
1540 {
apatrick@chromium.org9616e582012-06-22 18:27:01 +00001541 pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
1542 pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001543 }
1544
1545 if (fragmentShader->mUsesFrontFacing)
1546 {
1547 pixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
1548 }
1549
1550 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
1551 {
1552 if (varying->reg >= 0)
1553 {
1554 for (int i = 0; i < varying->size; i++)
1555 {
1556 int rows = VariableRowCount(varying->type);
1557 for (int j = 0; j < rows; j++)
1558 {
1559 std::string n = str(varying->reg + i * rows + j);
1560 pixelHLSL += " " + varying->name;
1561
1562 if (varying->array)
1563 {
1564 pixelHLSL += "[" + str(i) + "]";
1565 }
1566
1567 if (rows > 1)
1568 {
1569 pixelHLSL += "[" + str(j) + "]";
1570 }
1571
1572 pixelHLSL += " = input.v" + n + ";\n";
1573 }
1574 }
1575 }
1576 else UNREACHABLE();
1577 }
1578
1579 pixelHLSL += "\n"
1580 " gl_main();\n"
1581 "\n"
1582 " PS_OUTPUT output;\n"
1583 " output.gl_Color[0] = gl_Color[0];\n"
1584 "\n"
1585 " return output;\n"
1586 "}\n";
1587
1588 return true;
1589}
1590
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001591bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
1592{
1593 std::istringstream stream((const char*) binary, length);
1594 stream >> std::boolalpha;
1595
1596 int format = 0;
1597 stream >> format;
1598 if (format != GL_PROGRAM_BINARY_ANGLE)
1599 {
1600 infoLog.append("Invalid program binary format.");
1601 return false;
1602 }
1603
1604 int version = 0;
1605 stream >> version;
1606 if (version != BUILD_REVISION)
1607 {
1608 infoLog.append("Invalid program binary version.");
1609 return false;
1610 }
1611
1612 for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1613 {
1614 stream >> mLinkedAttribute[i].type;
1615 std::string name;
1616 stream >> name;
1617 mLinkedAttribute[i].name = name.substr(1, name.length() - 2);
1618 stream >> mSemanticIndex[i];
1619 }
1620
1621 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1622 {
1623 stream >> mSamplersPS[i].active;
1624 stream >> mSamplersPS[i].logicalTextureUnit;
1625
1626 int textureType;
1627 stream >> textureType;
1628 mSamplersPS[i].textureType = (TextureType) textureType;
1629 }
1630
1631 for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
1632 {
1633 stream >> mSamplersVS[i].active;
1634 stream >> mSamplersVS[i].logicalTextureUnit;
1635
1636 int textureType;
1637 stream >> textureType;
1638 mSamplersVS[i].textureType = (TextureType) textureType;
1639 }
1640
1641 stream >> mUsedVertexSamplerRange;
1642 stream >> mUsedPixelSamplerRange;
1643
1644 unsigned int size;
1645 stream >> size;
1646 if (!stream.good())
1647 {
1648 infoLog.append("Invalid program binary.");
1649 return false;
1650 }
1651
1652 mUniforms.resize(size);
1653 for (unsigned int i = 0; i < size; ++i)
1654 {
1655 GLenum type;
1656 std::string _name;
1657 unsigned int arraySize;
1658
1659 stream >> type >> _name >> arraySize;
1660
1661 mUniforms[i] = new Uniform(type, _name.substr(1, _name.length() - 2), arraySize);
1662
1663 stream >> mUniforms[i]->ps.float4Index;
1664 stream >> mUniforms[i]->ps.samplerIndex;
1665 stream >> mUniforms[i]->ps.boolIndex;
1666 stream >> mUniforms[i]->ps.registerCount;
1667
1668 stream >> mUniforms[i]->vs.float4Index;
1669 stream >> mUniforms[i]->vs.samplerIndex;
1670 stream >> mUniforms[i]->vs.boolIndex;
1671 stream >> mUniforms[i]->vs.registerCount;
1672 }
1673
1674 stream >> size;
1675 if (!stream.good())
1676 {
1677 infoLog.append("Invalid program binary.");
1678 return false;
1679 }
1680
1681 mUniformIndex.resize(size);
1682 for (unsigned int i = 0; i < size; ++i)
1683 {
1684 std::string name;
1685 stream >> name;
1686 mUniformIndex[i].name = name.substr(1, name.length() - 2);
1687 stream >> mUniformIndex[i].element;
1688 stream >> mUniformIndex[i].index;
1689 }
1690
1691 stream >> mDxDepthRangeLocation;
1692 stream >> mDxDepthLocation;
1693 stream >> mDxCoordLocation;
1694 stream >> mDxHalfPixelSizeLocation;
1695 stream >> mDxFrontCCWLocation;
1696 stream >> mDxPointsOrLinesLocation;
1697
1698 unsigned int pixelShaderSize;
1699 stream >> pixelShaderSize;
1700
1701 unsigned int vertexShaderSize;
1702 stream >> vertexShaderSize;
1703
1704 // Skip final newline.
1705 stream.ignore(1);
1706
1707 const char *ptr = (const char*) binary + stream.tellg();
1708
1709 const D3DCAPS9 *binaryIdentifier = (const D3DCAPS9*) ptr;
1710 ptr += sizeof(GUID);
1711
1712 D3DADAPTER_IDENTIFIER9 *currentIdentifier = getDisplay()->getAdapterIdentifier();
1713 if (memcmp(&currentIdentifier->DeviceIdentifier, binaryIdentifier, sizeof(GUID)) != 0)
1714 {
1715 infoLog.append("Invalid program binary.");
1716 return false;
1717 }
1718
1719 const char *pixelShaderFunction = ptr;
1720 ptr += pixelShaderSize;
1721
1722 const char *vertexShaderFunction = ptr;
1723 ptr += vertexShaderSize;
1724
1725 HRESULT result = mDevice->CreatePixelShader(reinterpret_cast<const DWORD*>(pixelShaderFunction), &mPixelExecutable);
1726 if (FAILED(result))
1727 {
1728 infoLog.append("Could not create pixel shader.");
1729 return false;
1730 }
1731
1732 result = mDevice->CreateVertexShader(reinterpret_cast<const DWORD*>(vertexShaderFunction), &mVertexExecutable);
1733 if (FAILED(result))
1734 {
1735 infoLog.append("Could not create vertex shader.");
1736 mPixelExecutable->Release();
1737 mPixelExecutable = NULL;
1738 return false;
1739 }
1740
1741 return true;
1742}
1743
1744bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
1745{
1746 std::ostringstream stream;
1747 stream << std::boolalpha;
1748
1749 stream << GL_PROGRAM_BINARY_ANGLE << std::endl;
1750 stream << BUILD_REVISION << std::endl;
1751
1752 for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1753 {
1754 stream << mLinkedAttribute[i].type << std::endl;
1755 stream << "\"" << mLinkedAttribute[i].name << "\"" << std::endl;
1756 stream << mSemanticIndex[i] << std::endl << std::endl;
1757 }
1758
1759 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1760 {
1761 stream << mSamplersPS[i].active << std::endl;
1762 stream << mSamplersPS[i].logicalTextureUnit << std::endl;
1763 stream << (int) mSamplersPS[i].textureType << std::endl << std::endl;
1764 }
1765
1766 for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
1767 {
1768 stream << mSamplersVS[i].active << std::endl;
1769 stream << mSamplersVS[i].logicalTextureUnit << std::endl;
1770 stream << (int) mSamplersVS[i].textureType << std::endl << std::endl;
1771 }
1772
1773 stream << mUsedVertexSamplerRange << std::endl;
1774 stream << mUsedPixelSamplerRange << std::endl << std::endl;
1775
1776 stream << mUniforms.size() << std::endl;
1777 for (unsigned int i = 0; i < mUniforms.size(); ++i)
1778 {
1779 stream << mUniforms[i]->type << std::endl;
1780 stream << "\"" << mUniforms[i]->_name << "\"" << std::endl;
1781 stream << mUniforms[i]->arraySize << std::endl << std::endl;
1782
1783 stream << mUniforms[i]->ps.float4Index << std::endl;
1784 stream << mUniforms[i]->ps.samplerIndex << std::endl;
1785 stream << mUniforms[i]->ps.boolIndex << std::endl;
1786 stream << mUniforms[i]->ps.registerCount << std::endl;
1787
1788 stream << mUniforms[i]->vs.float4Index << std::endl;
1789 stream << mUniforms[i]->vs.samplerIndex << std::endl;
1790 stream << mUniforms[i]->vs.boolIndex << std::endl;
1791 stream << mUniforms[i]->vs.registerCount << std::endl;
1792 }
1793
1794 stream << mUniformIndex.size() << std::endl;
1795 for (unsigned int i = 0; i < mUniformIndex.size(); ++i)
1796 {
1797 stream << "\"" << mUniformIndex[i].name << "\"" << std::endl;
1798 stream << mUniformIndex[i].element << std::endl;
1799 stream << mUniformIndex[i].index << std::endl << std::endl;
1800 }
1801
1802 stream << mDxDepthRangeLocation << std::endl;
1803 stream << mDxDepthLocation << std::endl;
1804 stream << mDxCoordLocation << std::endl;
1805 stream << mDxHalfPixelSizeLocation << std::endl;
1806 stream << mDxFrontCCWLocation << std::endl;
1807 stream << mDxPointsOrLinesLocation << std::endl;
1808
1809 UINT pixelShaderSize;
1810 HRESULT result = mPixelExecutable->GetFunction(NULL, &pixelShaderSize);
1811 ASSERT(SUCCEEDED(result));
1812 stream << pixelShaderSize << std::endl;
1813
1814 UINT vertexShaderSize;
1815 result = mVertexExecutable->GetFunction(NULL, &vertexShaderSize);
1816 ASSERT(SUCCEEDED(result));
1817 stream << vertexShaderSize << std::endl;
1818
1819 std::string text = stream.str();
1820
1821 D3DADAPTER_IDENTIFIER9 *identifier = getDisplay()->getAdapterIdentifier();
1822
1823 GLsizei totalLength = text.length() + sizeof(GUID) + pixelShaderSize + vertexShaderSize;
1824 if (totalLength > bufSize)
1825 {
1826 if (length)
1827 {
1828 *length = 0;
1829 }
1830
1831 return false;
1832 }
1833
1834 if (binary)
1835 {
1836 char *ptr = (char*) binary;
1837
1838 memcpy(ptr, text.c_str(), text.length());
1839 ptr += text.length();
1840
1841 memcpy(ptr, &identifier->DeviceIdentifier, sizeof(GUID));
1842 ptr += sizeof(GUID);
1843
1844 result = mPixelExecutable->GetFunction(ptr, &pixelShaderSize);
1845 ASSERT(SUCCEEDED(result));
1846 ptr += pixelShaderSize;
1847
1848 result = mVertexExecutable->GetFunction(ptr, &vertexShaderSize);
1849 ASSERT(SUCCEEDED(result));
1850 ptr += vertexShaderSize;
1851
1852 ASSERT(ptr - totalLength == binary);
1853 }
1854
1855 if (length)
1856 {
1857 *length = totalLength;
1858 }
1859
1860 return true;
1861}
1862
1863GLint ProgramBinary::getLength()
1864{
1865 GLint length;
1866 if (save(NULL, INT_MAX, &length))
1867 {
1868 return length;
1869 }
1870 else
1871 {
1872 return 0;
1873 }
1874}
1875
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001876bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001877{
1878 if (!fragmentShader || !fragmentShader->isCompiled())
1879 {
1880 return false;
1881 }
1882
1883 if (!vertexShader || !vertexShader->isCompiled())
1884 {
1885 return false;
1886 }
1887
1888 std::string pixelHLSL = fragmentShader->getHLSL();
1889 std::string vertexHLSL = vertexShader->getHLSL();
1890
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001891 if (!linkVaryings(infoLog, pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001892 {
1893 return false;
1894 }
1895
1896 Context *context = getContext();
1897 const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
1898 const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
1899
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001900 ID3D10Blob *vertexBinary = compileToBinary(infoLog, vertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
1901 ID3D10Blob *pixelBinary = compileToBinary(infoLog, pixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001902
1903 if (vertexBinary && pixelBinary)
1904 {
1905 HRESULT vertexResult = mDevice->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
1906 HRESULT pixelResult = mDevice->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
1907
1908 if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
1909 {
1910 return error(GL_OUT_OF_MEMORY, false);
1911 }
1912
1913 ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
1914
1915 vertexBinary->Release();
1916 pixelBinary->Release();
1917 vertexBinary = NULL;
1918 pixelBinary = NULL;
1919
1920 if (mVertexExecutable && mPixelExecutable)
1921 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001922 if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001923 {
1924 return false;
1925 }
1926
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001927 if (!linkUniforms(infoLog, GL_FRAGMENT_SHADER, mConstantTablePS))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001928 {
1929 return false;
1930 }
1931
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001932 if (!linkUniforms(infoLog, GL_VERTEX_SHADER, mConstantTableVS))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001933 {
1934 return false;
1935 }
1936
1937 // these uniforms are searched as already-decorated because gl_ and dx_
1938 // are reserved prefixes, and do not receive additional decoration
1939 mDxDepthRangeLocation = getUniformLocation("dx_DepthRange");
1940 mDxDepthLocation = getUniformLocation("dx_Depth");
1941 mDxCoordLocation = getUniformLocation("dx_Coord");
1942 mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize");
1943 mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW");
1944 mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines");
1945
1946 context->markDxUniformsDirty();
1947
1948 return true;
1949 }
1950 }
1951
1952 return false;
1953}
1954
1955// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001956bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001957{
1958 unsigned int usedLocations = 0;
1959
1960 // Link attributes that have a binding location
1961 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
1962 {
1963 int location = attributeBindings.getAttributeBinding(attribute->name);
1964
1965 if (location != -1) // Set by glBindAttribLocation
1966 {
1967 if (!mLinkedAttribute[location].name.empty())
1968 {
1969 // Multiple active attributes bound to the same location; not an error
1970 }
1971
1972 mLinkedAttribute[location] = *attribute;
1973
1974 int rows = VariableRowCount(attribute->type);
1975
1976 if (rows + location > MAX_VERTEX_ATTRIBS)
1977 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00001978 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001979
1980 return false;
1981 }
1982
1983 for (int i = 0; i < rows; i++)
1984 {
1985 usedLocations |= 1 << (location + i);
1986 }
1987 }
1988 }
1989
1990 // Link attributes that don't have a binding location
1991 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
1992 {
1993 int location = attributeBindings.getAttributeBinding(attribute->name);
1994
1995 if (location == -1) // Not set by glBindAttribLocation
1996 {
1997 int rows = VariableRowCount(attribute->type);
1998 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1999
2000 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
2001 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002002 infoLog.append("Too many active attributes (%s)", attribute->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002003
2004 return false; // Fail to link
2005 }
2006
2007 mLinkedAttribute[availableIndex] = *attribute;
2008 }
2009 }
2010
2011 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
2012 {
2013 int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
2014 int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
2015
2016 for (int r = 0; r < rows; r++)
2017 {
2018 mSemanticIndex[attributeIndex++] = index++;
2019 }
2020 }
2021
2022 return true;
2023}
2024
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002025bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, ID3DXConstantTable *constantTable)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002026{
2027 D3DXCONSTANTTABLE_DESC constantTableDescription;
2028
2029 constantTable->GetDesc(&constantTableDescription);
2030
2031 for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
2032 {
2033 D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
2034
2035 D3DXCONSTANT_DESC constantDescription;
2036 UINT descriptionCount = 1;
2037 HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
2038 ASSERT(SUCCEEDED(result));
2039
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002040 if (!defineUniform(infoLog, shader, constantHandle, constantDescription))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002041 {
2042 return false;
2043 }
2044 }
2045
2046 return true;
2047}
2048
2049// Adds the description of a constant found in the binary shader to the list of uniforms
2050// Returns true if succesful (uniform not already defined)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002051bool ProgramBinary::defineUniform(InfoLog &infoLog, GLenum shader, const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002052{
2053 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2054 {
2055 for (unsigned int i = 0; i < constantDescription.RegisterCount; i++)
2056 {
2057 D3DXHANDLE psConstant = mConstantTablePS->GetConstantByName(NULL, constantDescription.Name);
2058 D3DXHANDLE vsConstant = mConstantTableVS->GetConstantByName(NULL, constantDescription.Name);
2059
2060 if (psConstant)
2061 {
2062 unsigned int samplerIndex = mConstantTablePS->GetSamplerIndex(psConstant) + i;
2063
2064 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2065 {
2066 mSamplersPS[samplerIndex].active = true;
2067 mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
2068 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
2069 mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
2070 }
2071 else
2072 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002073 infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002074 return false;
2075 }
2076 }
2077
2078 if (vsConstant)
2079 {
2080 unsigned int samplerIndex = mConstantTableVS->GetSamplerIndex(vsConstant) + i;
2081
2082 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
2083 {
2084 mSamplersVS[samplerIndex].active = true;
2085 mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
2086 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
2087 mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
2088 }
2089 else
2090 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002091 infoLog.append("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002092 return false;
2093 }
2094 }
2095 }
2096 }
2097
2098 switch(constantDescription.Class)
2099 {
2100 case D3DXPC_STRUCT:
2101 {
2102 for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
2103 {
2104 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
2105 {
2106 D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
2107
2108 D3DXCONSTANT_DESC fieldDescription;
2109 UINT descriptionCount = 1;
2110
2111 HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
2112 ASSERT(SUCCEEDED(result));
2113
2114 std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
2115
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002116 if (!defineUniform(infoLog, shader, fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002117 {
2118 return false;
2119 }
2120 }
2121 }
2122
2123 return true;
2124 }
2125 case D3DXPC_SCALAR:
2126 case D3DXPC_VECTOR:
2127 case D3DXPC_MATRIX_COLUMNS:
2128 case D3DXPC_OBJECT:
2129 return defineUniform(shader, constantDescription, name + constantDescription.Name);
2130 default:
2131 UNREACHABLE();
2132 return false;
2133 }
2134}
2135
2136bool ProgramBinary::defineUniform(GLenum shader, const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
2137{
2138 Uniform *uniform = createUniform(constantDescription, _name);
2139
2140 if(!uniform)
2141 {
2142 return false;
2143 }
2144
2145 // Check if already defined
2146 GLint location = getUniformLocation(uniform->name);
2147 GLenum type = uniform->type;
2148
2149 if (location >= 0)
2150 {
2151 delete uniform;
2152 uniform = mUniforms[mUniformIndex[location].index];
2153 }
2154
2155 if (shader == GL_FRAGMENT_SHADER) uniform->ps.set(constantDescription);
2156 if (shader == GL_VERTEX_SHADER) uniform->vs.set(constantDescription);
2157
2158 if (location >= 0)
2159 {
2160 return uniform->type == type;
2161 }
2162
2163 mUniforms.push_back(uniform);
2164 unsigned int uniformIndex = mUniforms.size() - 1;
2165
2166 for (unsigned int i = 0; i < uniform->arraySize; ++i)
2167 {
2168 mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
2169 }
2170
2171 return true;
2172}
2173
2174Uniform *ProgramBinary::createUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
2175{
2176 if (constantDescription.Rows == 1) // Vectors and scalars
2177 {
2178 switch (constantDescription.Type)
2179 {
2180 case D3DXPT_SAMPLER2D:
2181 switch (constantDescription.Columns)
2182 {
2183 case 1: return new Uniform(GL_SAMPLER_2D, _name, constantDescription.Elements);
2184 default: UNREACHABLE();
2185 }
2186 break;
2187 case D3DXPT_SAMPLERCUBE:
2188 switch (constantDescription.Columns)
2189 {
2190 case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constantDescription.Elements);
2191 default: UNREACHABLE();
2192 }
2193 break;
2194 case D3DXPT_BOOL:
2195 switch (constantDescription.Columns)
2196 {
2197 case 1: return new Uniform(GL_BOOL, _name, constantDescription.Elements);
2198 case 2: return new Uniform(GL_BOOL_VEC2, _name, constantDescription.Elements);
2199 case 3: return new Uniform(GL_BOOL_VEC3, _name, constantDescription.Elements);
2200 case 4: return new Uniform(GL_BOOL_VEC4, _name, constantDescription.Elements);
2201 default: UNREACHABLE();
2202 }
2203 break;
2204 case D3DXPT_INT:
2205 switch (constantDescription.Columns)
2206 {
2207 case 1: return new Uniform(GL_INT, _name, constantDescription.Elements);
2208 case 2: return new Uniform(GL_INT_VEC2, _name, constantDescription.Elements);
2209 case 3: return new Uniform(GL_INT_VEC3, _name, constantDescription.Elements);
2210 case 4: return new Uniform(GL_INT_VEC4, _name, constantDescription.Elements);
2211 default: UNREACHABLE();
2212 }
2213 break;
2214 case D3DXPT_FLOAT:
2215 switch (constantDescription.Columns)
2216 {
2217 case 1: return new Uniform(GL_FLOAT, _name, constantDescription.Elements);
2218 case 2: return new Uniform(GL_FLOAT_VEC2, _name, constantDescription.Elements);
2219 case 3: return new Uniform(GL_FLOAT_VEC3, _name, constantDescription.Elements);
2220 case 4: return new Uniform(GL_FLOAT_VEC4, _name, constantDescription.Elements);
2221 default: UNREACHABLE();
2222 }
2223 break;
2224 default:
2225 UNREACHABLE();
2226 }
2227 }
2228 else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
2229 {
2230 switch (constantDescription.Type)
2231 {
2232 case D3DXPT_FLOAT:
2233 switch (constantDescription.Rows)
2234 {
2235 case 2: return new Uniform(GL_FLOAT_MAT2, _name, constantDescription.Elements);
2236 case 3: return new Uniform(GL_FLOAT_MAT3, _name, constantDescription.Elements);
2237 case 4: return new Uniform(GL_FLOAT_MAT4, _name, constantDescription.Elements);
2238 default: UNREACHABLE();
2239 }
2240 break;
2241 default: UNREACHABLE();
2242 }
2243 }
2244 else UNREACHABLE();
2245
2246 return 0;
2247}
2248
2249// This method needs to match OutputHLSL::decorate
2250std::string ProgramBinary::decorateAttribute(const std::string &name)
2251{
2252 if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
2253 {
2254 return "_" + name;
2255 }
2256
2257 return name;
2258}
2259
2260std::string ProgramBinary::undecorateUniform(const std::string &_name)
2261{
2262 std::string name = _name;
2263
2264 // Remove any structure field decoration
2265 size_t pos = 0;
2266 while ((pos = name.find("._", pos)) != std::string::npos)
2267 {
2268 name.replace(pos, 2, ".");
2269 }
2270
2271 // Remove the leading decoration
2272 if (name[0] == '_')
2273 {
2274 return name.substr(1);
2275 }
2276 else if (name.compare(0, 3, "ar_") == 0)
2277 {
2278 return name.substr(3);
2279 }
2280
2281 return name;
2282}
2283
2284void ProgramBinary::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
2285{
2286 float vector[D3D9_MAX_FLOAT_CONSTANTS * 4];
2287 BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS];
2288
2289 if (targetUniform->ps.float4Index >= 0 || targetUniform->vs.float4Index >= 0)
2290 {
2291 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2292 for (int i = 0; i < count; i++)
2293 {
2294 for (int j = 0; j < 4; j++)
2295 {
2296 if (j < width)
2297 {
2298 vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f;
2299 }
2300 else
2301 {
2302 vector[i * 4 + j] = 0.0f;
2303 }
2304 }
2305 }
2306 }
2307
2308 if (targetUniform->ps.boolIndex >= 0 || targetUniform->vs.boolIndex >= 0)
2309 {
2310 int psCount = targetUniform->ps.boolIndex >= 0 ? targetUniform->ps.registerCount : 0;
2311 int vsCount = targetUniform->vs.boolIndex >= 0 ? targetUniform->vs.registerCount : 0;
2312 int copyCount = std::min(count * width, std::max(psCount, vsCount));
2313 ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS);
2314 for (int i = 0; i < copyCount; i++)
2315 {
2316 boolVector[i] = v[i] != GL_FALSE;
2317 }
2318 }
2319
2320 if (targetUniform->ps.float4Index >= 0)
2321 {
2322 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, vector, targetUniform->ps.registerCount);
2323 }
2324
2325 if (targetUniform->ps.boolIndex >= 0)
2326 {
2327 mDevice->SetPixelShaderConstantB(targetUniform->ps.boolIndex, boolVector, targetUniform->ps.registerCount);
2328 }
2329
2330 if (targetUniform->vs.float4Index >= 0)
2331 {
2332 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, vector, targetUniform->vs.registerCount);
2333 }
2334
2335 if (targetUniform->vs.boolIndex >= 0)
2336 {
2337 mDevice->SetVertexShaderConstantB(targetUniform->vs.boolIndex, boolVector, targetUniform->vs.registerCount);
2338 }
2339}
2340
2341bool ProgramBinary::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
2342{
2343 if (targetUniform->ps.registerCount)
2344 {
2345 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, v, targetUniform->ps.registerCount);
2346 }
2347
2348 if (targetUniform->vs.registerCount)
2349 {
2350 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, v, targetUniform->vs.registerCount);
2351 }
2352
2353 return true;
2354}
2355
2356bool ProgramBinary::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
2357{
2358 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2359 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
2360
2361 for (int i = 0; i < count; i++)
2362 {
2363 vector[i] = D3DXVECTOR4((float)v[i], 0, 0, 0);
2364 }
2365
2366 if (targetUniform->ps.registerCount)
2367 {
2368 if (targetUniform->ps.samplerIndex >= 0)
2369 {
2370 unsigned int firstIndex = targetUniform->ps.samplerIndex;
2371
2372 for (int i = 0; i < count; i++)
2373 {
2374 unsigned int samplerIndex = firstIndex + i;
2375
2376 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2377 {
2378 ASSERT(mSamplersPS[samplerIndex].active);
2379 mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
2380 }
2381 }
2382 }
2383 else
2384 {
2385 ASSERT(targetUniform->ps.float4Index >= 0);
2386 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float*)vector, targetUniform->ps.registerCount);
2387 }
2388 }
2389
2390 if (targetUniform->vs.registerCount)
2391 {
2392 if (targetUniform->vs.samplerIndex >= 0)
2393 {
2394 unsigned int firstIndex = targetUniform->vs.samplerIndex;
2395
2396 for (int i = 0; i < count; i++)
2397 {
2398 unsigned int samplerIndex = firstIndex + i;
2399
2400 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
2401 {
2402 ASSERT(mSamplersVS[samplerIndex].active);
2403 mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
2404 }
2405 }
2406 }
2407 else
2408 {
2409 ASSERT(targetUniform->vs.float4Index >= 0);
2410 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
2411 }
2412 }
2413
2414 return true;
2415}
2416
2417bool ProgramBinary::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
2418{
2419 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2420 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
2421
2422 for (int i = 0; i < count; i++)
2423 {
2424 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
2425
2426 v += 2;
2427 }
2428
2429 applyUniformniv(targetUniform, count, vector);
2430
2431 return true;
2432}
2433
2434bool ProgramBinary::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
2435{
2436 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2437 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
2438
2439 for (int i = 0; i < count; i++)
2440 {
2441 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
2442
2443 v += 3;
2444 }
2445
2446 applyUniformniv(targetUniform, count, vector);
2447
2448 return true;
2449}
2450
2451bool ProgramBinary::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
2452{
2453 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2454 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
2455
2456 for (int i = 0; i < count; i++)
2457 {
2458 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
2459
2460 v += 4;
2461 }
2462
2463 applyUniformniv(targetUniform, count, vector);
2464
2465 return true;
2466}
2467
2468void ProgramBinary::applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector)
2469{
2470 if (targetUniform->ps.registerCount)
2471 {
2472 ASSERT(targetUniform->ps.float4Index >= 0);
2473 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float *)vector, targetUniform->ps.registerCount);
2474 }
2475
2476 if (targetUniform->vs.registerCount)
2477 {
2478 ASSERT(targetUniform->vs.float4Index >= 0);
2479 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
2480 }
2481}
2482
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002483bool ProgramBinary::isValidated() const
2484{
2485 return mValidated;
2486}
2487
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002488void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2489{
2490 // Skip over inactive attributes
2491 unsigned int activeAttribute = 0;
2492 unsigned int attribute;
2493 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2494 {
2495 if (mLinkedAttribute[attribute].name.empty())
2496 {
2497 continue;
2498 }
2499
2500 if (activeAttribute == index)
2501 {
2502 break;
2503 }
2504
2505 activeAttribute++;
2506 }
2507
2508 if (bufsize > 0)
2509 {
2510 const char *string = mLinkedAttribute[attribute].name.c_str();
2511
2512 strncpy(name, string, bufsize);
2513 name[bufsize - 1] = '\0';
2514
2515 if (length)
2516 {
2517 *length = strlen(name);
2518 }
2519 }
2520
2521 *size = 1; // Always a single 'type' instance
2522
2523 *type = mLinkedAttribute[attribute].type;
2524}
2525
2526GLint ProgramBinary::getActiveAttributeCount()
2527{
2528 int count = 0;
2529
2530 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2531 {
2532 if (!mLinkedAttribute[attributeIndex].name.empty())
2533 {
2534 count++;
2535 }
2536 }
2537
2538 return count;
2539}
2540
2541GLint ProgramBinary::getActiveAttributeMaxLength()
2542{
2543 int maxLength = 0;
2544
2545 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2546 {
2547 if (!mLinkedAttribute[attributeIndex].name.empty())
2548 {
2549 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2550 }
2551 }
2552
2553 return maxLength;
2554}
2555
2556void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2557{
2558 // Skip over internal uniforms
2559 unsigned int activeUniform = 0;
2560 unsigned int uniform;
2561 for (uniform = 0; uniform < mUniforms.size(); uniform++)
2562 {
2563 if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0)
2564 {
2565 continue;
2566 }
2567
2568 if (activeUniform == index)
2569 {
2570 break;
2571 }
2572
2573 activeUniform++;
2574 }
2575
2576 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2577
2578 if (bufsize > 0)
2579 {
2580 std::string string = mUniforms[uniform]->name;
2581
2582 if (mUniforms[uniform]->isArray())
2583 {
2584 string += "[0]";
2585 }
2586
2587 strncpy(name, string.c_str(), bufsize);
2588 name[bufsize - 1] = '\0';
2589
2590 if (length)
2591 {
2592 *length = strlen(name);
2593 }
2594 }
2595
2596 *size = mUniforms[uniform]->arraySize;
2597
2598 *type = mUniforms[uniform]->type;
2599}
2600
2601GLint ProgramBinary::getActiveUniformCount()
2602{
2603 int count = 0;
2604
2605 unsigned int numUniforms = mUniforms.size();
2606 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2607 {
2608 if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
2609 {
2610 count++;
2611 }
2612 }
2613
2614 return count;
2615}
2616
2617GLint ProgramBinary::getActiveUniformMaxLength()
2618{
2619 int maxLength = 0;
2620
2621 unsigned int numUniforms = mUniforms.size();
2622 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2623 {
2624 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
2625 {
2626 int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
2627 if (mUniforms[uniformIndex]->isArray())
2628 {
2629 length += 3; // Counting in "[0]".
2630 }
2631 maxLength = std::max(length, maxLength);
2632 }
2633 }
2634
2635 return maxLength;
2636}
2637
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002638void ProgramBinary::validate(InfoLog &infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002639{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002640 applyUniforms();
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002641 if (!validateSamplers(&infoLog))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002642 {
2643 mValidated = false;
2644 }
2645 else
2646 {
2647 mValidated = true;
2648 }
2649}
2650
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002651bool ProgramBinary::validateSamplers(InfoLog *infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002652{
2653 // if any two active samplers in a program are of different types, but refer to the same
2654 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2655 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2656
2657 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
2658 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2659
2660 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2661 {
2662 textureUnitType[i] = TEXTURE_UNKNOWN;
2663 }
2664
2665 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
2666 {
2667 if (mSamplersPS[i].active)
2668 {
2669 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
2670
2671 if (unit >= maxCombinedTextureImageUnits)
2672 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002673 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002674 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002675 infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002676 }
2677
2678 return false;
2679 }
2680
2681 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2682 {
2683 if (mSamplersPS[i].textureType != textureUnitType[unit])
2684 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002685 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002686 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002687 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002688 }
2689
2690 return false;
2691 }
2692 }
2693 else
2694 {
2695 textureUnitType[unit] = mSamplersPS[i].textureType;
2696 }
2697 }
2698 }
2699
2700 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
2701 {
2702 if (mSamplersVS[i].active)
2703 {
2704 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
2705
2706 if (unit >= maxCombinedTextureImageUnits)
2707 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002708 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002709 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002710 infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002711 }
2712
2713 return false;
2714 }
2715
2716 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2717 {
2718 if (mSamplersVS[i].textureType != textureUnitType[unit])
2719 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002720 if (infoLog)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002721 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +00002722 infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002723 }
2724
2725 return false;
2726 }
2727 }
2728 else
2729 {
2730 textureUnitType[unit] = mSamplersVS[i].textureType;
2731 }
2732 }
2733 }
2734
2735 return true;
2736}
2737
2738GLint ProgramBinary::getDxDepthRangeLocation() const
2739{
2740 return mDxDepthRangeLocation;
2741}
2742
2743GLint ProgramBinary::getDxDepthLocation() const
2744{
2745 return mDxDepthLocation;
2746}
2747
2748GLint ProgramBinary::getDxCoordLocation() const
2749{
2750 return mDxCoordLocation;
2751}
2752
2753GLint ProgramBinary::getDxHalfPixelSizeLocation() const
2754{
2755 return mDxHalfPixelSizeLocation;
2756}
2757
2758GLint ProgramBinary::getDxFrontCCWLocation() const
2759{
2760 return mDxFrontCCWLocation;
2761}
2762
2763GLint ProgramBinary::getDxPointsOrLinesLocation() const
2764{
2765 return mDxPointsOrLinesLocation;
2766}
2767
apatrick@chromium.org90080e32012-07-09 22:15:33 +00002768ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
2769{
2770}
2771
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00002772}