1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/ProgramBinary.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2622 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// Program.cpp: Implements the gl::Program class. Implements GL program objects 1.12 +// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. 1.13 + 1.14 +#include "libGLESv2/BinaryStream.h" 1.15 +#include "libGLESv2/ProgramBinary.h" 1.16 +#include "libGLESv2/renderer/ShaderExecutable.h" 1.17 + 1.18 +#include "common/debug.h" 1.19 +#include "common/version.h" 1.20 +#include "utilities.h" 1.21 + 1.22 +#include "libGLESv2/main.h" 1.23 +#include "libGLESv2/Shader.h" 1.24 +#include "libGLESv2/Program.h" 1.25 +#include "libGLESv2/renderer/Renderer.h" 1.26 +#include "libGLESv2/renderer/VertexDataManager.h" 1.27 + 1.28 +#include <algorithm> 1.29 + 1.30 +#undef near 1.31 +#undef far 1.32 + 1.33 +namespace gl 1.34 +{ 1.35 +std::string str(int i) 1.36 +{ 1.37 + char buffer[20]; 1.38 + snprintf(buffer, sizeof(buffer), "%d", i); 1.39 + return buffer; 1.40 +} 1.41 + 1.42 +UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) 1.43 + : name(name), element(element), index(index) 1.44 +{ 1.45 +} 1.46 + 1.47 +unsigned int ProgramBinary::mCurrentSerial = 1; 1.48 + 1.49 +ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial()) 1.50 +{ 1.51 + mPixelExecutable = NULL; 1.52 + mVertexExecutable = NULL; 1.53 + mGeometryExecutable = NULL; 1.54 + 1.55 + mValidated = false; 1.56 + 1.57 + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) 1.58 + { 1.59 + mSemanticIndex[index] = -1; 1.60 + } 1.61 + 1.62 + for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) 1.63 + { 1.64 + mSamplersPS[index].active = false; 1.65 + } 1.66 + 1.67 + for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) 1.68 + { 1.69 + mSamplersVS[index].active = false; 1.70 + } 1.71 + 1.72 + mUsedVertexSamplerRange = 0; 1.73 + mUsedPixelSamplerRange = 0; 1.74 + mUsesPointSize = false; 1.75 +} 1.76 + 1.77 +ProgramBinary::~ProgramBinary() 1.78 +{ 1.79 + delete mPixelExecutable; 1.80 + mPixelExecutable = NULL; 1.81 + 1.82 + delete mVertexExecutable; 1.83 + mVertexExecutable = NULL; 1.84 + 1.85 + delete mGeometryExecutable; 1.86 + mGeometryExecutable = NULL; 1.87 + 1.88 + while (!mUniforms.empty()) 1.89 + { 1.90 + delete mUniforms.back(); 1.91 + mUniforms.pop_back(); 1.92 + } 1.93 +} 1.94 + 1.95 +unsigned int ProgramBinary::getSerial() const 1.96 +{ 1.97 + return mSerial; 1.98 +} 1.99 + 1.100 +unsigned int ProgramBinary::issueSerial() 1.101 +{ 1.102 + return mCurrentSerial++; 1.103 +} 1.104 + 1.105 +rx::ShaderExecutable *ProgramBinary::getPixelExecutable() 1.106 +{ 1.107 + return mPixelExecutable; 1.108 +} 1.109 + 1.110 +rx::ShaderExecutable *ProgramBinary::getVertexExecutable() 1.111 +{ 1.112 + return mVertexExecutable; 1.113 +} 1.114 + 1.115 +rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() 1.116 +{ 1.117 + return mGeometryExecutable; 1.118 +} 1.119 + 1.120 +GLuint ProgramBinary::getAttributeLocation(const char *name) 1.121 +{ 1.122 + if (name) 1.123 + { 1.124 + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) 1.125 + { 1.126 + if (mLinkedAttribute[index].name == std::string(name)) 1.127 + { 1.128 + return index; 1.129 + } 1.130 + } 1.131 + } 1.132 + 1.133 + return -1; 1.134 +} 1.135 + 1.136 +int ProgramBinary::getSemanticIndex(int attributeIndex) 1.137 +{ 1.138 + ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); 1.139 + 1.140 + return mSemanticIndex[attributeIndex]; 1.141 +} 1.142 + 1.143 +// Returns one more than the highest sampler index used. 1.144 +GLint ProgramBinary::getUsedSamplerRange(SamplerType type) 1.145 +{ 1.146 + switch (type) 1.147 + { 1.148 + case SAMPLER_PIXEL: 1.149 + return mUsedPixelSamplerRange; 1.150 + case SAMPLER_VERTEX: 1.151 + return mUsedVertexSamplerRange; 1.152 + default: 1.153 + UNREACHABLE(); 1.154 + return 0; 1.155 + } 1.156 +} 1.157 + 1.158 +bool ProgramBinary::usesPointSize() const 1.159 +{ 1.160 + return mUsesPointSize; 1.161 +} 1.162 + 1.163 +bool ProgramBinary::usesPointSpriteEmulation() const 1.164 +{ 1.165 + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; 1.166 +} 1.167 + 1.168 +bool ProgramBinary::usesGeometryShader() const 1.169 +{ 1.170 + return usesPointSpriteEmulation(); 1.171 +} 1.172 + 1.173 +// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler 1.174 +// index (0-15 for the pixel shader and 0-3 for the vertex shader). 1.175 +GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) 1.176 +{ 1.177 + GLint logicalTextureUnit = -1; 1.178 + 1.179 + switch (type) 1.180 + { 1.181 + case SAMPLER_PIXEL: 1.182 + ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); 1.183 + 1.184 + if (mSamplersPS[samplerIndex].active) 1.185 + { 1.186 + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; 1.187 + } 1.188 + break; 1.189 + case SAMPLER_VERTEX: 1.190 + ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); 1.191 + 1.192 + if (mSamplersVS[samplerIndex].active) 1.193 + { 1.194 + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; 1.195 + } 1.196 + break; 1.197 + default: UNREACHABLE(); 1.198 + } 1.199 + 1.200 + if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) 1.201 + { 1.202 + return logicalTextureUnit; 1.203 + } 1.204 + 1.205 + return -1; 1.206 +} 1.207 + 1.208 +// Returns the texture type for a given Direct3D 9 sampler type and 1.209 +// index (0-15 for the pixel shader and 0-3 for the vertex shader). 1.210 +TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) 1.211 +{ 1.212 + switch (type) 1.213 + { 1.214 + case SAMPLER_PIXEL: 1.215 + ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); 1.216 + ASSERT(mSamplersPS[samplerIndex].active); 1.217 + return mSamplersPS[samplerIndex].textureType; 1.218 + case SAMPLER_VERTEX: 1.219 + ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); 1.220 + ASSERT(mSamplersVS[samplerIndex].active); 1.221 + return mSamplersVS[samplerIndex].textureType; 1.222 + default: UNREACHABLE(); 1.223 + } 1.224 + 1.225 + return TEXTURE_2D; 1.226 +} 1.227 + 1.228 +GLint ProgramBinary::getUniformLocation(std::string name) 1.229 +{ 1.230 + unsigned int subscript = 0; 1.231 + 1.232 + // Strip any trailing array operator and retrieve the subscript 1.233 + size_t open = name.find_last_of('['); 1.234 + size_t close = name.find_last_of(']'); 1.235 + if (open != std::string::npos && close == name.length() - 1) 1.236 + { 1.237 + subscript = atoi(name.substr(open + 1).c_str()); 1.238 + name.erase(open); 1.239 + } 1.240 + 1.241 + unsigned int numUniforms = mUniformIndex.size(); 1.242 + for (unsigned int location = 0; location < numUniforms; location++) 1.243 + { 1.244 + if (mUniformIndex[location].name == name && 1.245 + mUniformIndex[location].element == subscript) 1.246 + { 1.247 + return location; 1.248 + } 1.249 + } 1.250 + 1.251 + return -1; 1.252 +} 1.253 + 1.254 +bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) 1.255 +{ 1.256 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.257 + { 1.258 + return false; 1.259 + } 1.260 + 1.261 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.262 + targetUniform->dirty = true; 1.263 + 1.264 + int elementCount = targetUniform->elementCount(); 1.265 + 1.266 + if (elementCount == 1 && count > 1) 1.267 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.268 + 1.269 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.270 + 1.271 + if (targetUniform->type == GL_FLOAT) 1.272 + { 1.273 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; 1.274 + 1.275 + for (int i = 0; i < count; i++) 1.276 + { 1.277 + target[0] = v[0]; 1.278 + target[1] = 0; 1.279 + target[2] = 0; 1.280 + target[3] = 0; 1.281 + target += 4; 1.282 + v += 1; 1.283 + } 1.284 + } 1.285 + else if (targetUniform->type == GL_BOOL) 1.286 + { 1.287 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.288 + 1.289 + for (int i = 0; i < count; i++) 1.290 + { 1.291 + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; 1.292 + boolParams[1] = GL_FALSE; 1.293 + boolParams[2] = GL_FALSE; 1.294 + boolParams[3] = GL_FALSE; 1.295 + boolParams += 4; 1.296 + v += 1; 1.297 + } 1.298 + } 1.299 + else 1.300 + { 1.301 + return false; 1.302 + } 1.303 + 1.304 + return true; 1.305 +} 1.306 + 1.307 +bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) 1.308 +{ 1.309 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.310 + { 1.311 + return false; 1.312 + } 1.313 + 1.314 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.315 + targetUniform->dirty = true; 1.316 + 1.317 + int elementCount = targetUniform->elementCount(); 1.318 + 1.319 + if (elementCount == 1 && count > 1) 1.320 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.321 + 1.322 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.323 + 1.324 + if (targetUniform->type == GL_FLOAT_VEC2) 1.325 + { 1.326 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; 1.327 + 1.328 + for (int i = 0; i < count; i++) 1.329 + { 1.330 + target[0] = v[0]; 1.331 + target[1] = v[1]; 1.332 + target[2] = 0; 1.333 + target[3] = 0; 1.334 + target += 4; 1.335 + v += 2; 1.336 + } 1.337 + } 1.338 + else if (targetUniform->type == GL_BOOL_VEC2) 1.339 + { 1.340 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.341 + 1.342 + for (int i = 0; i < count; i++) 1.343 + { 1.344 + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; 1.345 + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; 1.346 + boolParams[2] = GL_FALSE; 1.347 + boolParams[3] = GL_FALSE; 1.348 + boolParams += 4; 1.349 + v += 2; 1.350 + } 1.351 + } 1.352 + else 1.353 + { 1.354 + return false; 1.355 + } 1.356 + 1.357 + return true; 1.358 +} 1.359 + 1.360 +bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) 1.361 +{ 1.362 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.363 + { 1.364 + return false; 1.365 + } 1.366 + 1.367 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.368 + targetUniform->dirty = true; 1.369 + 1.370 + int elementCount = targetUniform->elementCount(); 1.371 + 1.372 + if (elementCount == 1 && count > 1) 1.373 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.374 + 1.375 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.376 + 1.377 + if (targetUniform->type == GL_FLOAT_VEC3) 1.378 + { 1.379 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; 1.380 + 1.381 + for (int i = 0; i < count; i++) 1.382 + { 1.383 + target[0] = v[0]; 1.384 + target[1] = v[1]; 1.385 + target[2] = v[2]; 1.386 + target[3] = 0; 1.387 + target += 4; 1.388 + v += 3; 1.389 + } 1.390 + } 1.391 + else if (targetUniform->type == GL_BOOL_VEC3) 1.392 + { 1.393 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.394 + 1.395 + for (int i = 0; i < count; i++) 1.396 + { 1.397 + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; 1.398 + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; 1.399 + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; 1.400 + boolParams[3] = GL_FALSE; 1.401 + boolParams += 4; 1.402 + v += 3; 1.403 + } 1.404 + } 1.405 + else 1.406 + { 1.407 + return false; 1.408 + } 1.409 + 1.410 + return true; 1.411 +} 1.412 + 1.413 +bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) 1.414 +{ 1.415 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.416 + { 1.417 + return false; 1.418 + } 1.419 + 1.420 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.421 + targetUniform->dirty = true; 1.422 + 1.423 + int elementCount = targetUniform->elementCount(); 1.424 + 1.425 + if (elementCount == 1 && count > 1) 1.426 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.427 + 1.428 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.429 + 1.430 + if (targetUniform->type == GL_FLOAT_VEC4) 1.431 + { 1.432 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; 1.433 + 1.434 + for (int i = 0; i < count; i++) 1.435 + { 1.436 + target[0] = v[0]; 1.437 + target[1] = v[1]; 1.438 + target[2] = v[2]; 1.439 + target[3] = v[3]; 1.440 + target += 4; 1.441 + v += 4; 1.442 + } 1.443 + } 1.444 + else if (targetUniform->type == GL_BOOL_VEC4) 1.445 + { 1.446 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.447 + 1.448 + for (int i = 0; i < count; i++) 1.449 + { 1.450 + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; 1.451 + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; 1.452 + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; 1.453 + boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE; 1.454 + boolParams += 4; 1.455 + v += 4; 1.456 + } 1.457 + } 1.458 + else 1.459 + { 1.460 + return false; 1.461 + } 1.462 + 1.463 + return true; 1.464 +} 1.465 + 1.466 +template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight> 1.467 +void transposeMatrix(T *target, const GLfloat *value) 1.468 +{ 1.469 + int copyWidth = std::min(targetWidth, srcWidth); 1.470 + int copyHeight = std::min(targetHeight, srcHeight); 1.471 + 1.472 + for (int x = 0; x < copyWidth; x++) 1.473 + { 1.474 + for (int y = 0; y < copyHeight; y++) 1.475 + { 1.476 + target[x * targetWidth + y] = (T)value[y * srcWidth + x]; 1.477 + } 1.478 + } 1.479 + // clear unfilled right side 1.480 + for (int y = 0; y < copyHeight; y++) 1.481 + { 1.482 + for (int x = srcWidth; x < targetWidth; x++) 1.483 + { 1.484 + target[y * targetWidth + x] = (T)0; 1.485 + } 1.486 + } 1.487 + // clear unfilled bottom. 1.488 + for (int y = srcHeight; y < targetHeight; y++) 1.489 + { 1.490 + for (int x = 0; x < targetWidth; x++) 1.491 + { 1.492 + target[y * targetWidth + x] = (T)0; 1.493 + } 1.494 + } 1.495 +} 1.496 + 1.497 +bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value) 1.498 +{ 1.499 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.500 + { 1.501 + return false; 1.502 + } 1.503 + 1.504 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.505 + targetUniform->dirty = true; 1.506 + 1.507 + if (targetUniform->type != GL_FLOAT_MAT2) 1.508 + { 1.509 + return false; 1.510 + } 1.511 + 1.512 + int elementCount = targetUniform->elementCount(); 1.513 + 1.514 + if (elementCount == 1 && count > 1) 1.515 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.516 + 1.517 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.518 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8; 1.519 + 1.520 + for (int i = 0; i < count; i++) 1.521 + { 1.522 + transposeMatrix<GLfloat,4,2,2,2>(target, value); 1.523 + target += 8; 1.524 + value += 4; 1.525 + } 1.526 + 1.527 + return true; 1.528 +} 1.529 + 1.530 +bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value) 1.531 +{ 1.532 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.533 + { 1.534 + return false; 1.535 + } 1.536 + 1.537 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.538 + targetUniform->dirty = true; 1.539 + 1.540 + if (targetUniform->type != GL_FLOAT_MAT3) 1.541 + { 1.542 + return false; 1.543 + } 1.544 + 1.545 + int elementCount = targetUniform->elementCount(); 1.546 + 1.547 + if (elementCount == 1 && count > 1) 1.548 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.549 + 1.550 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.551 + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12; 1.552 + 1.553 + for (int i = 0; i < count; i++) 1.554 + { 1.555 + transposeMatrix<GLfloat,4,3,3,3>(target, value); 1.556 + target += 12; 1.557 + value += 9; 1.558 + } 1.559 + 1.560 + return true; 1.561 +} 1.562 + 1.563 + 1.564 +bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value) 1.565 +{ 1.566 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.567 + { 1.568 + return false; 1.569 + } 1.570 + 1.571 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.572 + targetUniform->dirty = true; 1.573 + 1.574 + if (targetUniform->type != GL_FLOAT_MAT4) 1.575 + { 1.576 + return false; 1.577 + } 1.578 + 1.579 + int elementCount = targetUniform->elementCount(); 1.580 + 1.581 + if (elementCount == 1 && count > 1) 1.582 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.583 + 1.584 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.585 + GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16); 1.586 + 1.587 + for (int i = 0; i < count; i++) 1.588 + { 1.589 + transposeMatrix<GLfloat,4,4,4,4>(target, value); 1.590 + target += 16; 1.591 + value += 16; 1.592 + } 1.593 + 1.594 + return true; 1.595 +} 1.596 + 1.597 +bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) 1.598 +{ 1.599 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.600 + { 1.601 + return false; 1.602 + } 1.603 + 1.604 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.605 + targetUniform->dirty = true; 1.606 + 1.607 + int elementCount = targetUniform->elementCount(); 1.608 + 1.609 + if (elementCount == 1 && count > 1) 1.610 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.611 + 1.612 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.613 + 1.614 + if (targetUniform->type == GL_INT || 1.615 + targetUniform->type == GL_SAMPLER_2D || 1.616 + targetUniform->type == GL_SAMPLER_CUBE) 1.617 + { 1.618 + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.619 + 1.620 + for (int i = 0; i < count; i++) 1.621 + { 1.622 + target[0] = v[0]; 1.623 + target[1] = 0; 1.624 + target[2] = 0; 1.625 + target[3] = 0; 1.626 + target += 4; 1.627 + v += 1; 1.628 + } 1.629 + } 1.630 + else if (targetUniform->type == GL_BOOL) 1.631 + { 1.632 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.633 + 1.634 + for (int i = 0; i < count; i++) 1.635 + { 1.636 + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; 1.637 + boolParams[1] = GL_FALSE; 1.638 + boolParams[2] = GL_FALSE; 1.639 + boolParams[3] = GL_FALSE; 1.640 + boolParams += 4; 1.641 + v += 1; 1.642 + } 1.643 + } 1.644 + else 1.645 + { 1.646 + return false; 1.647 + } 1.648 + 1.649 + return true; 1.650 +} 1.651 + 1.652 +bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) 1.653 +{ 1.654 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.655 + { 1.656 + return false; 1.657 + } 1.658 + 1.659 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.660 + targetUniform->dirty = true; 1.661 + 1.662 + int elementCount = targetUniform->elementCount(); 1.663 + 1.664 + if (elementCount == 1 && count > 1) 1.665 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.666 + 1.667 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.668 + 1.669 + if (targetUniform->type == GL_INT_VEC2) 1.670 + { 1.671 + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.672 + 1.673 + for (int i = 0; i < count; i++) 1.674 + { 1.675 + target[0] = v[0]; 1.676 + target[1] = v[1]; 1.677 + target[2] = 0; 1.678 + target[3] = 0; 1.679 + target += 4; 1.680 + v += 2; 1.681 + } 1.682 + } 1.683 + else if (targetUniform->type == GL_BOOL_VEC2) 1.684 + { 1.685 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.686 + 1.687 + for (int i = 0; i < count; i++) 1.688 + { 1.689 + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; 1.690 + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; 1.691 + boolParams[2] = GL_FALSE; 1.692 + boolParams[3] = GL_FALSE; 1.693 + boolParams += 4; 1.694 + v += 2; 1.695 + } 1.696 + } 1.697 + else 1.698 + { 1.699 + return false; 1.700 + } 1.701 + 1.702 + return true; 1.703 +} 1.704 + 1.705 +bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) 1.706 +{ 1.707 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.708 + { 1.709 + return false; 1.710 + } 1.711 + 1.712 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.713 + targetUniform->dirty = true; 1.714 + 1.715 + int elementCount = targetUniform->elementCount(); 1.716 + 1.717 + if (elementCount == 1 && count > 1) 1.718 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.719 + 1.720 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.721 + 1.722 + if (targetUniform->type == GL_INT_VEC3) 1.723 + { 1.724 + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.725 + 1.726 + for (int i = 0; i < count; i++) 1.727 + { 1.728 + target[0] = v[0]; 1.729 + target[1] = v[1]; 1.730 + target[2] = v[2]; 1.731 + target[3] = 0; 1.732 + target += 4; 1.733 + v += 3; 1.734 + } 1.735 + } 1.736 + else if (targetUniform->type == GL_BOOL_VEC3) 1.737 + { 1.738 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.739 + 1.740 + for (int i = 0; i < count; i++) 1.741 + { 1.742 + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; 1.743 + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; 1.744 + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; 1.745 + boolParams[3] = GL_FALSE; 1.746 + boolParams += 4; 1.747 + v += 3; 1.748 + } 1.749 + } 1.750 + else 1.751 + { 1.752 + return false; 1.753 + } 1.754 + 1.755 + return true; 1.756 +} 1.757 + 1.758 +bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) 1.759 +{ 1.760 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.761 + { 1.762 + return false; 1.763 + } 1.764 + 1.765 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.766 + targetUniform->dirty = true; 1.767 + 1.768 + int elementCount = targetUniform->elementCount(); 1.769 + 1.770 + if (elementCount == 1 && count > 1) 1.771 + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1.772 + 1.773 + count = std::min(elementCount - (int)mUniformIndex[location].element, count); 1.774 + 1.775 + if (targetUniform->type == GL_INT_VEC4) 1.776 + { 1.777 + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.778 + 1.779 + for (int i = 0; i < count; i++) 1.780 + { 1.781 + target[0] = v[0]; 1.782 + target[1] = v[1]; 1.783 + target[2] = v[2]; 1.784 + target[3] = v[3]; 1.785 + target += 4; 1.786 + v += 4; 1.787 + } 1.788 + } 1.789 + else if (targetUniform->type == GL_BOOL_VEC4) 1.790 + { 1.791 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.792 + 1.793 + for (int i = 0; i < count; i++) 1.794 + { 1.795 + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; 1.796 + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; 1.797 + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; 1.798 + boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE; 1.799 + boolParams += 4; 1.800 + v += 4; 1.801 + } 1.802 + } 1.803 + else 1.804 + { 1.805 + return false; 1.806 + } 1.807 + 1.808 + return true; 1.809 +} 1.810 + 1.811 +bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) 1.812 +{ 1.813 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.814 + { 1.815 + return false; 1.816 + } 1.817 + 1.818 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.819 + 1.820 + // sized queries -- ensure the provided buffer is large enough 1.821 + if (bufSize) 1.822 + { 1.823 + int requiredBytes = UniformExternalSize(targetUniform->type); 1.824 + if (*bufSize < requiredBytes) 1.825 + { 1.826 + return false; 1.827 + } 1.828 + } 1.829 + 1.830 + switch (targetUniform->type) 1.831 + { 1.832 + case GL_FLOAT_MAT2: 1.833 + transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); 1.834 + break; 1.835 + case GL_FLOAT_MAT3: 1.836 + transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); 1.837 + break; 1.838 + case GL_FLOAT_MAT4: 1.839 + transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); 1.840 + break; 1.841 + default: 1.842 + { 1.843 + unsigned int size = UniformComponentCount(targetUniform->type); 1.844 + 1.845 + switch (UniformComponentType(targetUniform->type)) 1.846 + { 1.847 + case GL_BOOL: 1.848 + { 1.849 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.850 + 1.851 + for (unsigned int i = 0; i < size; i++) 1.852 + { 1.853 + params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; 1.854 + } 1.855 + } 1.856 + break; 1.857 + case GL_FLOAT: 1.858 + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat), 1.859 + size * sizeof(GLfloat)); 1.860 + break; 1.861 + case GL_INT: 1.862 + { 1.863 + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.864 + 1.865 + for (unsigned int i = 0; i < size; i++) 1.866 + { 1.867 + params[i] = (float)intParams[i]; 1.868 + } 1.869 + } 1.870 + break; 1.871 + default: UNREACHABLE(); 1.872 + } 1.873 + } 1.874 + } 1.875 + 1.876 + return true; 1.877 +} 1.878 + 1.879 +bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) 1.880 +{ 1.881 + if (location < 0 || location >= (int)mUniformIndex.size()) 1.882 + { 1.883 + return false; 1.884 + } 1.885 + 1.886 + Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; 1.887 + 1.888 + // sized queries -- ensure the provided buffer is large enough 1.889 + if (bufSize) 1.890 + { 1.891 + int requiredBytes = UniformExternalSize(targetUniform->type); 1.892 + if (*bufSize < requiredBytes) 1.893 + { 1.894 + return false; 1.895 + } 1.896 + } 1.897 + 1.898 + switch (targetUniform->type) 1.899 + { 1.900 + case GL_FLOAT_MAT2: 1.901 + transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); 1.902 + break; 1.903 + case GL_FLOAT_MAT3: 1.904 + transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); 1.905 + break; 1.906 + case GL_FLOAT_MAT4: 1.907 + transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); 1.908 + break; 1.909 + default: 1.910 + { 1.911 + unsigned int size = VariableColumnCount(targetUniform->type); 1.912 + 1.913 + switch (UniformComponentType(targetUniform->type)) 1.914 + { 1.915 + case GL_BOOL: 1.916 + { 1.917 + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; 1.918 + 1.919 + for (unsigned int i = 0; i < size; i++) 1.920 + { 1.921 + params[i] = boolParams[i]; 1.922 + } 1.923 + } 1.924 + break; 1.925 + case GL_FLOAT: 1.926 + { 1.927 + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; 1.928 + 1.929 + for (unsigned int i = 0; i < size; i++) 1.930 + { 1.931 + params[i] = (GLint)floatParams[i]; 1.932 + } 1.933 + } 1.934 + break; 1.935 + case GL_INT: 1.936 + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint), 1.937 + size * sizeof(GLint)); 1.938 + break; 1.939 + default: UNREACHABLE(); 1.940 + } 1.941 + } 1.942 + } 1.943 + 1.944 + return true; 1.945 +} 1.946 + 1.947 +void ProgramBinary::dirtyAllUniforms() 1.948 +{ 1.949 + unsigned int numUniforms = mUniforms.size(); 1.950 + for (unsigned int index = 0; index < numUniforms; index++) 1.951 + { 1.952 + mUniforms[index]->dirty = true; 1.953 + } 1.954 +} 1.955 + 1.956 +// Applies all the uniforms set for this program object to the renderer 1.957 +void ProgramBinary::applyUniforms() 1.958 +{ 1.959 + // Retrieve sampler uniform values 1.960 + for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) 1.961 + { 1.962 + Uniform *targetUniform = *ub; 1.963 + 1.964 + if (targetUniform->dirty) 1.965 + { 1.966 + if (targetUniform->type == GL_SAMPLER_2D || 1.967 + targetUniform->type == GL_SAMPLER_CUBE) 1.968 + { 1.969 + int count = targetUniform->elementCount(); 1.970 + GLint (*v)[4] = (GLint(*)[4])targetUniform->data; 1.971 + 1.972 + if (targetUniform->psRegisterIndex >= 0) 1.973 + { 1.974 + unsigned int firstIndex = targetUniform->psRegisterIndex; 1.975 + 1.976 + for (int i = 0; i < count; i++) 1.977 + { 1.978 + unsigned int samplerIndex = firstIndex + i; 1.979 + 1.980 + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) 1.981 + { 1.982 + ASSERT(mSamplersPS[samplerIndex].active); 1.983 + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; 1.984 + } 1.985 + } 1.986 + } 1.987 + 1.988 + if (targetUniform->vsRegisterIndex >= 0) 1.989 + { 1.990 + unsigned int firstIndex = targetUniform->vsRegisterIndex; 1.991 + 1.992 + for (int i = 0; i < count; i++) 1.993 + { 1.994 + unsigned int samplerIndex = firstIndex + i; 1.995 + 1.996 + if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) 1.997 + { 1.998 + ASSERT(mSamplersVS[samplerIndex].active); 1.999 + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; 1.1000 + } 1.1001 + } 1.1002 + } 1.1003 + } 1.1004 + } 1.1005 + } 1.1006 + 1.1007 + mRenderer->applyUniforms(this, &mUniforms); 1.1008 +} 1.1009 + 1.1010 +// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 1.1011 +// Returns the number of used varying registers, or -1 if unsuccesful 1.1012 +int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader) 1.1013 +{ 1.1014 + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); 1.1015 + 1.1016 + fragmentShader->resetVaryingsRegisterAssignment(); 1.1017 + 1.1018 + for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) 1.1019 + { 1.1020 + int n = VariableRowCount(varying->type) * varying->size; 1.1021 + int m = VariableColumnCount(varying->type); 1.1022 + bool success = false; 1.1023 + 1.1024 + if (m == 2 || m == 3 || m == 4) 1.1025 + { 1.1026 + for (int r = 0; r <= maxVaryingVectors - n && !success; r++) 1.1027 + { 1.1028 + bool available = true; 1.1029 + 1.1030 + for (int y = 0; y < n && available; y++) 1.1031 + { 1.1032 + for (int x = 0; x < m && available; x++) 1.1033 + { 1.1034 + if (packing[r + y][x]) 1.1035 + { 1.1036 + available = false; 1.1037 + } 1.1038 + } 1.1039 + } 1.1040 + 1.1041 + if (available) 1.1042 + { 1.1043 + varying->reg = r; 1.1044 + varying->col = 0; 1.1045 + 1.1046 + for (int y = 0; y < n; y++) 1.1047 + { 1.1048 + for (int x = 0; x < m; x++) 1.1049 + { 1.1050 + packing[r + y][x] = &*varying; 1.1051 + } 1.1052 + } 1.1053 + 1.1054 + success = true; 1.1055 + } 1.1056 + } 1.1057 + 1.1058 + if (!success && m == 2) 1.1059 + { 1.1060 + for (int r = maxVaryingVectors - n; r >= 0 && !success; r--) 1.1061 + { 1.1062 + bool available = true; 1.1063 + 1.1064 + for (int y = 0; y < n && available; y++) 1.1065 + { 1.1066 + for (int x = 2; x < 4 && available; x++) 1.1067 + { 1.1068 + if (packing[r + y][x]) 1.1069 + { 1.1070 + available = false; 1.1071 + } 1.1072 + } 1.1073 + } 1.1074 + 1.1075 + if (available) 1.1076 + { 1.1077 + varying->reg = r; 1.1078 + varying->col = 2; 1.1079 + 1.1080 + for (int y = 0; y < n; y++) 1.1081 + { 1.1082 + for (int x = 2; x < 4; x++) 1.1083 + { 1.1084 + packing[r + y][x] = &*varying; 1.1085 + } 1.1086 + } 1.1087 + 1.1088 + success = true; 1.1089 + } 1.1090 + } 1.1091 + } 1.1092 + } 1.1093 + else if (m == 1) 1.1094 + { 1.1095 + int space[4] = {0}; 1.1096 + 1.1097 + for (int y = 0; y < maxVaryingVectors; y++) 1.1098 + { 1.1099 + for (int x = 0; x < 4; x++) 1.1100 + { 1.1101 + space[x] += packing[y][x] ? 0 : 1; 1.1102 + } 1.1103 + } 1.1104 + 1.1105 + int column = 0; 1.1106 + 1.1107 + for (int x = 0; x < 4; x++) 1.1108 + { 1.1109 + if (space[x] >= n && space[x] < space[column]) 1.1110 + { 1.1111 + column = x; 1.1112 + } 1.1113 + } 1.1114 + 1.1115 + if (space[column] >= n) 1.1116 + { 1.1117 + for (int r = 0; r < maxVaryingVectors; r++) 1.1118 + { 1.1119 + if (!packing[r][column]) 1.1120 + { 1.1121 + varying->reg = r; 1.1122 + 1.1123 + for (int y = r; y < r + n; y++) 1.1124 + { 1.1125 + packing[y][column] = &*varying; 1.1126 + } 1.1127 + 1.1128 + break; 1.1129 + } 1.1130 + } 1.1131 + 1.1132 + varying->col = column; 1.1133 + 1.1134 + success = true; 1.1135 + } 1.1136 + } 1.1137 + else UNREACHABLE(); 1.1138 + 1.1139 + if (!success) 1.1140 + { 1.1141 + infoLog.append("Could not pack varying %s", varying->name.c_str()); 1.1142 + 1.1143 + return -1; 1.1144 + } 1.1145 + } 1.1146 + 1.1147 + // Return the number of used registers 1.1148 + int registers = 0; 1.1149 + 1.1150 + for (int r = 0; r < maxVaryingVectors; r++) 1.1151 + { 1.1152 + if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) 1.1153 + { 1.1154 + registers++; 1.1155 + } 1.1156 + } 1.1157 + 1.1158 + return registers; 1.1159 +} 1.1160 + 1.1161 +bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], 1.1162 + std::string& pixelHLSL, std::string& vertexHLSL, 1.1163 + FragmentShader *fragmentShader, VertexShader *vertexShader) 1.1164 +{ 1.1165 + if (pixelHLSL.empty() || vertexHLSL.empty()) 1.1166 + { 1.1167 + return false; 1.1168 + } 1.1169 + 1.1170 + bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; 1.1171 + bool usesFragColor = fragmentShader->mUsesFragColor; 1.1172 + bool usesFragData = fragmentShader->mUsesFragData; 1.1173 + if (usesFragColor && usesFragData) 1.1174 + { 1.1175 + infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); 1.1176 + return false; 1.1177 + } 1.1178 + 1.1179 + // Write the HLSL input/output declarations 1.1180 + const int shaderModel = mRenderer->getMajorShaderModel(); 1.1181 + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); 1.1182 + 1.1183 + const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0); 1.1184 + 1.1185 + // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor 1.1186 + const bool broadcast = fragmentShader->mUsesFragColor; 1.1187 + const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1); 1.1188 + 1.1189 + if (registersNeeded > maxVaryingVectors) 1.1190 + { 1.1191 + infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); 1.1192 + 1.1193 + return false; 1.1194 + } 1.1195 + 1.1196 + vertexShader->resetVaryingsRegisterAssignment(); 1.1197 + 1.1198 + for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++) 1.1199 + { 1.1200 + bool matched = false; 1.1201 + 1.1202 + for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++) 1.1203 + { 1.1204 + if (output->name == input->name) 1.1205 + { 1.1206 + if (output->type != input->type || output->size != input->size) 1.1207 + { 1.1208 + infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str()); 1.1209 + 1.1210 + return false; 1.1211 + } 1.1212 + 1.1213 + output->reg = input->reg; 1.1214 + output->col = input->col; 1.1215 + 1.1216 + matched = true; 1.1217 + break; 1.1218 + } 1.1219 + } 1.1220 + 1.1221 + if (!matched) 1.1222 + { 1.1223 + infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); 1.1224 + 1.1225 + return false; 1.1226 + } 1.1227 + } 1.1228 + 1.1229 + mUsesPointSize = vertexShader->mUsesPointSize; 1.1230 + std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD"; 1.1231 + std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR"; 1.1232 + std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION"; 1.1233 + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; 1.1234 + 1.1235 + // special varyings that use reserved registers 1.1236 + int reservedRegisterIndex = registers; 1.1237 + std::string fragCoordSemantic; 1.1238 + std::string pointCoordSemantic; 1.1239 + 1.1240 + if (fragmentShader->mUsesFragCoord) 1.1241 + { 1.1242 + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); 1.1243 + } 1.1244 + 1.1245 + if (fragmentShader->mUsesPointCoord) 1.1246 + { 1.1247 + // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords. 1.1248 + // In DX11 we compute this in the GS. 1.1249 + if (shaderModel == 3) 1.1250 + { 1.1251 + pointCoordSemantic = "TEXCOORD0"; 1.1252 + } 1.1253 + else if (shaderModel >= 4) 1.1254 + { 1.1255 + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); 1.1256 + } 1.1257 + } 1.1258 + 1.1259 + vertexHLSL += "struct VS_INPUT\n" 1.1260 + "{\n"; 1.1261 + 1.1262 + int semanticIndex = 0; 1.1263 + for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) 1.1264 + { 1.1265 + switch (attribute->type) 1.1266 + { 1.1267 + case GL_FLOAT: vertexHLSL += " float "; break; 1.1268 + case GL_FLOAT_VEC2: vertexHLSL += " float2 "; break; 1.1269 + case GL_FLOAT_VEC3: vertexHLSL += " float3 "; break; 1.1270 + case GL_FLOAT_VEC4: vertexHLSL += " float4 "; break; 1.1271 + case GL_FLOAT_MAT2: vertexHLSL += " float2x2 "; break; 1.1272 + case GL_FLOAT_MAT3: vertexHLSL += " float3x3 "; break; 1.1273 + case GL_FLOAT_MAT4: vertexHLSL += " float4x4 "; break; 1.1274 + default: UNREACHABLE(); 1.1275 + } 1.1276 + 1.1277 + vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n"; 1.1278 + 1.1279 + semanticIndex += VariableRowCount(attribute->type); 1.1280 + } 1.1281 + 1.1282 + vertexHLSL += "};\n" 1.1283 + "\n" 1.1284 + "struct VS_OUTPUT\n" 1.1285 + "{\n"; 1.1286 + 1.1287 + if (shaderModel < 4) 1.1288 + { 1.1289 + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; 1.1290 + } 1.1291 + 1.1292 + for (int r = 0; r < registers; r++) 1.1293 + { 1.1294 + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); 1.1295 + 1.1296 + vertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; 1.1297 + } 1.1298 + 1.1299 + if (fragmentShader->mUsesFragCoord) 1.1300 + { 1.1301 + vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; 1.1302 + } 1.1303 + 1.1304 + if (vertexShader->mUsesPointSize && shaderModel >= 3) 1.1305 + { 1.1306 + vertexHLSL += " float gl_PointSize : PSIZE;\n"; 1.1307 + } 1.1308 + 1.1309 + if (shaderModel >= 4) 1.1310 + { 1.1311 + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; 1.1312 + } 1.1313 + 1.1314 + vertexHLSL += "};\n" 1.1315 + "\n" 1.1316 + "VS_OUTPUT main(VS_INPUT input)\n" 1.1317 + "{\n"; 1.1318 + 1.1319 + for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) 1.1320 + { 1.1321 + vertexHLSL += " " + decorateAttribute(attribute->name) + " = "; 1.1322 + 1.1323 + if (VariableRowCount(attribute->type) > 1) // Matrix 1.1324 + { 1.1325 + vertexHLSL += "transpose"; 1.1326 + } 1.1327 + 1.1328 + vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n"; 1.1329 + } 1.1330 + 1.1331 + if (shaderModel >= 4) 1.1332 + { 1.1333 + vertexHLSL += "\n" 1.1334 + " gl_main();\n" 1.1335 + "\n" 1.1336 + " VS_OUTPUT output;\n" 1.1337 + " output.gl_Position.x = gl_Position.x;\n" 1.1338 + " output.gl_Position.y = -gl_Position.y;\n" 1.1339 + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" 1.1340 + " output.gl_Position.w = gl_Position.w;\n"; 1.1341 + } 1.1342 + else 1.1343 + { 1.1344 + vertexHLSL += "\n" 1.1345 + " gl_main();\n" 1.1346 + "\n" 1.1347 + " VS_OUTPUT output;\n" 1.1348 + " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" 1.1349 + " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" 1.1350 + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" 1.1351 + " output.gl_Position.w = gl_Position.w;\n"; 1.1352 + } 1.1353 + 1.1354 + if (vertexShader->mUsesPointSize && shaderModel >= 3) 1.1355 + { 1.1356 + vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; 1.1357 + } 1.1358 + 1.1359 + if (fragmentShader->mUsesFragCoord) 1.1360 + { 1.1361 + vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; 1.1362 + } 1.1363 + 1.1364 + for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++) 1.1365 + { 1.1366 + if (varying->reg >= 0) 1.1367 + { 1.1368 + for (int i = 0; i < varying->size; i++) 1.1369 + { 1.1370 + int rows = VariableRowCount(varying->type); 1.1371 + 1.1372 + for (int j = 0; j < rows; j++) 1.1373 + { 1.1374 + int r = varying->reg + i * rows + j; 1.1375 + vertexHLSL += " output.v" + str(r); 1.1376 + 1.1377 + bool sharedRegister = false; // Register used by multiple varyings 1.1378 + 1.1379 + for (int x = 0; x < 4; x++) 1.1380 + { 1.1381 + if (packing[r][x] && packing[r][x] != packing[r][0]) 1.1382 + { 1.1383 + sharedRegister = true; 1.1384 + break; 1.1385 + } 1.1386 + } 1.1387 + 1.1388 + if(sharedRegister) 1.1389 + { 1.1390 + vertexHLSL += "."; 1.1391 + 1.1392 + for (int x = 0; x < 4; x++) 1.1393 + { 1.1394 + if (packing[r][x] == &*varying) 1.1395 + { 1.1396 + switch(x) 1.1397 + { 1.1398 + case 0: vertexHLSL += "x"; break; 1.1399 + case 1: vertexHLSL += "y"; break; 1.1400 + case 2: vertexHLSL += "z"; break; 1.1401 + case 3: vertexHLSL += "w"; break; 1.1402 + } 1.1403 + } 1.1404 + } 1.1405 + } 1.1406 + 1.1407 + vertexHLSL += " = " + varying->name; 1.1408 + 1.1409 + if (varying->array) 1.1410 + { 1.1411 + vertexHLSL += "[" + str(i) + "]"; 1.1412 + } 1.1413 + 1.1414 + if (rows > 1) 1.1415 + { 1.1416 + vertexHLSL += "[" + str(j) + "]"; 1.1417 + } 1.1418 + 1.1419 + vertexHLSL += ";\n"; 1.1420 + } 1.1421 + } 1.1422 + } 1.1423 + } 1.1424 + 1.1425 + vertexHLSL += "\n" 1.1426 + " return output;\n" 1.1427 + "}\n"; 1.1428 + 1.1429 + pixelHLSL += "struct PS_INPUT\n" 1.1430 + "{\n"; 1.1431 + 1.1432 + for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) 1.1433 + { 1.1434 + if (varying->reg >= 0) 1.1435 + { 1.1436 + for (int i = 0; i < varying->size; i++) 1.1437 + { 1.1438 + int rows = VariableRowCount(varying->type); 1.1439 + for (int j = 0; j < rows; j++) 1.1440 + { 1.1441 + std::string n = str(varying->reg + i * rows + j); 1.1442 + pixelHLSL += " float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n"; 1.1443 + } 1.1444 + } 1.1445 + } 1.1446 + else UNREACHABLE(); 1.1447 + } 1.1448 + 1.1449 + if (fragmentShader->mUsesFragCoord) 1.1450 + { 1.1451 + pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; 1.1452 + } 1.1453 + 1.1454 + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) 1.1455 + { 1.1456 + pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; 1.1457 + } 1.1458 + 1.1459 + // Must consume the PSIZE element if the geometry shader is not active 1.1460 + // We won't know if we use a GS until we draw 1.1461 + if (vertexShader->mUsesPointSize && shaderModel >= 4) 1.1462 + { 1.1463 + pixelHLSL += " float gl_PointSize : PSIZE;\n"; 1.1464 + } 1.1465 + 1.1466 + if (fragmentShader->mUsesFragCoord) 1.1467 + { 1.1468 + if (shaderModel >= 4) 1.1469 + { 1.1470 + pixelHLSL += " float4 dx_VPos : SV_Position;\n"; 1.1471 + } 1.1472 + else if (shaderModel >= 3) 1.1473 + { 1.1474 + pixelHLSL += " float2 dx_VPos : VPOS;\n"; 1.1475 + } 1.1476 + } 1.1477 + 1.1478 + pixelHLSL += "};\n" 1.1479 + "\n" 1.1480 + "struct PS_OUTPUT\n" 1.1481 + "{\n"; 1.1482 + 1.1483 + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) 1.1484 + { 1.1485 + pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n"; 1.1486 + } 1.1487 + 1.1488 + if (fragmentShader->mUsesFragDepth) 1.1489 + { 1.1490 + pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n"; 1.1491 + } 1.1492 + 1.1493 + pixelHLSL += "};\n" 1.1494 + "\n"; 1.1495 + 1.1496 + if (fragmentShader->mUsesFrontFacing) 1.1497 + { 1.1498 + if (shaderModel >= 4) 1.1499 + { 1.1500 + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" 1.1501 + "{\n"; 1.1502 + } 1.1503 + else 1.1504 + { 1.1505 + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" 1.1506 + "{\n"; 1.1507 + } 1.1508 + } 1.1509 + else 1.1510 + { 1.1511 + pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n" 1.1512 + "{\n"; 1.1513 + } 1.1514 + 1.1515 + if (fragmentShader->mUsesFragCoord) 1.1516 + { 1.1517 + pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; 1.1518 + 1.1519 + if (shaderModel >= 4) 1.1520 + { 1.1521 + pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" 1.1522 + " gl_FragCoord.y = input.dx_VPos.y;\n"; 1.1523 + } 1.1524 + else if (shaderModel >= 3) 1.1525 + { 1.1526 + pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n" 1.1527 + " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; 1.1528 + } 1.1529 + else 1.1530 + { 1.1531 + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport() 1.1532 + pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n" 1.1533 + " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n"; 1.1534 + } 1.1535 + 1.1536 + pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" 1.1537 + " gl_FragCoord.w = rhw;\n"; 1.1538 + } 1.1539 + 1.1540 + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) 1.1541 + { 1.1542 + pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; 1.1543 + pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; 1.1544 + } 1.1545 + 1.1546 + if (fragmentShader->mUsesFrontFacing) 1.1547 + { 1.1548 + if (shaderModel <= 3) 1.1549 + { 1.1550 + pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; 1.1551 + } 1.1552 + else 1.1553 + { 1.1554 + pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; 1.1555 + } 1.1556 + } 1.1557 + 1.1558 + for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) 1.1559 + { 1.1560 + if (varying->reg >= 0) 1.1561 + { 1.1562 + for (int i = 0; i < varying->size; i++) 1.1563 + { 1.1564 + int rows = VariableRowCount(varying->type); 1.1565 + for (int j = 0; j < rows; j++) 1.1566 + { 1.1567 + std::string n = str(varying->reg + i * rows + j); 1.1568 + pixelHLSL += " " + varying->name; 1.1569 + 1.1570 + if (varying->array) 1.1571 + { 1.1572 + pixelHLSL += "[" + str(i) + "]"; 1.1573 + } 1.1574 + 1.1575 + if (rows > 1) 1.1576 + { 1.1577 + pixelHLSL += "[" + str(j) + "]"; 1.1578 + } 1.1579 + 1.1580 + switch (VariableColumnCount(varying->type)) 1.1581 + { 1.1582 + case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break; 1.1583 + case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break; 1.1584 + case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break; 1.1585 + case 4: pixelHLSL += " = input.v" + n + ";\n"; break; 1.1586 + default: UNREACHABLE(); 1.1587 + } 1.1588 + } 1.1589 + } 1.1590 + } 1.1591 + else UNREACHABLE(); 1.1592 + } 1.1593 + 1.1594 + pixelHLSL += "\n" 1.1595 + " gl_main();\n" 1.1596 + "\n" 1.1597 + " PS_OUTPUT output;\n"; 1.1598 + 1.1599 + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) 1.1600 + { 1.1601 + unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex; 1.1602 + 1.1603 + pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n"; 1.1604 + } 1.1605 + 1.1606 + if (fragmentShader->mUsesFragDepth) 1.1607 + { 1.1608 + pixelHLSL += " output.gl_Depth = gl_Depth;\n"; 1.1609 + } 1.1610 + 1.1611 + pixelHLSL += "\n" 1.1612 + " return output;\n" 1.1613 + "}\n"; 1.1614 + 1.1615 + return true; 1.1616 +} 1.1617 + 1.1618 +bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) 1.1619 +{ 1.1620 + BinaryInputStream stream(binary, length); 1.1621 + 1.1622 + int format = 0; 1.1623 + stream.read(&format); 1.1624 + if (format != GL_PROGRAM_BINARY_ANGLE) 1.1625 + { 1.1626 + infoLog.append("Invalid program binary format."); 1.1627 + return false; 1.1628 + } 1.1629 + 1.1630 + int version = 0; 1.1631 + stream.read(&version); 1.1632 + if (version != VERSION_DWORD) 1.1633 + { 1.1634 + infoLog.append("Invalid program binary version."); 1.1635 + return false; 1.1636 + } 1.1637 + 1.1638 + int compileFlags = 0; 1.1639 + stream.read(&compileFlags); 1.1640 + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) 1.1641 + { 1.1642 + infoLog.append("Mismatched compilation flags."); 1.1643 + return false; 1.1644 + } 1.1645 + 1.1646 + for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) 1.1647 + { 1.1648 + stream.read(&mLinkedAttribute[i].type); 1.1649 + std::string name; 1.1650 + stream.read(&name); 1.1651 + mLinkedAttribute[i].name = name; 1.1652 + stream.read(&mSemanticIndex[i]); 1.1653 + } 1.1654 + 1.1655 + for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) 1.1656 + { 1.1657 + stream.read(&mSamplersPS[i].active); 1.1658 + stream.read(&mSamplersPS[i].logicalTextureUnit); 1.1659 + 1.1660 + int textureType; 1.1661 + stream.read(&textureType); 1.1662 + mSamplersPS[i].textureType = (TextureType) textureType; 1.1663 + } 1.1664 + 1.1665 + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) 1.1666 + { 1.1667 + stream.read(&mSamplersVS[i].active); 1.1668 + stream.read(&mSamplersVS[i].logicalTextureUnit); 1.1669 + 1.1670 + int textureType; 1.1671 + stream.read(&textureType); 1.1672 + mSamplersVS[i].textureType = (TextureType) textureType; 1.1673 + } 1.1674 + 1.1675 + stream.read(&mUsedVertexSamplerRange); 1.1676 + stream.read(&mUsedPixelSamplerRange); 1.1677 + stream.read(&mUsesPointSize); 1.1678 + 1.1679 + size_t size; 1.1680 + stream.read(&size); 1.1681 + if (stream.error()) 1.1682 + { 1.1683 + infoLog.append("Invalid program binary."); 1.1684 + return false; 1.1685 + } 1.1686 + 1.1687 + mUniforms.resize(size); 1.1688 + for (unsigned int i = 0; i < size; ++i) 1.1689 + { 1.1690 + GLenum type; 1.1691 + GLenum precision; 1.1692 + std::string name; 1.1693 + unsigned int arraySize; 1.1694 + 1.1695 + stream.read(&type); 1.1696 + stream.read(&precision); 1.1697 + stream.read(&name); 1.1698 + stream.read(&arraySize); 1.1699 + 1.1700 + mUniforms[i] = new Uniform(type, precision, name, arraySize); 1.1701 + 1.1702 + stream.read(&mUniforms[i]->psRegisterIndex); 1.1703 + stream.read(&mUniforms[i]->vsRegisterIndex); 1.1704 + stream.read(&mUniforms[i]->registerCount); 1.1705 + } 1.1706 + 1.1707 + stream.read(&size); 1.1708 + if (stream.error()) 1.1709 + { 1.1710 + infoLog.append("Invalid program binary."); 1.1711 + return false; 1.1712 + } 1.1713 + 1.1714 + mUniformIndex.resize(size); 1.1715 + for (unsigned int i = 0; i < size; ++i) 1.1716 + { 1.1717 + stream.read(&mUniformIndex[i].name); 1.1718 + stream.read(&mUniformIndex[i].element); 1.1719 + stream.read(&mUniformIndex[i].index); 1.1720 + } 1.1721 + 1.1722 + unsigned int pixelShaderSize; 1.1723 + stream.read(&pixelShaderSize); 1.1724 + 1.1725 + unsigned int vertexShaderSize; 1.1726 + stream.read(&vertexShaderSize); 1.1727 + 1.1728 + unsigned int geometryShaderSize; 1.1729 + stream.read(&geometryShaderSize); 1.1730 + 1.1731 + const char *ptr = (const char*) binary + stream.offset(); 1.1732 + 1.1733 + const GUID *binaryIdentifier = (const GUID *) ptr; 1.1734 + ptr += sizeof(GUID); 1.1735 + 1.1736 + GUID identifier = mRenderer->getAdapterIdentifier(); 1.1737 + if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) 1.1738 + { 1.1739 + infoLog.append("Invalid program binary."); 1.1740 + return false; 1.1741 + } 1.1742 + 1.1743 + const char *pixelShaderFunction = ptr; 1.1744 + ptr += pixelShaderSize; 1.1745 + 1.1746 + const char *vertexShaderFunction = ptr; 1.1747 + ptr += vertexShaderSize; 1.1748 + 1.1749 + const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL; 1.1750 + ptr += geometryShaderSize; 1.1751 + 1.1752 + mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction), 1.1753 + pixelShaderSize, rx::SHADER_PIXEL); 1.1754 + if (!mPixelExecutable) 1.1755 + { 1.1756 + infoLog.append("Could not create pixel shader."); 1.1757 + return false; 1.1758 + } 1.1759 + 1.1760 + mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction), 1.1761 + vertexShaderSize, rx::SHADER_VERTEX); 1.1762 + if (!mVertexExecutable) 1.1763 + { 1.1764 + infoLog.append("Could not create vertex shader."); 1.1765 + delete mPixelExecutable; 1.1766 + mPixelExecutable = NULL; 1.1767 + return false; 1.1768 + } 1.1769 + 1.1770 + if (geometryShaderFunction != NULL && geometryShaderSize > 0) 1.1771 + { 1.1772 + mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction), 1.1773 + geometryShaderSize, rx::SHADER_GEOMETRY); 1.1774 + if (!mGeometryExecutable) 1.1775 + { 1.1776 + infoLog.append("Could not create geometry shader."); 1.1777 + delete mPixelExecutable; 1.1778 + mPixelExecutable = NULL; 1.1779 + delete mVertexExecutable; 1.1780 + mVertexExecutable = NULL; 1.1781 + return false; 1.1782 + } 1.1783 + } 1.1784 + else 1.1785 + { 1.1786 + mGeometryExecutable = NULL; 1.1787 + } 1.1788 + 1.1789 + return true; 1.1790 +} 1.1791 + 1.1792 +bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) 1.1793 +{ 1.1794 + BinaryOutputStream stream; 1.1795 + 1.1796 + stream.write(GL_PROGRAM_BINARY_ANGLE); 1.1797 + stream.write(VERSION_DWORD); 1.1798 + stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); 1.1799 + 1.1800 + for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) 1.1801 + { 1.1802 + stream.write(mLinkedAttribute[i].type); 1.1803 + stream.write(mLinkedAttribute[i].name); 1.1804 + stream.write(mSemanticIndex[i]); 1.1805 + } 1.1806 + 1.1807 + for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) 1.1808 + { 1.1809 + stream.write(mSamplersPS[i].active); 1.1810 + stream.write(mSamplersPS[i].logicalTextureUnit); 1.1811 + stream.write((int) mSamplersPS[i].textureType); 1.1812 + } 1.1813 + 1.1814 + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) 1.1815 + { 1.1816 + stream.write(mSamplersVS[i].active); 1.1817 + stream.write(mSamplersVS[i].logicalTextureUnit); 1.1818 + stream.write((int) mSamplersVS[i].textureType); 1.1819 + } 1.1820 + 1.1821 + stream.write(mUsedVertexSamplerRange); 1.1822 + stream.write(mUsedPixelSamplerRange); 1.1823 + stream.write(mUsesPointSize); 1.1824 + 1.1825 + stream.write(mUniforms.size()); 1.1826 + for (unsigned int i = 0; i < mUniforms.size(); ++i) 1.1827 + { 1.1828 + stream.write(mUniforms[i]->type); 1.1829 + stream.write(mUniforms[i]->precision); 1.1830 + stream.write(mUniforms[i]->name); 1.1831 + stream.write(mUniforms[i]->arraySize); 1.1832 + 1.1833 + stream.write(mUniforms[i]->psRegisterIndex); 1.1834 + stream.write(mUniforms[i]->vsRegisterIndex); 1.1835 + stream.write(mUniforms[i]->registerCount); 1.1836 + } 1.1837 + 1.1838 + stream.write(mUniformIndex.size()); 1.1839 + for (unsigned int i = 0; i < mUniformIndex.size(); ++i) 1.1840 + { 1.1841 + stream.write(mUniformIndex[i].name); 1.1842 + stream.write(mUniformIndex[i].element); 1.1843 + stream.write(mUniformIndex[i].index); 1.1844 + } 1.1845 + 1.1846 + UINT pixelShaderSize = mPixelExecutable->getLength(); 1.1847 + stream.write(pixelShaderSize); 1.1848 + 1.1849 + UINT vertexShaderSize = mVertexExecutable->getLength(); 1.1850 + stream.write(vertexShaderSize); 1.1851 + 1.1852 + UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; 1.1853 + stream.write(geometryShaderSize); 1.1854 + 1.1855 + GUID identifier = mRenderer->getAdapterIdentifier(); 1.1856 + 1.1857 + GLsizei streamLength = stream.length(); 1.1858 + const void *streamData = stream.data(); 1.1859 + 1.1860 + GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize; 1.1861 + if (totalLength > bufSize) 1.1862 + { 1.1863 + if (length) 1.1864 + { 1.1865 + *length = 0; 1.1866 + } 1.1867 + 1.1868 + return false; 1.1869 + } 1.1870 + 1.1871 + if (binary) 1.1872 + { 1.1873 + char *ptr = (char*) binary; 1.1874 + 1.1875 + memcpy(ptr, streamData, streamLength); 1.1876 + ptr += streamLength; 1.1877 + 1.1878 + memcpy(ptr, &identifier, sizeof(GUID)); 1.1879 + ptr += sizeof(GUID); 1.1880 + 1.1881 + memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); 1.1882 + ptr += pixelShaderSize; 1.1883 + 1.1884 + memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize); 1.1885 + ptr += vertexShaderSize; 1.1886 + 1.1887 + if (mGeometryExecutable != NULL && geometryShaderSize > 0) 1.1888 + { 1.1889 + memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize); 1.1890 + ptr += geometryShaderSize; 1.1891 + } 1.1892 + 1.1893 + ASSERT(ptr - totalLength == binary); 1.1894 + } 1.1895 + 1.1896 + if (length) 1.1897 + { 1.1898 + *length = totalLength; 1.1899 + } 1.1900 + 1.1901 + return true; 1.1902 +} 1.1903 + 1.1904 +GLint ProgramBinary::getLength() 1.1905 +{ 1.1906 + GLint length; 1.1907 + if (save(NULL, INT_MAX, &length)) 1.1908 + { 1.1909 + return length; 1.1910 + } 1.1911 + else 1.1912 + { 1.1913 + return 0; 1.1914 + } 1.1915 +} 1.1916 + 1.1917 +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) 1.1918 +{ 1.1919 + if (!fragmentShader || !fragmentShader->isCompiled()) 1.1920 + { 1.1921 + return false; 1.1922 + } 1.1923 + 1.1924 + if (!vertexShader || !vertexShader->isCompiled()) 1.1925 + { 1.1926 + return false; 1.1927 + } 1.1928 + 1.1929 + std::string pixelHLSL = fragmentShader->getHLSL(); 1.1930 + std::string vertexHLSL = vertexShader->getHLSL(); 1.1931 + 1.1932 + // Map the varyings to the register file 1.1933 + const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL}; 1.1934 + int registers = packVaryings(infoLog, packing, fragmentShader); 1.1935 + 1.1936 + if (registers < 0) 1.1937 + { 1.1938 + return false; 1.1939 + } 1.1940 + 1.1941 + if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) 1.1942 + { 1.1943 + return false; 1.1944 + } 1.1945 + 1.1946 + bool success = true; 1.1947 + 1.1948 + if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) 1.1949 + { 1.1950 + success = false; 1.1951 + } 1.1952 + 1.1953 + if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) 1.1954 + { 1.1955 + success = false; 1.1956 + } 1.1957 + 1.1958 + // special case for gl_DepthRange, the only built-in uniform (also a struct) 1.1959 + if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange) 1.1960 + { 1.1961 + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0)); 1.1962 + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0)); 1.1963 + mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0)); 1.1964 + } 1.1965 + 1.1966 + if (success) 1.1967 + { 1.1968 + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); 1.1969 + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); 1.1970 + 1.1971 + if (usesGeometryShader()) 1.1972 + { 1.1973 + std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); 1.1974 + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); 1.1975 + } 1.1976 + 1.1977 + if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) 1.1978 + { 1.1979 + infoLog.append("Failed to create D3D shaders."); 1.1980 + success = false; 1.1981 + 1.1982 + delete mVertexExecutable; 1.1983 + mVertexExecutable = NULL; 1.1984 + delete mPixelExecutable; 1.1985 + mPixelExecutable = NULL; 1.1986 + delete mGeometryExecutable; 1.1987 + mGeometryExecutable = NULL; 1.1988 + } 1.1989 + } 1.1990 + 1.1991 + return success; 1.1992 +} 1.1993 + 1.1994 +// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices 1.1995 +bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) 1.1996 +{ 1.1997 + unsigned int usedLocations = 0; 1.1998 + 1.1999 + // Link attributes that have a binding location 1.2000 + for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) 1.2001 + { 1.2002 + int location = attributeBindings.getAttributeBinding(attribute->name); 1.2003 + 1.2004 + if (location != -1) // Set by glBindAttribLocation 1.2005 + { 1.2006 + if (!mLinkedAttribute[location].name.empty()) 1.2007 + { 1.2008 + // Multiple active attributes bound to the same location; not an error 1.2009 + } 1.2010 + 1.2011 + mLinkedAttribute[location] = *attribute; 1.2012 + 1.2013 + int rows = VariableRowCount(attribute->type); 1.2014 + 1.2015 + if (rows + location > MAX_VERTEX_ATTRIBS) 1.2016 + { 1.2017 + infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location); 1.2018 + 1.2019 + return false; 1.2020 + } 1.2021 + 1.2022 + for (int i = 0; i < rows; i++) 1.2023 + { 1.2024 + usedLocations |= 1 << (location + i); 1.2025 + } 1.2026 + } 1.2027 + } 1.2028 + 1.2029 + // Link attributes that don't have a binding location 1.2030 + for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) 1.2031 + { 1.2032 + int location = attributeBindings.getAttributeBinding(attribute->name); 1.2033 + 1.2034 + if (location == -1) // Not set by glBindAttribLocation 1.2035 + { 1.2036 + int rows = VariableRowCount(attribute->type); 1.2037 + int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); 1.2038 + 1.2039 + if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) 1.2040 + { 1.2041 + infoLog.append("Too many active attributes (%s)", attribute->name.c_str()); 1.2042 + 1.2043 + return false; // Fail to link 1.2044 + } 1.2045 + 1.2046 + mLinkedAttribute[availableIndex] = *attribute; 1.2047 + } 1.2048 + } 1.2049 + 1.2050 + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) 1.2051 + { 1.2052 + int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); 1.2053 + int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1); 1.2054 + 1.2055 + for (int r = 0; r < rows; r++) 1.2056 + { 1.2057 + mSemanticIndex[attributeIndex++] = index++; 1.2058 + } 1.2059 + } 1.2060 + 1.2061 + return true; 1.2062 +} 1.2063 + 1.2064 +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms) 1.2065 +{ 1.2066 + for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++) 1.2067 + { 1.2068 + if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog)) 1.2069 + { 1.2070 + return false; 1.2071 + } 1.2072 + } 1.2073 + 1.2074 + for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++) 1.2075 + { 1.2076 + if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog)) 1.2077 + { 1.2078 + return false; 1.2079 + } 1.2080 + } 1.2081 + 1.2082 + return true; 1.2083 +} 1.2084 + 1.2085 +bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog) 1.2086 +{ 1.2087 + if (constant.type == GL_SAMPLER_2D || 1.2088 + constant.type == GL_SAMPLER_CUBE) 1.2089 + { 1.2090 + unsigned int samplerIndex = constant.registerIndex; 1.2091 + 1.2092 + do 1.2093 + { 1.2094 + if (shader == GL_VERTEX_SHADER) 1.2095 + { 1.2096 + if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) 1.2097 + { 1.2098 + mSamplersVS[samplerIndex].active = true; 1.2099 + mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; 1.2100 + mSamplersVS[samplerIndex].logicalTextureUnit = 0; 1.2101 + mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); 1.2102 + } 1.2103 + else 1.2104 + { 1.2105 + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits()); 1.2106 + return false; 1.2107 + } 1.2108 + } 1.2109 + else if (shader == GL_FRAGMENT_SHADER) 1.2110 + { 1.2111 + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) 1.2112 + { 1.2113 + mSamplersPS[samplerIndex].active = true; 1.2114 + mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; 1.2115 + mSamplersPS[samplerIndex].logicalTextureUnit = 0; 1.2116 + mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); 1.2117 + } 1.2118 + else 1.2119 + { 1.2120 + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); 1.2121 + return false; 1.2122 + } 1.2123 + } 1.2124 + else UNREACHABLE(); 1.2125 + 1.2126 + samplerIndex++; 1.2127 + } 1.2128 + while (samplerIndex < constant.registerIndex + constant.arraySize); 1.2129 + } 1.2130 + 1.2131 + Uniform *uniform = NULL; 1.2132 + GLint location = getUniformLocation(constant.name); 1.2133 + 1.2134 + if (location >= 0) // Previously defined, type and precision must match 1.2135 + { 1.2136 + uniform = mUniforms[mUniformIndex[location].index]; 1.2137 + 1.2138 + if (uniform->type != constant.type) 1.2139 + { 1.2140 + infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1.2141 + return false; 1.2142 + } 1.2143 + 1.2144 + if (uniform->precision != constant.precision) 1.2145 + { 1.2146 + infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1.2147 + return false; 1.2148 + } 1.2149 + } 1.2150 + else 1.2151 + { 1.2152 + uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize); 1.2153 + } 1.2154 + 1.2155 + if (!uniform) 1.2156 + { 1.2157 + return false; 1.2158 + } 1.2159 + 1.2160 + if (shader == GL_FRAGMENT_SHADER) 1.2161 + { 1.2162 + uniform->psRegisterIndex = constant.registerIndex; 1.2163 + } 1.2164 + else if (shader == GL_VERTEX_SHADER) 1.2165 + { 1.2166 + uniform->vsRegisterIndex = constant.registerIndex; 1.2167 + } 1.2168 + else UNREACHABLE(); 1.2169 + 1.2170 + if (location >= 0) 1.2171 + { 1.2172 + return uniform->type == constant.type; 1.2173 + } 1.2174 + 1.2175 + mUniforms.push_back(uniform); 1.2176 + unsigned int uniformIndex = mUniforms.size() - 1; 1.2177 + 1.2178 + for (unsigned int i = 0; i < uniform->elementCount(); i++) 1.2179 + { 1.2180 + mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex)); 1.2181 + } 1.2182 + 1.2183 + if (shader == GL_VERTEX_SHADER) 1.2184 + { 1.2185 + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors()) 1.2186 + { 1.2187 + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); 1.2188 + return false; 1.2189 + } 1.2190 + } 1.2191 + else if (shader == GL_FRAGMENT_SHADER) 1.2192 + { 1.2193 + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) 1.2194 + { 1.2195 + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors()); 1.2196 + return false; 1.2197 + } 1.2198 + } 1.2199 + else UNREACHABLE(); 1.2200 + 1.2201 + return true; 1.2202 +} 1.2203 + 1.2204 +std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const 1.2205 +{ 1.2206 + // for now we only handle point sprite emulation 1.2207 + ASSERT(usesPointSpriteEmulation()); 1.2208 + return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader); 1.2209 +} 1.2210 + 1.2211 +std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const 1.2212 +{ 1.2213 + ASSERT(registers >= 0); 1.2214 + ASSERT(vertexShader->mUsesPointSize); 1.2215 + ASSERT(mRenderer->getMajorShaderModel() >= 4); 1.2216 + 1.2217 + std::string geomHLSL; 1.2218 + 1.2219 + std::string varyingSemantic = "TEXCOORD"; 1.2220 + 1.2221 + std::string fragCoordSemantic; 1.2222 + std::string pointCoordSemantic; 1.2223 + 1.2224 + int reservedRegisterIndex = registers; 1.2225 + 1.2226 + if (fragmentShader->mUsesFragCoord) 1.2227 + { 1.2228 + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); 1.2229 + } 1.2230 + 1.2231 + if (fragmentShader->mUsesPointCoord) 1.2232 + { 1.2233 + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); 1.2234 + } 1.2235 + 1.2236 + geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" 1.2237 + "\n" 1.2238 + "struct GS_INPUT\n" 1.2239 + "{\n"; 1.2240 + 1.2241 + for (int r = 0; r < registers; r++) 1.2242 + { 1.2243 + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); 1.2244 + 1.2245 + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; 1.2246 + } 1.2247 + 1.2248 + if (fragmentShader->mUsesFragCoord) 1.2249 + { 1.2250 + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; 1.2251 + } 1.2252 + 1.2253 + geomHLSL += " float gl_PointSize : PSIZE;\n" 1.2254 + " float4 gl_Position : SV_Position;\n" 1.2255 + "};\n" 1.2256 + "\n" 1.2257 + "struct GS_OUTPUT\n" 1.2258 + "{\n"; 1.2259 + 1.2260 + for (int r = 0; r < registers; r++) 1.2261 + { 1.2262 + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); 1.2263 + 1.2264 + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; 1.2265 + } 1.2266 + 1.2267 + if (fragmentShader->mUsesFragCoord) 1.2268 + { 1.2269 + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; 1.2270 + } 1.2271 + 1.2272 + if (fragmentShader->mUsesPointCoord) 1.2273 + { 1.2274 + geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; 1.2275 + } 1.2276 + 1.2277 + geomHLSL += " float gl_PointSize : PSIZE;\n" 1.2278 + " float4 gl_Position : SV_Position;\n" 1.2279 + "};\n" 1.2280 + "\n" 1.2281 + "static float2 pointSpriteCorners[] = \n" 1.2282 + "{\n" 1.2283 + " float2( 0.5f, -0.5f),\n" 1.2284 + " float2( 0.5f, 0.5f),\n" 1.2285 + " float2(-0.5f, -0.5f),\n" 1.2286 + " float2(-0.5f, 0.5f)\n" 1.2287 + "};\n" 1.2288 + "\n" 1.2289 + "static float2 pointSpriteTexcoords[] = \n" 1.2290 + "{\n" 1.2291 + " float2(1.0f, 1.0f),\n" 1.2292 + " float2(1.0f, 0.0f),\n" 1.2293 + " float2(0.0f, 1.0f),\n" 1.2294 + " float2(0.0f, 0.0f)\n" 1.2295 + "};\n" 1.2296 + "\n" 1.2297 + "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n" 1.2298 + "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n" 1.2299 + "\n" 1.2300 + "[maxvertexcount(4)]\n" 1.2301 + "void main(point GS_INPUT input[1], inout TriangleStream<GS_OUTPUT> outStream)\n" 1.2302 + "{\n" 1.2303 + " GS_OUTPUT output = (GS_OUTPUT)0;\n" 1.2304 + " output.gl_PointSize = input[0].gl_PointSize;\n"; 1.2305 + 1.2306 + for (int r = 0; r < registers; r++) 1.2307 + { 1.2308 + geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n"; 1.2309 + } 1.2310 + 1.2311 + if (fragmentShader->mUsesFragCoord) 1.2312 + { 1.2313 + geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; 1.2314 + } 1.2315 + 1.2316 + geomHLSL += " \n" 1.2317 + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" 1.2318 + " float4 gl_Position = input[0].gl_Position;\n" 1.2319 + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n"; 1.2320 + 1.2321 + for (int corner = 0; corner < 4; corner++) 1.2322 + { 1.2323 + geomHLSL += " \n" 1.2324 + " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; 1.2325 + 1.2326 + if (fragmentShader->mUsesPointCoord) 1.2327 + { 1.2328 + geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n"; 1.2329 + } 1.2330 + 1.2331 + geomHLSL += " outStream.Append(output);\n"; 1.2332 + } 1.2333 + 1.2334 + geomHLSL += " \n" 1.2335 + " outStream.RestartStrip();\n" 1.2336 + "}\n"; 1.2337 + 1.2338 + return geomHLSL; 1.2339 +} 1.2340 + 1.2341 +// This method needs to match OutputHLSL::decorate 1.2342 +std::string ProgramBinary::decorateAttribute(const std::string &name) 1.2343 +{ 1.2344 + if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0) 1.2345 + { 1.2346 + return "_" + name; 1.2347 + } 1.2348 + 1.2349 + return name; 1.2350 +} 1.2351 + 1.2352 +bool ProgramBinary::isValidated() const 1.2353 +{ 1.2354 + return mValidated; 1.2355 +} 1.2356 + 1.2357 +void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 1.2358 +{ 1.2359 + // Skip over inactive attributes 1.2360 + unsigned int activeAttribute = 0; 1.2361 + unsigned int attribute; 1.2362 + for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) 1.2363 + { 1.2364 + if (mLinkedAttribute[attribute].name.empty()) 1.2365 + { 1.2366 + continue; 1.2367 + } 1.2368 + 1.2369 + if (activeAttribute == index) 1.2370 + { 1.2371 + break; 1.2372 + } 1.2373 + 1.2374 + activeAttribute++; 1.2375 + } 1.2376 + 1.2377 + if (bufsize > 0) 1.2378 + { 1.2379 + const char *string = mLinkedAttribute[attribute].name.c_str(); 1.2380 + 1.2381 + strncpy(name, string, bufsize); 1.2382 + name[bufsize - 1] = '\0'; 1.2383 + 1.2384 + if (length) 1.2385 + { 1.2386 + *length = strlen(name); 1.2387 + } 1.2388 + } 1.2389 + 1.2390 + *size = 1; // Always a single 'type' instance 1.2391 + 1.2392 + *type = mLinkedAttribute[attribute].type; 1.2393 +} 1.2394 + 1.2395 +GLint ProgramBinary::getActiveAttributeCount() const 1.2396 +{ 1.2397 + int count = 0; 1.2398 + 1.2399 + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) 1.2400 + { 1.2401 + if (!mLinkedAttribute[attributeIndex].name.empty()) 1.2402 + { 1.2403 + count++; 1.2404 + } 1.2405 + } 1.2406 + 1.2407 + return count; 1.2408 +} 1.2409 + 1.2410 +GLint ProgramBinary::getActiveAttributeMaxLength() const 1.2411 +{ 1.2412 + int maxLength = 0; 1.2413 + 1.2414 + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) 1.2415 + { 1.2416 + if (!mLinkedAttribute[attributeIndex].name.empty()) 1.2417 + { 1.2418 + maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); 1.2419 + } 1.2420 + } 1.2421 + 1.2422 + return maxLength; 1.2423 +} 1.2424 + 1.2425 +void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 1.2426 +{ 1.2427 + ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount() 1.2428 + 1.2429 + if (bufsize > 0) 1.2430 + { 1.2431 + std::string string = mUniforms[index]->name; 1.2432 + 1.2433 + if (mUniforms[index]->isArray()) 1.2434 + { 1.2435 + string += "[0]"; 1.2436 + } 1.2437 + 1.2438 + strncpy(name, string.c_str(), bufsize); 1.2439 + name[bufsize - 1] = '\0'; 1.2440 + 1.2441 + if (length) 1.2442 + { 1.2443 + *length = strlen(name); 1.2444 + } 1.2445 + } 1.2446 + 1.2447 + *size = mUniforms[index]->elementCount(); 1.2448 + 1.2449 + *type = mUniforms[index]->type; 1.2450 +} 1.2451 + 1.2452 +GLint ProgramBinary::getActiveUniformCount() const 1.2453 +{ 1.2454 + return mUniforms.size(); 1.2455 +} 1.2456 + 1.2457 +GLint ProgramBinary::getActiveUniformMaxLength() const 1.2458 +{ 1.2459 + int maxLength = 0; 1.2460 + 1.2461 + unsigned int numUniforms = mUniforms.size(); 1.2462 + for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) 1.2463 + { 1.2464 + if (!mUniforms[uniformIndex]->name.empty()) 1.2465 + { 1.2466 + int length = (int)(mUniforms[uniformIndex]->name.length() + 1); 1.2467 + if (mUniforms[uniformIndex]->isArray()) 1.2468 + { 1.2469 + length += 3; // Counting in "[0]". 1.2470 + } 1.2471 + maxLength = std::max(length, maxLength); 1.2472 + } 1.2473 + } 1.2474 + 1.2475 + return maxLength; 1.2476 +} 1.2477 + 1.2478 +void ProgramBinary::validate(InfoLog &infoLog) 1.2479 +{ 1.2480 + applyUniforms(); 1.2481 + if (!validateSamplers(&infoLog)) 1.2482 + { 1.2483 + mValidated = false; 1.2484 + } 1.2485 + else 1.2486 + { 1.2487 + mValidated = true; 1.2488 + } 1.2489 +} 1.2490 + 1.2491 +bool ProgramBinary::validateSamplers(InfoLog *infoLog) 1.2492 +{ 1.2493 + // if any two active samplers in a program are of different types, but refer to the same 1.2494 + // texture image unit, and this is the current program, then ValidateProgram will fail, and 1.2495 + // DrawArrays and DrawElements will issue the INVALID_OPERATION error. 1.2496 + 1.2497 + const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); 1.2498 + TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; 1.2499 + 1.2500 + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) 1.2501 + { 1.2502 + textureUnitType[i] = TEXTURE_UNKNOWN; 1.2503 + } 1.2504 + 1.2505 + for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) 1.2506 + { 1.2507 + if (mSamplersPS[i].active) 1.2508 + { 1.2509 + unsigned int unit = mSamplersPS[i].logicalTextureUnit; 1.2510 + 1.2511 + if (unit >= maxCombinedTextureImageUnits) 1.2512 + { 1.2513 + if (infoLog) 1.2514 + { 1.2515 + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); 1.2516 + } 1.2517 + 1.2518 + return false; 1.2519 + } 1.2520 + 1.2521 + if (textureUnitType[unit] != TEXTURE_UNKNOWN) 1.2522 + { 1.2523 + if (mSamplersPS[i].textureType != textureUnitType[unit]) 1.2524 + { 1.2525 + if (infoLog) 1.2526 + { 1.2527 + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 1.2528 + } 1.2529 + 1.2530 + return false; 1.2531 + } 1.2532 + } 1.2533 + else 1.2534 + { 1.2535 + textureUnitType[unit] = mSamplersPS[i].textureType; 1.2536 + } 1.2537 + } 1.2538 + } 1.2539 + 1.2540 + for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) 1.2541 + { 1.2542 + if (mSamplersVS[i].active) 1.2543 + { 1.2544 + unsigned int unit = mSamplersVS[i].logicalTextureUnit; 1.2545 + 1.2546 + if (unit >= maxCombinedTextureImageUnits) 1.2547 + { 1.2548 + if (infoLog) 1.2549 + { 1.2550 + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); 1.2551 + } 1.2552 + 1.2553 + return false; 1.2554 + } 1.2555 + 1.2556 + if (textureUnitType[unit] != TEXTURE_UNKNOWN) 1.2557 + { 1.2558 + if (mSamplersVS[i].textureType != textureUnitType[unit]) 1.2559 + { 1.2560 + if (infoLog) 1.2561 + { 1.2562 + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 1.2563 + } 1.2564 + 1.2565 + return false; 1.2566 + } 1.2567 + } 1.2568 + else 1.2569 + { 1.2570 + textureUnitType[unit] = mSamplersVS[i].textureType; 1.2571 + } 1.2572 + } 1.2573 + } 1.2574 + 1.2575 + return true; 1.2576 +} 1.2577 + 1.2578 +ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) 1.2579 +{ 1.2580 +} 1.2581 + 1.2582 +struct AttributeSorter 1.2583 +{ 1.2584 + AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS]) 1.2585 + : originalIndices(semanticIndices) 1.2586 + { 1.2587 + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 1.2588 + { 1.2589 + indices[i] = i; 1.2590 + } 1.2591 + 1.2592 + std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this); 1.2593 + } 1.2594 + 1.2595 + bool operator()(int a, int b) 1.2596 + { 1.2597 + return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b]; 1.2598 + } 1.2599 + 1.2600 + int indices[MAX_VERTEX_ATTRIBS]; 1.2601 + const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; 1.2602 +}; 1.2603 + 1.2604 +void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const 1.2605 +{ 1.2606 + AttributeSorter sorter(mSemanticIndex); 1.2607 + 1.2608 + int oldIndices[MAX_VERTEX_ATTRIBS]; 1.2609 + rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS]; 1.2610 + 1.2611 + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 1.2612 + { 1.2613 + oldIndices[i] = mSemanticIndex[i]; 1.2614 + oldTranslatedAttributes[i] = attributes[i]; 1.2615 + } 1.2616 + 1.2617 + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 1.2618 + { 1.2619 + int oldIndex = sorter.indices[i]; 1.2620 + sortedSemanticIndices[i] = oldIndices[oldIndex]; 1.2621 + attributes[i] = oldTranslatedAttributes[oldIndex]; 1.2622 + } 1.2623 +} 1.2624 + 1.2625 +}