gfx/angle/src/libGLESv2/ProgramBinary.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial