| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Gr/gl/ShaderImpl.h>
- #include <AnKi/Gr/GrManager.h>
- #include <AnKi/Gr/gl/GrManagerImpl.h>
- #include <AnKi/Gr/gl/GlState.h>
- #include <AnKi/Gr/ShaderCompiler.h>
- #include <AnKi/Util/StringList.h>
- #include <AnKi/Util/Logger.h>
- #define ANKI_DUMP_SHADERS ANKI_EXTRA_CHECKS
- #if ANKI_DUMP_SHADERS
- # include <anki/util/File.h>
- #endif
- namespace anki {
- /// Fake glDeleteShaders because some jenius created a conflicting interface
- static void deleteShaders(GLsizei n, const GLuint* names)
- {
- ANKI_ASSERT(n == 1);
- ANKI_ASSERT(names);
- glDeleteShader(*names);
- }
- ShaderImpl::~ShaderImpl()
- {
- destroyDeferred(getManager(), deleteShaders);
- }
- Error ShaderImpl::init(CString source, ConstWeakArray<ShaderSpecializationConstValue> constValues)
- {
- ANKI_ASSERT(source);
- ANKI_ASSERT(!isCreated());
- static const Array<GLenum, 6> gltype = {{GL_VERTEX_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER,
- GL_GEOMETRY_SHADER, GL_FRAGMENT_SHADER, GL_COMPUTE_SHADER}};
- m_glType = gltype[U(m_shaderType)];
- // Create a new shader with spec consts if needed
- StringAuto newSrc(getAllocator());
- if(constValues.getSize())
- {
- // Create const str
- StringListAuto constStrLines(getAllocator());
- U count = 0;
- for(const ShaderSpecializationConstValue& constVal : constValues)
- {
- if(constVal.m_dataType == ShaderVariableDataType::INT)
- {
- constStrLines.pushBackSprintf("#define _anki_spec_const_%u %i", count, constVal.m_int);
- }
- else
- {
- ANKI_ASSERT(constVal.m_dataType == ShaderVariableDataType::FLOAT);
- constStrLines.pushBackSprintf("#define _anki_spec_const_%u %f", count, constVal.m_float);
- }
- ++count;
- }
- StringAuto constStr(getAllocator());
- constStrLines.join("\n", constStr);
- // Break the old source
- StringListAuto lines(getAllocator());
- lines.splitString(source, '\n');
- ANKI_ASSERT(lines.getFront().find("#version") == 0);
- lines.popFront();
- // Append the const values
- lines.pushFront(constStr.toCString());
- lines.pushFront("#version 450 core");
- // Create the new string
- lines.join("\n", newSrc);
- source = newSrc.toCString();
- }
- // Gen name, create and compile
- const char* sourceStrs[1] = {nullptr};
- sourceStrs[0] = &source[0];
- m_glName = glCreateShader(m_glType);
- glShaderSource(m_glName, 1, sourceStrs, NULL);
- glCompileShader(m_glName);
- #if ANKI_DUMP_SHADERS
- {
- const char* ext;
- switch(m_glType)
- {
- case GL_VERTEX_SHADER:
- ext = "vert";
- break;
- case GL_TESS_CONTROL_SHADER:
- ext = "tesc";
- break;
- case GL_TESS_EVALUATION_SHADER:
- ext = "tese";
- break;
- case GL_GEOMETRY_SHADER:
- ext = "geom";
- break;
- case GL_FRAGMENT_SHADER:
- ext = "frag";
- break;
- case GL_COMPUTE_SHADER:
- ext = "comp";
- break;
- default:
- ext = nullptr;
- ANKI_ASSERT(0);
- }
- StringAuto fname(getAllocator());
- CString cacheDir = getManager().getCacheDirectory();
- fname.sprintf("%s/%05u.%s", &cacheDir[0], static_cast<U32>(m_glName), ext);
- File file;
- ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
- ANKI_CHECK(file.writeText("%s", source.cstr()));
- }
- #endif
- GLint status = GL_FALSE;
- glGetShaderiv(m_glName, GL_COMPILE_STATUS, &status);
- if(status == GL_FALSE)
- {
- auto alloc = getAllocator();
- StringAuto compilerLog(alloc);
- GLint compilerLogLen = 0;
- GLint charsWritten = 0;
- glGetShaderiv(m_glName, GL_INFO_LOG_LENGTH, &compilerLogLen);
- compilerLog.create(' ', compilerLogLen + 1);
- glGetShaderInfoLog(m_glName, compilerLogLen, &charsWritten, &compilerLog[0]);
- ShaderCompiler::logShaderErrorCode(compilerLog.toCString(), source, alloc);
- // Compilation failed, set error anyway
- return Error::USER_DATA;
- }
- return Error::NONE;
- }
- } // end namespace anki
|