// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #include #include #include #include #include #include #include #include namespace anki { #if ANKI_GL == ANKI_GL_DESKTOP struct GlDbg { GLenum token; const char* str; }; static const GlDbg gldbgsource[] = {{GL_DEBUG_SOURCE_API, "GL_DEBUG_SOURCE_API"}, {GL_DEBUG_SOURCE_WINDOW_SYSTEM, "GL_DEBUG_SOURCE_WINDOW_SYSTEM"}, {GL_DEBUG_SOURCE_SHADER_COMPILER, "GL_DEBUG_SOURCE_SHADER_COMPILER"}, {GL_DEBUG_SOURCE_THIRD_PARTY, "GL_DEBUG_SOURCE_THIRD_PARTY"}, {GL_DEBUG_SOURCE_APPLICATION, "GL_DEBUG_SOURCE_APPLICATION"}, {GL_DEBUG_SOURCE_OTHER, "GL_DEBUG_SOURCE_OTHER"}}; static const GlDbg gldbgtype[] = {{GL_DEBUG_TYPE_ERROR, "GL_DEBUG_TYPE_ERROR"}, {GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"}, {GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"}, {GL_DEBUG_TYPE_PORTABILITY, "GL_DEBUG_TYPE_PORTABILITY"}, {GL_DEBUG_TYPE_PERFORMANCE, "GL_DEBUG_TYPE_PERFORMANCE"}, {GL_DEBUG_TYPE_OTHER, "GL_DEBUG_TYPE_OTHER"}}; static const GlDbg gldbgseverity[] = {{GL_DEBUG_SEVERITY_LOW, "GL_DEBUG_SEVERITY_LOW"}, {GL_DEBUG_SEVERITY_MEDIUM, "GL_DEBUG_SEVERITY_MEDIUM"}, {GL_DEBUG_SEVERITY_HIGH, "GL_DEBUG_SEVERITY_HIGH"}}; # if ANKI_OS == ANKI_OS_WINDOWS && ANKI_COMPILER != ANKI_COMPILER_MSVC __stdcall # endif void oglMessagesCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const GLvoid* userParam) { using namespace anki; const GlDbg* sourced = &gldbgsource[0]; while(source != sourced->token) { ++sourced; } const GlDbg* typed = &gldbgtype[0]; while(type != typed->token) { ++typed; } switch(severity) { case GL_DEBUG_SEVERITY_LOW: ANKI_GL_LOGI("GL: %s, %s: %s", sourced->str, typed->str, message); break; case GL_DEBUG_SEVERITY_MEDIUM: ANKI_GL_LOGW("GL: %s, %s: %s", sourced->str, typed->str, message); break; case GL_DEBUG_SEVERITY_HIGH: ANKI_GL_LOGE("GL: %s, %s: %s", sourced->str, typed->str, message); break; } } #endif void GlState::initMainThread(const ConfigSet& config) { m_registerMessages = config.getNumber("gr_debugContext"); } void GlState::initRenderThread() { // GL version GLint major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); m_version = major * 100 + minor * 10; // Vendor CString glstr = reinterpret_cast(glGetString(GL_VENDOR)); if(glstr.find("ARM") != CString::NPOS) { m_gpu = GpuVendor::ARM; } else if(glstr.find("NVIDIA") != CString::NPOS) { m_gpu = GpuVendor::NVIDIA; } else if(glstr.find("AMD") != CString::NPOS || glstr.find("ATI") != CString::NPOS) { m_gpu = GpuVendor::AMD; } else if(glstr.find("Intel") != CString::NPOS) { m_gpu = GpuVendor::INTEL; } ANKI_GL_LOGI("GPU vendor is %s", &GPU_VENDOR_STR[m_gpu][0]); // Enable debug messages #if ANKI_GL == ANKI_GL_DESKTOP if(m_registerMessages) { glDebugMessageCallback(oglMessagesCallback, nullptr); for(U s = 0; s < sizeof(gldbgsource) / sizeof(GlDbg); s++) { for(U t = 0; t < sizeof(gldbgtype) / sizeof(GlDbg); t++) { for(U sv = 0; sv < sizeof(gldbgseverity) / sizeof(GlDbg); sv++) { glDebugMessageControl(gldbgsource[s].token, gldbgtype[t].token, gldbgseverity[sv].token, 0, nullptr, GL_TRUE); } } } } #endif // Set some GL state glEnable(GL_PROGRAM_POINT_SIZE); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); glEnable(GL_CULL_FACE); glEnable(GL_SCISSOR_TEST); glScissor(0, 0, MAX_I16, MAX_I16); glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); // Create default VAO glGenVertexArrays(1, &m_defaultVao); glBindVertexArray(m_defaultVao); // Enable all attributes for(U i = 0; i < MAX_VERTEX_ATTRIBUTES; ++i) { glEnableVertexAttribArray(i); } I64 val; glGetInteger64v(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &val); m_uboAlignment = max(ANKI_SAFE_ALIGNMENT, val); // Some GPU have really low requirements glGetInteger64v(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &val); m_ssboAlignment = max(ANKI_SAFE_ALIGNMENT, val); // Some GPU have really low requirements glGetInteger64v(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &val); m_tboAlignment = max(ANKI_SAFE_ALIGNMENT, val); // Some GPU have really low requirements glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &val); m_uniBlockMaxSize = val; glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &val); m_storageBlockMaxSize = val; m_tboMaxRange = MAX_U32; // Texture buffer textures glGenTextures(MAX_DESCRIPTOR_SETS * MAX_TEXTURE_BUFFER_BINDINGS, &m_texBuffTextures[0][0]); for(U i = 0; i < MAX_DESCRIPTOR_SETS; ++i) { for(U j = 0; j < MAX_TEXTURE_BUFFER_BINDINGS; ++j) { U unit = MAX_TEXTURE_BINDINGS * MAX_DESCRIPTOR_SETS + MAX_TEXTURE_BUFFER_BINDINGS * i + j; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_BUFFER, m_texBuffTextures[i][j]); } } // Get extensions GLint extCount = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &extCount); while(extCount--) { const char* ext = reinterpret_cast(glGetStringi(GL_EXTENSIONS, extCount)); if(CString(ext) == "GL_ARB_shader_ballot") { ANKI_GL_LOGI("Found GL_ARB_shader_ballot"); m_extensions |= GlExtensions::ARB_SHADER_BALLOT; } } } void GlState::destroy() { glDeleteVertexArrays(1, &m_defaultVao); m_crntProg.reset(nullptr); } } // end namespace anki