| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- // Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <anki/gr/gl/ShaderProgramImpl.h>
- #include <anki/gr/Shader.h>
- #include <anki/gr/gl/ShaderImpl.h>
- namespace anki
- {
- static void deletePrograms(GLsizei n, const GLuint* progs)
- {
- ANKI_ASSERT(n == 1);
- ANKI_ASSERT(progs);
- glDeleteProgram(*progs);
- }
- ShaderProgramImpl::~ShaderProgramImpl()
- {
- destroyDeferred(getManager(), deletePrograms);
- m_refl.m_uniforms.destroy(getAllocator());
- }
- Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
- {
- m_glName = glCreateProgram();
- ANKI_ASSERT(m_glName != 0);
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*vert).getGlName());
- m_shaders[ShaderType::VERTEX] = vert;
- if(tessc)
- {
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tessc).getGlName());
- m_shaders[ShaderType::TESSELLATION_CONTROL] = tessc;
- }
- if(tesse)
- {
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*tesse).getGlName());
- m_shaders[ShaderType::TESSELLATION_EVALUATION] = tesse;
- }
- if(geom)
- {
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*geom).getGlName());
- m_shaders[ShaderType::GEOMETRY] = geom;
- }
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*frag).getGlName());
- m_shaders[ShaderType::FRAGMENT] = frag;
- return link(static_cast<const ShaderImpl&>(*vert).getGlName(), static_cast<const ShaderImpl&>(*frag).getGlName());
- }
- Error ShaderProgramImpl::initCompute(ShaderPtr comp)
- {
- m_glName = glCreateProgram();
- ANKI_ASSERT(m_glName != 0);
- glAttachShader(m_glName, static_cast<const ShaderImpl&>(*comp).getGlName());
- m_shaders[ShaderType::COMPUTE] = comp;
- return link(0, 0);
- }
- Error ShaderProgramImpl::link(GLuint vert, GLuint frag)
- {
- Error err = Error::NONE;
- glLinkProgram(m_glName);
- GLint status = 0;
- glGetProgramiv(m_glName, GL_LINK_STATUS, &status);
- if(!status)
- {
- GLint infoLen = 0;
- GLint charsWritten = 0;
- DynamicArrayAuto<char> infoLogTxt(getAllocator());
- glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &infoLen);
- infoLogTxt.create(infoLen + 1);
- glGetProgramInfoLog(m_glName, infoLen, &charsWritten, &infoLogTxt[0]);
- ANKI_GL_LOGE("Link error log follows (vs:%u, fs:%u):\n%s", vert, frag, &infoLogTxt[0]);
- err = Error::USER_DATA;
- }
- return err;
- }
- const ShaderProgramImplReflection& ShaderProgramImpl::getReflection()
- {
- if(m_reflInitialized)
- {
- return m_refl;
- }
- GLint uniformCount = 0;
- glGetProgramiv(getGlName(), GL_ACTIVE_UNIFORMS, &uniformCount);
- if(uniformCount)
- {
- for(U i = 0; i < U(uniformCount); ++i)
- {
- // Get uniform info
- GLsizei len;
- GLenum type;
- GLint size;
- Array<char, 128> name;
- glGetActiveUniform(getGlName(), i, sizeof(name), &len, &size, &type, &name[0]);
- name[len] = '\0';
- if(CString(&name[0]).find("gl_") == 0)
- {
- // Builtin, skip
- continue;
- }
- // Set type
- ShaderVariableDataType akType = ShaderVariableDataType::NONE;
- switch(type)
- {
- case GL_FLOAT_VEC4:
- akType = ShaderVariableDataType::VEC4;
- break;
- case GL_INT_VEC4:
- akType = ShaderVariableDataType::IVEC4;
- break;
- case GL_UNSIGNED_INT_VEC4:
- akType = ShaderVariableDataType::UVEC4;
- break;
- case GL_FLOAT_MAT4:
- akType = ShaderVariableDataType::MAT4;
- break;
- case GL_FLOAT_MAT3:
- akType = ShaderVariableDataType::MAT3;
- break;
- default:
- // Unsupported type, skip as well
- continue;
- }
- const GLint location = glGetUniformLocation(getGlName(), &name[0]);
- if(location < 0)
- {
- // Uniform block maybe, skip
- continue;
- }
- // Store
- ShaderProgramImplReflection::Uniform uni;
- uni.m_location = location;
- uni.m_type = akType;
- uni.m_arrSize = size;
- m_refl.m_uniforms.emplaceBack(getAllocator(), uni);
- }
- // Sort the uniforms
- std::sort(m_refl.m_uniforms.getBegin(),
- m_refl.m_uniforms.getEnd(),
- [](const ShaderProgramImplReflection::Uniform& a, const ShaderProgramImplReflection::Uniform& b) {
- return a.m_location < b.m_location;
- });
- // Now calculate the offset inside the push constant buffer
- m_refl.m_uniformDataSize = 0;
- for(ShaderProgramImplReflection::Uniform& uni : m_refl.m_uniforms)
- {
- U32 dataSize = 0;
- switch(uni.m_type)
- {
- case ShaderVariableDataType::VEC4:
- case ShaderVariableDataType::IVEC4:
- case ShaderVariableDataType::UVEC4:
- dataSize = sizeof(F32) * 4;
- break;
- case ShaderVariableDataType::MAT4:
- dataSize = sizeof(F32) * 16;
- break;
- case ShaderVariableDataType::MAT3:
- dataSize = sizeof(F32) * 12;
- break;
- default:
- ANKI_ASSERT(!"Unsupported type");
- }
- uni.m_pushConstantOffset = m_refl.m_uniformDataSize;
- m_refl.m_uniformDataSize += dataSize * uni.m_arrSize;
- }
- }
- m_reflInitialized = true;
- return m_refl;
- }
- } // end namespace anki
|