inline void VL_glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length) { if (glProgramBinary) glProgramBinary(program, binaryFormat, binary, length); else VL_UNSUPPORTED_FUNC(); }
bool Shader::LoadFromBinary(const void* buffer, unsigned int size) { #if NAZARA_RENDERER_SAFE if (!glProgramBinary) { NazaraError("GL_ARB_get_program_binary not supported"); return false; } if (!buffer || size < sizeof(UInt64)) { NazaraError("Invalid buffer"); return false; } #endif Context::EnsureContext(); const UInt8* ptr = reinterpret_cast<const UInt8*>(buffer); // On récupère le format au début du binaire ///TODO: ByteStream ? GLenum binaryFormat = static_cast<GLenum>(*reinterpret_cast<const UInt64*>(&ptr[0])); ptr += sizeof(UInt64); glProgramBinary(m_program, binaryFormat, ptr, size - sizeof(UInt64)); return PostLinkage(); }
int JNICALL Java_com_gomdev_gles_GLESShader_nLoadProgramBinary (JNIEnv * env, jobject obj, jint program, jint binaryFormat, jstring str) { char* fileName = (char*)env->GetStringUTFChars(str, NULL); #ifdef DEBUG dump("before"); #endif if(fileName != NULL) { BinaryInfo* binaryInfo = find(fileName); if(binaryInfo != NULL) { #ifdef DEBUG LOGI("Load() cache hit!!! - %s", fileName); #endif removeBinaryFromList(binaryInfo, false); add(binaryInfo); } else { #ifdef DEBUG LOGI("Load() cache miss!! - %s", fileName); #endif binaryInfo = readFile(fileName); if(binaryInfo == NULL) { LOGE("Load() binaryInfo is NULL"); return 0; } add(binaryInfo); } // if (glProgramBinaryOES == NULL) { // glProgramBinaryOES = (PFNGLPROGRAMBINARYOESPROC) eglGetProcAddress("glProgramBinaryOES"); // } glProgramBinary(program, sBinaryFormat, binaryInfo->binary, binaryInfo->length); GLint success; glGetProgramiv(program, GL_LINK_STATUS, &success); env->ReleaseStringUTFChars(str, fileName); if (!success) { LOGE("nLoadProgramBinary() link fail"); return 0; } #ifdef DEBUG dump("after"); #endif return 1; } else { LOGE("nLoadProgramBinary() fileName is NULL"); return 0; } }
void gfx::ShaderProgram::LoadProgramBinary(const rString& filename) { std::stringstream ss; ss << filename; ss << ".bin"; FILE* fp = fopen(ss.str().c_str(), "rb"); //header ShaderProgramBinary header; fseek(fp, 0, SEEK_SET); fread(&header, sizeof(ShaderProgramBinary),1,fp); //shader prog GLbyte* binary = new GLbyte[header.Size]; fseek(fp, sizeof(ShaderProgramBinary), SEEK_SET); fread(binary, header.Size, 1, fp); fclose(fp); GLint formats = 0; glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats); GLint *binaryFormats = new GLint[formats]; glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, binaryFormats); m_Handle = glCreateProgram(); glProgramBinary(m_Handle,(GLenum)(*binaryFormats),binary,header.Size); GLint succes; glGetProgramiv(m_Handle, GL_LINK_STATUS, &succes); if(!succes) { Logger::Log("Failed to load shader program binary", "ShaderProgram", LogSeverity::ERROR_MSG); } delete [] binary; delete [] binaryFormats; }
void GLSLProgram::getMicrocodeFromCache(uint32 id) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(id); cacheMicrocode->seek(0); // Turns out we need this param when loading. GLenum binaryFormat = 0; cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); // Get size of binary. GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum)); // Load binary. OGRE_CHECK_GL_ERROR(glProgramBinary(mGLProgramHandle, binaryFormat, cacheMicrocode->getCurrentPtr(), binaryLength)); GLint success = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_LINK_STATUS, &success)); if(success) { mLinked = true; return; } logObjectInfo("could not load from cache "+getCombinedName(), mGLProgramHandle); // Something must have changed since the program binaries // were cached away. Fallback to source shader loading path, // and then retrieve and cache new program binaries once again. compileAndLink(); }
static bool fgm_program_from_binary(GLuint program, fe_iov *binfile) { #ifndef FE_TARGET_EMSCRIPTEN GLsizei binlen = binfile->len - HEADER_SIZE; char *bin = ((char*)binfile->base) + HEADER_SIZE; GLenum binfmt = fe_hw_swap32_net_to_host( *(GLenum*)(((char*)binfile->base)+sizeof(fe_timestamp)) ); glProgramBinary(program, binfmt, bin, binlen); // >= ES 3.0 GLint err, status; err = glGetError(); if(err != GL_INVALID_ENUM) { glGetProgramiv(program, GL_LINK_STATUS, &status); if(status == GL_TRUE) { fe_logv(TAG, "Successfully reused the program binary.\n"); return true; } } fe_logw(TAG, "Could not reuse the program binary : \n"); if(err != GL_INVALID_ENUM) { fe_gl_log_program_info(program, fe_logw); fe_logw(TAG, "\n"); } else fe_logw(TAG, "Either 0x%x is an unrecognized binary format, " "or the OpenGL implementation just rejected it. " "See also the context's settings.\n", binfmt); return false; #else /* FE_TARGET_EMSCRIPTEN */ return true; #endif }
bool ProgramBinaryImplementation_GetProgramBinaryARB::updateProgramLinkSource(const Program * program) const { if (program->m_binary) { glProgramBinary(program->id(), program->m_binary->format(), program->m_binary->data(), program->m_binary->length()); return true; } return program->compileAttachedShaders(); }
/* * * Core in: * OpenGL : 4.1 * OpenGLES : 3.1 */ void rglProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) { #if !defined(HAVE_OPENGLES) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES_3_1) glProgramBinary(program, binaryFormat, binary, length); #else printf("WARNING! Not implemented.\n"); #endif }
void ProgramShaderCache::ProgramShaderCacheInserter::Read ( const SHADERUID& key, const u8* value, u32 value_size ) { const u8 *binary = value+sizeof(GLenum); GLenum *prog_format = (GLenum*)value; GLint binary_size = value_size-sizeof(GLenum); PCacheEntry entry; entry.in_cache = 1; entry.shader.glprogid = glCreateProgram(); glProgramBinary(entry.shader.glprogid, *prog_format, binary, binary_size); GLint success; glGetProgramiv(entry.shader.glprogid, GL_LINK_STATUS, &success); if (success) { pshaders[key] = entry; entry.shader.SetProgramVariables(); } else glDeleteProgram(entry.shader.glprogid); }
//----------------------------------------------------------------------- void GLSLProgramCommon::getMicrocodeFromCache(void) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(getCombinedName()); // add to the microcode to the cache String name; name = getCombinedName(); // turns out we need this param when loading GLenum binaryFormat = 0; cacheMicrocode->seek(0); // get size of binary cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum)); // load binary OGRE_CHECK_GL_ERROR(glProgramBinary(mGLProgramHandle, binaryFormat, cacheMicrocode->getPtr(), binaryLength)); GLint success = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_LINK_STATUS, &success)); if (!success) { // // Something must have changed since the program binaries // were cached away. Fallback to source shader loading path, // and then retrieve and cache new program binaries once again. // compileAndLink(); } }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_string& hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); bool supported = false; for (auto supported_fmt : GL_binary_formats) { if ((GLenum)supported_fmt == binary_format) { supported = true; break; } } if (!supported) { // This can happen in case an implementation stops supporting a particular binary format nprintf(("ShaderCache", "Unsupported binary format %d encountered in shader cache.\n", binary_format)); return false; } auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }
void GLSLSeparableProgram::loadIndividualProgram(GLSLShader *program) { if (program && !program->isLinked()) { GLint linkStatus = 0; String programName = program->getName(); GLuint programHandle = program->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_SEPARABLE, GL_TRUE)); //if (GpuProgramManager::getSingleton().getSaveMicrocodesToCache()) OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE)); // Use precompiled program if possible. bool microcodeAvailableInCache = GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(programName); if (microcodeAvailableInCache) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(programName); cacheMicrocode->seek(0); GLenum binaryFormat = 0; cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); GLint binaryLength = cacheMicrocode->size() - sizeof(GLenum); OGRE_CHECK_GL_ERROR(glProgramBinary(programHandle, binaryFormat, cacheMicrocode->getPtr() + sizeof(GLenum), binaryLength)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if (!linkStatus) logObjectInfo("Could not use cached binary " + programName, programHandle); } // Compilation needed if precompiled program is // unavailable or failed to link. if (!linkStatus) { try { program->compile(true); } catch (Exception& e) { LogManager::getSingleton().stream() << e.getDescription(); mTriedToLinkAndFailed = true; return; } program->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); // Binary cache needs an update. microcodeAvailableInCache = false; } program->setLinked(linkStatus); mLinked = linkStatus; mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL program result : "), programHandle ); if (program->getType() == GPT_VERTEX_PROGRAM) setSkeletalAnimationIncluded(program->isSkeletalAnimationIncluded()); // Add the microcode to the cache. if (!microcodeAvailableInCache && mLinked && GpuProgramManager::getSingleton().getSaveMicrocodesToCache() ) { // Get buffer size. GLint binaryLength = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); // Create microcode. GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode((unsigned long)binaryLength + sizeof(GLenum)); // Get binary. OGRE_CHECK_GL_ERROR(glGetProgramBinary(programHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum))); // std::vector<uchar> buffer(binaryLength); // GLenum format(0); // OGRE_CHECK_GL_ERROR(glGetProgramBinary(programHandle, binaryLength, NULL, &format, &buffer[0])); // GLenum binaryFormat = 0; // std::vector<uchar> binaryData(binaryLength); // newMicrocode->read(&binaryFormat, sizeof(GLenum)); // newMicrocode->read(&binaryData[0], binaryLength); GpuProgramManager::getSingleton().addMicrocodeToCache(programName, newMicrocode); } } }
/* char const * retrieveBinaryCache(char const* Path) { return 0; } enum { PROGRAM_SEPARATE_BIT = (1 << 0), PROGRAM_CACHE_BIT = (1 << 1), PROGRAM_BYPASS_CACHE_BIT = (1 << 2) }; bool hasProgramBinarySPIRVSupport() { GLint NumProgramBinaryFormats(0); glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &NumProgramBinaryFormats); std::vector<GLint> ProgramBinaryFormats(static_cast<std::size_t>(NumProgramBinaryFormats)); glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, &ProgramBinaryFormats[0]); for(std::size_t FormatIndex = 0; FormatIndex < ProgramBinaryFormats.size(); ++FormatIndex) { if(ProgramBinaryFormats[FormatIndex] == GL_PROGRAM_BINARY_SPIR_V) return true; } return false; } bool isProgramBinarySPIRV(GLubyte * binary) { return *reinterpret_cast<GLuint*>(binary) == 0x07230203; } GLuint createProgram(char const* Path, GLbitfield Flags) { assert(HasProgramBinarySPIRVSupport()); assert(Path); if(!(Flags & PROGRAM_BYPASS_CACHE_BIT)) Path = retrieveBinaryCache(Path); GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(!loadBinary(Path, Format, Data, Size)) return 0; assert((isProgramBinarySPIRV(&Data[0]) && Format == GL_PROGRAM_BINARY_SPIR_V) || Format != GL_PROGRAM_BINARY_SPIR_V); GLuint ProgramName = glCreateProgram(); glProgramParameteri(ProgramName, GL_PROGRAM_SEPARABLE, Flags & PROGRAM_SEPARATE_BIT ? GL_TRUE : GL_FALSE); glProgramParameteri(ProgramName, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, Flags & PROGRAM_CACHE_BIT ? GL_TRUE : GL_FALSE); glProgramBinary(ProgramName, Format, &Data[0], Size); glLinkProgram(ProgramName); return ProgramName; } */ bool initProgram() { bool Validated = true; GLint Success = 0; glGenProgramPipelines(1, &PipelineName); ProgramName[program::VERT] = glCreateProgram(); glProgramParameteri(ProgramName[program::VERT], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::VERT], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); ProgramName[program::GEOM] = glCreateProgram(); glProgramParameteri(ProgramName[program::GEOM], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::GEOM], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); ProgramName[program::FRAG] = glCreateProgram(); glProgramParameteri(ProgramName[program::FRAG], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::FRAG], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(loadBinary(getDataDirectory() + VERT_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::VERT], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::VERT], GL_LINK_STATUS, &Success); Validated = Validated && Success == GL_TRUE; } } { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(loadBinary(getDataDirectory() + GEOM_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::GEOM], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::GEOM], GL_LINK_STATUS, &Success); Validated = Validated && Success == GL_TRUE; } } { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(loadBinary(getDataDirectory() + FRAG_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::FRAG], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::FRAG], GL_LINK_STATUS, &Success); Validated = Validated && Success == GL_TRUE; } } compiler Compiler; if(Validated && !Success) { GLuint VertShaderName = Compiler.create(GL_VERTEX_SHADER, getDataDirectory() + VERT_SHADER_SOURCE); glAttachShader(ProgramName[program::VERT], VertShaderName); glLinkProgram(ProgramName[program::VERT]); } if(Validated && !Success) { GLuint GeomShaderName = Compiler.create(GL_GEOMETRY_SHADER, getDataDirectory() + GEOM_SHADER_SOURCE); glAttachShader(ProgramName[program::GEOM], GeomShaderName); glLinkProgram(ProgramName[program::GEOM]); } if(Validated && !Success) { GLuint FragShaderName = Compiler.create(GL_FRAGMENT_SHADER, getDataDirectory() + FRAG_SHADER_SOURCE); glAttachShader(ProgramName[program::FRAG], FragShaderName); glLinkProgram(ProgramName[program::FRAG]); } if(Validated) { glUseProgramStages(PipelineName, GL_VERTEX_SHADER_BIT, ProgramName[program::VERT]); glUseProgramStages(PipelineName, GL_GEOMETRY_SHADER_BIT, ProgramName[program::GEOM]); glUseProgramStages(PipelineName, GL_FRAGMENT_SHADER_BIT, ProgramName[program::FRAG]); Validated = Validated && this->checkError("initProgram - stage"); } if(Validated) { Validated = Validated && Compiler.checkProgram(ProgramName[program::VERT]); Validated = Validated && Compiler.checkProgram(ProgramName[program::GEOM]); Validated = Validated && Compiler.checkProgram(ProgramName[program::FRAG]); } if(Validated) { UniformMVP = glGetUniformLocation(ProgramName[program::VERT], "MVP"); UniformDiffuse = glGetUniformLocation(ProgramName[program::FRAG], "Diffuse"); } saveProgram(ProgramName[program::VERT], getDataDirectory() + VERT_PROGRAM_BINARY); saveProgram(ProgramName[program::GEOM], getDataDirectory() + GEOM_PROGRAM_BINARY); saveProgram(ProgramName[program::FRAG], getDataDirectory() + FRAG_PROGRAM_BINARY); return Validated && this->checkError("initProgram"); }
void ShaderProgram::setBinary(GLenum format, const void* binary, GLsizei length) { if(ext::programBinary()) glCheck(glProgramBinary(program_, format, binary, length)); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL41_nglProgramBinary(JNIEnv *env, jclass clazz, jint program, jint binaryFormat, jlong binary, jint length, jlong function_pointer) { const GLvoid *binary_address = (const GLvoid *)(intptr_t)binary; glProgramBinaryPROC glProgramBinary = (glProgramBinaryPROC)((intptr_t)function_pointer); glProgramBinary(program, binaryFormat, binary_address, length); }
bool initProgram() { bool Validated = true; GLint Success = 0; glGenProgramPipelines(1, &PipelineName); // Vertex program ProgramName[program::VERT] = glCreateProgram(); glProgramParameteri(ProgramName[program::VERT], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::VERT], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(glf::loadBinary(glf::DATA_DIRECTORY + VERT_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::VERT], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::VERT], GL_LINK_STATUS, &Success); } } // Create program if(Validated && !Success) { GLuint VertShaderName = glf::createShader(GL_VERTEX_SHADER, glf::DATA_DIRECTORY + VERT_SHADER_SOURCE); glAttachShader(ProgramName[program::VERT], VertShaderName); glDeleteShader(VertShaderName); glLinkProgram(ProgramName[program::VERT]); Validated = Validated && glf::checkProgram(ProgramName[program::VERT]); } // Geometry program ProgramName[program::GEOM] = glCreateProgram(); glProgramParameteri(ProgramName[program::GEOM], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::GEOM], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(glf::loadBinary(glf::DATA_DIRECTORY + GEOM_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::GEOM], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::GEOM], GL_LINK_STATUS, &Success); } } // Create program if(Validated && !Success) { GLuint GeomShaderName = glf::createShader(GL_GEOMETRY_SHADER, glf::DATA_DIRECTORY + GEOM_SHADER_SOURCE); glAttachShader(ProgramName[program::GEOM], GeomShaderName); glDeleteShader(GeomShaderName); glLinkProgram(ProgramName[program::GEOM]); Validated = Validated && glf::checkProgram(ProgramName[program::GEOM]); } // Fragment program ProgramName[program::FRAG] = glCreateProgram(); glProgramParameteri(ProgramName[program::FRAG], GL_PROGRAM_SEPARABLE, GL_TRUE); glProgramParameteri(ProgramName[program::FRAG], GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); { GLenum Format = 0; GLint Size = 0; std::vector<glm::byte> Data; if(glf::loadBinary(glf::DATA_DIRECTORY + FRAG_PROGRAM_BINARY, Format, Data, Size)) { glProgramBinary(ProgramName[program::FRAG], Format, &Data[0], Size); glGetProgramiv(ProgramName[program::FRAG], GL_LINK_STATUS, &Success); } } // Create program if(Validated && !Success) { GLuint FragShaderName = glf::createShader(GL_FRAGMENT_SHADER, glf::DATA_DIRECTORY + FRAG_SHADER_SOURCE); glAttachShader(ProgramName[program::FRAG], FragShaderName); glDeleteShader(FragShaderName); glLinkProgram(ProgramName[program::FRAG]); Validated = Validated && glf::checkProgram(ProgramName[program::FRAG]); } // Pipeline program if(Validated) { glUseProgramStages(PipelineName, GL_VERTEX_SHADER_BIT, ProgramName[program::VERT]); glUseProgramStages(PipelineName, GL_GEOMETRY_SHADER_BIT, ProgramName[program::GEOM]); glUseProgramStages(PipelineName, GL_FRAGMENT_SHADER_BIT, ProgramName[program::FRAG]); Validated = Validated && glf::checkError("initProgram - stage"); } // Get variables locations if(Validated) { UniformMVP = glGetUniformLocation(ProgramName[program::VERT], "MVP"); UniformDiffuse = glGetUniformLocation(ProgramName[program::FRAG], "Diffuse"); } return Validated && glf::checkError("initProgram"); }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, SCP_string hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }
/*!**************************************************************************** @Function loadBinaryProgram @Return bool True if load succeeded. @Description This function takes as input the ID of a shader program object which should have been created prior to calling this function, as well as a filename to load the binary program from. The function will load in a file storing the binary shader program, and the enum value determining its format. It will then load the binary into memory. @Note: This function is not able to check if the shaders have changed. If you change the shaders then the file this saves out either needs to be deleted or a new file used. ******************************************************************************/ bool OGLES3BinaryShader::loadBinaryProgram(const char* Filename, GLuint &ProgramObjectID) { // Open the file. FILE* infile = fopen(Filename, "rb"); // File open failed, either doesn't exist or is empty. if (!infile) return false; // Find initialise the shader binary. fseek(infile, 0, SEEK_END); GLsizei length = (GLint)ftell(infile)-sizeof(GLenum); if (!length) { fclose(infile); return false; // File appears empty. } // Allocate a buffer large enough to store the binary program. GLvoid* ShaderBinary = (GLvoid*)malloc(length); // Read in the binary format GLenum format=0; fseek(infile, 0, SEEK_SET); fread(&format, sizeof(GLenum), 1, infile); // Read in the program binary. fread(ShaderBinary, length, 1, infile); fclose(infile); // Create an empty shader program ProgramObjectID = glCreateProgram(); // Load the binary into the program object -- no need to link! glProgramBinary(ProgramObjectID, format, ShaderBinary, length); // Delete the binary program from memory. free(ShaderBinary); // Check that the program was loaded correctly, uses the same checks as when linking with a standard shader. GLint loaded; glGetProgramiv(ProgramObjectID, GL_LINK_STATUS, &loaded); if(!loaded) { // Something must have changed. Need to recompile shaders. int i32InfoLogLength, i32CharsWritten; glGetProgramiv(ProgramObjectID, GL_INFO_LOG_LENGTH, &i32InfoLogLength); char* pszInfoLog = new char[i32InfoLogLength]; glGetProgramInfoLog(ProgramObjectID, i32InfoLogLength, &i32CharsWritten, pszInfoLog); char* pszMsg = new char[i32InfoLogLength+256]; strcpy(pszMsg, "Failed to load binary program: "); strcat(pszMsg, pszInfoLog); PVRShellSet(prefExitMessage, pszMsg); delete [] pszMsg; delete [] pszInfoLog; return false; } return true; }