| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892 |
- #include "anki/gl/ShaderProgram.h"
- #include "anki/gl/GlException.h"
- #include "anki/gl/GlState.h"
- #include "anki/math/Math.h"
- #include "anki/util/Exception.h"
- #include "anki/gl/Texture.h"
- #include "anki/core/Logger.h"
- #include "anki/util/StringList.h"
- #include "anki/util/Array.h"
- #include <sstream>
- #include <iomanip>
- namespace anki {
- //==============================================================================
- static const char* padding = "======================================="
- "=======================================";
- //==============================================================================
- // ShaderProgramVariable =
- //==============================================================================
- //==============================================================================
- ShaderProgramVariable& ShaderProgramVariable::operator=(
- const ShaderProgramVariable& b)
- {
- ANKI_ASSERT(type == b.type);
- loc = b.loc;
- name = b.name;
- glDataType = b.glDataType;
- size = b.size;
- fatherSProg = b.fatherSProg;
- return *this;
- }
- //==============================================================================
- // ShaderProgramUniformVariable =
- //==============================================================================
- //==============================================================================
- ShaderProgramUniformVariable& ShaderProgramUniformVariable::operator=(
- const ShaderProgramUniformVariable& b)
- {
- ShaderProgramVariable::operator=(b);
- index = b.index;
- block = b.block;
- offset = b.offset;
- arrayStride = b.arrayStride;
- matrixStride = b.matrixStride;
- return *this;
- }
- //==============================================================================
- void ShaderProgramUniformVariable::doCommonSetCode() const
- {
- ANKI_ASSERT(getLocation() != -1
- && "You cannot set variable in uniform block");
- ANKI_ASSERT(ShaderProgram::getCurrentProgramGlId() ==
- getFatherShaderProgram().getGlId());
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const F32 x) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT);
- ANKI_ASSERT(getSize() == 1);
- glUniform1f(getLocation(), x);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Vec2& x) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
- ANKI_ASSERT(getSize() == 1);
- glUniform2f(getLocation(), x.x(), x.y());
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const F32 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT);
- ANKI_ASSERT(size <= getSize() && size != 0);
-
- glUniform1fv(getLocation(), size, x);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Vec2 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
- ANKI_ASSERT(size <= getSize() && size != 0);
- glUniform2fv(getLocation(), size, &(const_cast<Vec2&>(x[0]))[0]);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Vec3 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC3);
- ANKI_ASSERT(size <= getSize() && size != 0);
- glUniform3fv(getLocation(), size, &(const_cast<Vec3&>(x[0]))[0]);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Vec4 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC4);
- ANKI_ASSERT(size <= getSize() && size != 0);
-
- glUniform4fv(getLocation(), size, &(const_cast<Vec4&>(x[0]))[0]);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Mat3 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT3);
- ANKI_ASSERT(size <= getSize() && size != 0);
- glUniformMatrix3fv(getLocation(), size, true, &(x[0])[0]);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Mat4 x[], U32 size) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT4);
- ANKI_ASSERT(size <= getSize() && size != 0);
- glUniformMatrix4fv(getLocation(), size, true, &(x[0])[0]);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Texture& tex) const
- {
- doCommonSetCode();
- ANKI_ASSERT(getGlDataType() == GL_SAMPLER_2D
- || getGlDataType() == GL_SAMPLER_2D_SHADOW
- || getGlDataType() == GL_UNSIGNED_INT_SAMPLER_2D
- || getGlDataType() == GL_SAMPLER_2D_ARRAY_SHADOW);
-
- glUniform1i(getLocation(), tex.bind());
- }
- //==============================================================================
- void ShaderProgramUniformVariable::set(const Texture* const texes[],
- const U32 count) const
- {
- doCommonSetCode();
- ANKI_ASSERT(count <= getSize() && count != 0);
- ANKI_ASSERT(count <= 128);
- Array<GLint, 128> units;
- for(U32 i = 0; i < count; i++)
- {
- const Texture* tex = texes[i];
- units[i] = tex->bind();
- }
- glUniform1iv(getLocation(), count, &units[0]);
- }
- //==============================================================================
- // Template functions that return the GL type using an AnKi type
- template<typename T>
- static Bool checkType(GLenum glDataType);
- template<>
- Bool checkType<F32>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT;
- }
- template<>
- Bool checkType<Vec2>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT_VEC2;
- }
- template<>
- Bool checkType<Vec3>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT_VEC3;
- }
- template<>
- Bool checkType<Vec4>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT_VEC4;
- }
- template<>
- Bool checkType<Mat3>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT_MAT3;
- }
- template<>
- Bool checkType<Mat4>(GLenum glDataType)
- {
- return glDataType == GL_FLOAT_MAT4;
- }
- //==============================================================================
- template<typename T>
- void ShaderProgramUniformVariable::setClientMemorySanityChecks(
- U32 buffSize, U32 size) const
- {
- ANKI_ASSERT(checkType<T>(getGlDataType()));
- ANKI_ASSERT(size <= getSize() && size > 0);
- ANKI_ASSERT(offset != -1 && arrayStride != -1 && "Uniform is not in block");
- ANKI_ASSERT(block->getSize() <= buffSize);
- ANKI_ASSERT(size <= 1 || arrayStride != 0);
- }
- //==============================================================================
- template<typename T>
- void ShaderProgramUniformVariable::setClientMemoryInternal(
- void* buff_, U32 buffSize, const T arr[], U32 size) const
- {
- setClientMemorySanityChecks<T>(buffSize, size);
- U8* buff = (U8*)buff_ + offset;
- for(U32 i = 0; i < size; i++)
- {
- T* ptr = (T*)buff;
- *ptr = arr[i];
- buff += arrayStride;
- }
- }
- //==============================================================================
- template<typename T, typename Vec>
- void ShaderProgramUniformVariable::setClientMemoryInternalMatrix(
- void* buff_, U32 buffSize, const T arr[], U32 size) const
- {
- setClientMemorySanityChecks<T>(buffSize, size);
- ANKI_ASSERT(matrixStride >= (GLint)sizeof(Vec));
- U8* buff = (U8*)buff_ + offset;
- for(U32 i = 0; i < size; i++)
- {
- U8* subbuff = buff;
- for(U j = 0; j < sizeof(T) / sizeof(Vec); j++)
- {
- Vec* ptr = (Vec*)subbuff;
- *ptr = arr[i].getRow(j);
- subbuff += matrixStride;
- }
- buff += arrayStride;
- }
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const F32 arr[], U32 size) const
- {
- setClientMemoryInternal(buff, buffSize, arr, size);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const Vec2 arr[], U32 size) const
- {
- setClientMemoryInternal(buff, buffSize, arr, size);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const Vec3 arr[], U32 size) const
- {
- setClientMemoryInternal(buff, buffSize, arr, size);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const Vec4 arr[], U32 size) const
- {
- setClientMemoryInternal(buff, buffSize, arr, size);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const Mat3 arr[], U32 size) const
- {
- setClientMemoryInternalMatrix<Mat3, Vec3>(buff, buffSize, arr, size);
- }
- //==============================================================================
- void ShaderProgramUniformVariable::setClientMemory(void* buff, U32 buffSize,
- const Mat4 arr[], U32 size) const
- {
- setClientMemoryInternalMatrix<Mat4, Vec4>(buff, buffSize, arr, size);
- }
- //==============================================================================
- // ShaderProgramUniformBlock =
- //==============================================================================
- //==============================================================================
- ShaderProgramUniformBlock& ShaderProgramUniformBlock::operator=(
- const ShaderProgramUniformBlock& b)
- {
- uniforms = b.uniforms;
- index = b.index;
- size = b.size;
- name = b.name;
- bindingPoint = b.bindingPoint;
- progId = b.progId;
- return *this;
- }
- //==============================================================================
- // ShaderProgram =
- //==============================================================================
- //==============================================================================
- thread_local const ShaderProgram* ShaderProgram::current = nullptr;
- //==============================================================================
- void ShaderProgram::create(const char* vertSource, const char* tcSource,
- const char* teSource, const char* geomSource, const char* fragSource,
- const char* xfbVaryings[], const GLenum xfbBufferMode)
- {
- ANKI_ASSERT(!isCreated());
- U32 minor = GlStateCommonSingleton::get().getMinorVersion();
- U32 major = GlStateCommonSingleton::get().getMajorVersion();
- // 1) create and compile the shaders
- //
- std::string preprocSrc;
- #if ANKI_GL == ANKI_GL_DESKTOP
- preprocSrc = "#version " + std::to_string(major)
- + std::to_string(minor) + "0 core\n";
- if(major == 3)
- {
- preprocSrc += "#extension GL_ARB_shading_language_420pack : enable\n"
- "#extension GL_ARB_shading_language_packing : enable\n"
- "#extension GL_ARB_gpu_shader5 : enable\n";
- }
- else
- {
- preprocSrc += "#extension GL_ARB_gpu_shader5 : enable\n";
- }
- #else
- preprocSrc = "#version " + std::to_string(major)
- + std::to_string(minor) + "0 es\n";
- #endif
- ANKI_ASSERT(vertSource != nullptr);
- vertShaderGlId = createAndCompileShader(vertSource, preprocSrc.c_str(),
- GL_VERTEX_SHADER);
- if(tcSource != nullptr)
- {
- #if ANKI_GL == ANKI_GL_DESKTOP
- ANKI_ASSERT(major > 3);
- tcShaderGlId = createAndCompileShader(tcSource, preprocSrc.c_str(),
- GL_TESS_CONTROL_SHADER);
- #else
- ANKI_ASSERT(0 && "Not allowed");
- #endif
- }
- if(teSource != nullptr)
- {
- #if ANKI_GL == ANKI_GL_DESKTOP
- ANKI_ASSERT(major > 3);
- teShaderGlId = createAndCompileShader(teSource, preprocSrc.c_str(),
- GL_TESS_EVALUATION_SHADER);
- #else
- ANKI_ASSERT(0 && "Not allowed");
- #endif
- }
- if(geomSource != nullptr)
- {
- #if ANKI_GL == ANKI_GL_DESKTOP
- geomShaderGlId = createAndCompileShader(geomSource,
- preprocSrc.c_str(), GL_GEOMETRY_SHADER);
- #else
- ANKI_ASSERT(0 && "Not allowed");
- #endif
- }
- ANKI_ASSERT(fragSource != nullptr);
- fragShaderGlId = createAndCompileShader(fragSource, preprocSrc.c_str(),
- GL_FRAGMENT_SHADER);
- // 2) create program and attach shaders
- glId = glCreateProgram();
- if(glId == 0)
- {
- throw ANKI_EXCEPTION("glCreateProgram() failed");
- }
- glAttachShader(glId, vertShaderGlId);
- glAttachShader(glId, fragShaderGlId);
- if(tcSource != nullptr)
- {
- glAttachShader(glId, tcShaderGlId);
- }
- if(teSource != nullptr)
- {
- glAttachShader(glId, teShaderGlId);
- }
- if(geomSource != nullptr)
- {
- glAttachShader(glId, geomShaderGlId);
- }
- // 3) set the XFB varyings
- U count = 0;
- if(xfbVaryings)
- {
- while(xfbVaryings[count] != nullptr)
- {
- ++count;
- }
- }
- if(count)
- {
- glTransformFeedbackVaryings(
- glId,
- count,
- xfbVaryings,
- xfbBufferMode);
- }
- // 4) link
- link();
- // init the rest
- bind();
- initUniAndAttribVars();
- initUniformBlocks();
- }
- //==============================================================================
- void ShaderProgram::destroy()
- {
- unbind();
- if(vertShaderGlId != 0)
- {
- glDeleteShader(vertShaderGlId);
- }
- if(tcShaderGlId != 0)
- {
- glDeleteShader(tcShaderGlId);
- }
- if(teShaderGlId != 0)
- {
- glDeleteShader(teShaderGlId);
- }
- if(geomShaderGlId != 0)
- {
- glDeleteShader(geomShaderGlId);
- }
- if(fragShaderGlId != 0)
- {
- glDeleteShader(fragShaderGlId);
- }
- if(glId != 0)
- {
- glDeleteProgram(glId);
- }
- init();
- }
- //==============================================================================
- GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
- const char* preproc, GLenum type)
- {
- GLuint glId = 0;
- const char* sourceStrs[1] = {nullptr};
- // create the shader
- glId = glCreateShader(type);
- // attach the source
- std::string fullSrc = preproc;
- fullSrc += sourceCode;
- sourceStrs[0] = fullSrc.c_str();
- // compile
- glShaderSource(glId, 1, sourceStrs, NULL);
- glCompileShader(glId);
- GLint success;
- glGetShaderiv(glId, GL_COMPILE_STATUS, &success);
- if(!success)
- {
- // Get info log
- GLint infoLen = 0;
- GLint charsWritten = 0;
- Vector<char> infoLog;
- glGetShaderiv(glId, GL_INFO_LOG_LENGTH, &infoLen);
- infoLog.resize(infoLen + 1);
- glGetShaderInfoLog(glId, infoLen, &charsWritten, &infoLog[0]);
- infoLog[charsWritten] = '\0';
- std::stringstream err;
- err << "Shader compile failed (0x" << std::hex << type << std::dec
- << "):\n" << padding << "\n" << &infoLog[0]
- << "\n" << padding << "\nSource:\n" << padding << "\n";
- // Prettyfy source
- StringList lines = StringList::splitString(fullSrc.c_str(), '\n', true);
- int lineno = 0;
- for(const std::string& line : lines)
- {
- err << std::setw(4) << std::setfill('0') << ++lineno << ": "
- << line << std::endl;
- }
- err << padding;
-
- // Throw
- throw ANKI_EXCEPTION(err.str());
- }
- ANKI_ASSERT(glId != 0);
- return glId;
- }
- //==============================================================================
- void ShaderProgram::link() const
- {
- // link
- glLinkProgram(glId);
- // check if linked correctly
- GLint success;
- glGetProgramiv(glId, GL_LINK_STATUS, &success);
- if(!success)
- {
- int info_len = 0;
- int charsWritten = 0;
- std::string infoLogTxt;
- glGetProgramiv(glId, GL_INFO_LOG_LENGTH, &info_len);
- infoLogTxt.resize(info_len + 1);
- glGetProgramInfoLog(glId, info_len, &charsWritten, &infoLogTxt[0]);
- throw ANKI_EXCEPTION("Link error log follows:\n"
- + infoLogTxt);
- }
- }
- //==============================================================================
- void ShaderProgram::initUniAndAttribVars()
- {
- GLint num;
- Array<char, 256> name_;
- GLsizei length;
- GLint size;
- GLenum type;
- //
- // attrib locations
- //
- glGetProgramiv(glId, GL_ACTIVE_ATTRIBUTES, &num);
- U32 attribsCount = (U32)num;
- // Count the _useful_ attribs
- for(GLint i = 0; i < num; i++)
- {
- // Name
- glGetActiveAttrib(glId, i, sizeof(name_), &length,
- &size, &type, &name_[0]);
- name_[length] = '\0';
- // check if its FFP location
- GLint loc = glGetAttribLocation(glId, &name_[0]);
- if(loc == -1)
- {
- // if -1 it means that its an FFP var or a weird crap like
- // gl_InstanceID
- --attribsCount;
- }
- }
- attribs.resize(attribsCount);
- attribs.shrink_to_fit();
- attribsCount = 0;
- for(GLint i = 0; i < num; i++) // loop all attributes
- {
- // Name
- glGetActiveAttrib(glId, i, sizeof(name_), &length,
- &size, &type, &name_[0]);
- name_[length] = '\0';
- // check if its FFP location
- GLint loc = glGetAttribLocation(glId, &name_[0]);
- if(loc == -1)
- {
- // if -1 it means that its an FFP var or a weird crap like
- // gl_InstanceID
- continue;
- }
- ShaderProgramAttributeVariable& var = attribs[attribsCount++];
- var.loc = loc;
- var.name = &name_[0];
- var.name.shrink_to_fit();
- var.glDataType = type;
- var.size = size;
- var.fatherSProg = this;
- nameToAttribVar[var.name.c_str()] = &var;
- }
- //
- // uni locations
- //
- glGetProgramiv(glId, GL_ACTIVE_UNIFORMS, &num);
- U unisCount = num;
- // Count the _useful_ uniforms
- for(GLint i = 0; i < num; i++)
- {
- glGetActiveUniform(glId, i, sizeof(name_), &length,
- &size, &type, &name_[0]);
- name_[length] = '\0';
- // See bellow for info
- if(strchr(&name_[0], '[') != nullptr
- && strstr(&name_[0], "[0]") == nullptr)
- {
- --unisCount;
- }
- }
- unis.resize(unisCount);
- unis.shrink_to_fit();
- unisCount = 0;
- for(GLint i = 0; i < num; i++) // loop all uniforms
- {
- glGetActiveUniform(glId, i, sizeof(name_), &length,
- &size, &type, &name_[0]);
- name_[length] = '\0';
- // In case of uniform arrays some implementations (nVidia) on
- // GL_ACTIVE_UNIFORMS they return the number of uniforms that are inside
- // that uniform array in addition to the first element (it will count
- // for example the float_arr[9]). But other implementations don't (Mali
- // T6xx). Also in some cases with big arrays (IS shader) this will
- // overpopulate the uniforms vector and hash map. So, to solve this if
- // the uniform name has something like this "[N]" where N != 0 then
- // ignore the uniform and put it as array
- if(strchr(&name_[0], '[') != nullptr)
- {
- // Found bracket
- if(strstr(&name_[0], "[0]") == nullptr)
- {
- // Found something other than "[0]"
- continue;
- }
- else
- {
- // Cut the bracket stuff
- name_[length - 3] = '\0';
- }
- }
- ShaderProgramUniformVariable& var = unis[unisCount++];
- // -1 means in uniform block
- GLint loc = glGetUniformLocation(glId, &name_[0]);
- var.loc = loc;
- var.name = &name_[0];
- var.name.shrink_to_fit();
- var.glDataType = type;
- var.size = size;
- var.fatherSProg = this;
- var.index = (GLuint)i;
- nameToUniVar[var.name.c_str()] = &var;
- }
- }
- //==============================================================================
- void ShaderProgram::initUniformBlocks()
- {
- // Get blocks count and create the vector
- GLint blocksCount;
- glGetProgramiv(glId, GL_ACTIVE_UNIFORM_BLOCKS, &blocksCount);
- if(blocksCount < 1)
- {
- // Early exit
- return;
- }
- blocks.resize(blocksCount);
- blocks.shrink_to_fit();
- // Init all blocks
- GLuint i = 0;
- for(ShaderProgramUniformBlock& block : blocks)
- {
- GLint gli; // General purpose int
- // Name
- Array<char, 256> name;
- GLsizei len;
- glGetActiveUniformBlockName(glId, i, sizeof(name), &len, &name[0]);
- // The name is null terminated
- block.name = &name[0];
- block.name.shrink_to_fit();
- // Index
- ANKI_ASSERT(glGetUniformBlockIndex(glId, name) == i);
- block.index = i;
- // Size
- glGetActiveUniformBlockiv(glId, i, GL_UNIFORM_BLOCK_DATA_SIZE, &gli);
- block.size = gli;
- // Binding point
- glGetActiveUniformBlockiv(glId, i, GL_UNIFORM_BLOCK_BINDING, &gli);
- block.bindingPoint = gli;
- // Prog id
- block.progId = glId;
- // Other update
- nameToBlock[block.name.c_str()] = █
- ++i;
- }
- // Connect uniforms and blocks
- for(ShaderProgramUniformVariable& uni : unis)
- {
- /* Block index */
- GLint blockIndex;
- glGetActiveUniformsiv(glId, 1, &(uni.index), GL_UNIFORM_BLOCK_INDEX,
- &blockIndex);
- if(blockIndex == -1)
- {
- continue;
- }
- uni.block = &blocks[blockIndex];
- blocks[blockIndex].uniforms.push_back(&uni);
- /* Offset in block */
- GLint offset;
- glGetActiveUniformsiv(glId, 1, &(uni.index), GL_UNIFORM_OFFSET,
- &offset);
- ANKI_ASSERT(offset != -1); // If -1 then it should break before
- uni.offset = offset;
- /* Array stride */
- GLint arrStride;
- glGetActiveUniformsiv(glId, 1, &(uni.index), GL_UNIFORM_ARRAY_STRIDE,
- &arrStride);
- ANKI_ASSERT(arrStride != -1); // If -1 then it should break before
- uni.arrayStride = arrStride;
- /* Matrix stride */
- GLint matStride;
- glGetActiveUniformsiv(glId, 1, &(uni.index), GL_UNIFORM_MATRIX_STRIDE,
- &matStride);
- ANKI_ASSERT(matStride != -1); // If -1 then it should break before
- uni.matrixStride = matStride;
- /* Matrix layout check */
- GLint isRowMajor;
- glGetActiveUniformsiv(glId, 1, &(uni.index), GL_UNIFORM_IS_ROW_MAJOR,
- &isRowMajor);
- if(isRowMajor)
- {
- ANKI_LOGW("The engine is designed to work with column major "
- "matrices: " << uni.name);
- }
- }
- }
- //==============================================================================
- const ShaderProgramAttributeVariable*
- ShaderProgram::tryFindAttributeVariable(const char* name) const
- {
- NameToAttribVarHashMap::const_iterator it = nameToAttribVar.find(name);
- return (it == nameToAttribVar.end()) ? nullptr : it->second;
- }
- //==============================================================================
- const ShaderProgramAttributeVariable&
- ShaderProgram::findAttributeVariable(const char* name) const
- {
- const ShaderProgramAttributeVariable* var = tryFindAttributeVariable(name);
- if(var == nullptr)
- {
- throw ANKI_EXCEPTION("Attribute variable not found: " + name);
- }
- return *var;
- }
- //==============================================================================
- const ShaderProgramUniformVariable* ShaderProgram::tryFindUniformVariable(
- const char* name) const
- {
- NameToUniVarHashMap::const_iterator it = nameToUniVar.find(name);
- if(it == nameToUniVar.end())
- {
- return nullptr;
- }
- return it->second;
- }
- //==============================================================================
- const ShaderProgramUniformVariable& ShaderProgram::findUniformVariable(
- const char* name) const
- {
- const ShaderProgramUniformVariable* var = tryFindUniformVariable(name);
- if(var == nullptr)
- {
- throw ANKI_EXCEPTION("Uniform variable not found: " + name);
- }
- return *var;
- }
- //==============================================================================
- const ShaderProgramUniformBlock* ShaderProgram::tryFindUniformBlock(
- const char* name) const
- {
- NameToUniformBlockHashMap::const_iterator it = nameToBlock.find(name);
- return (it == nameToBlock.end()) ? nullptr : it->second;
- }
- //==============================================================================
- const ShaderProgramUniformBlock& ShaderProgram::findUniformBlock(
- const char* name) const
- {
- const ShaderProgramUniformBlock* block = tryFindUniformBlock(name);
- if(block == nullptr)
- {
- throw ANKI_EXCEPTION("Block not found: " + name);
- }
- return *block;
- }
- //==============================================================================
- std::ostream& operator<<(std::ostream& s, const ShaderProgram& x)
- {
- s << "ShaderProgram\n";
- s << "Uniform variables:\n";
- for(auto var : x.unis)
- {
- s << var.getName() << " " << var.getLocation() << '\n';
- }
- s << "Attrib variables:\n";
- for(auto var : x.attribs)
- {
- s << var.getName() << " " << var.getLocation() << '\n';
- }
- return s;
- }
- } // end namespace anki
|