Added ShaderProgram::LoadFromBinary
Former-commit-id: fdc6b06173954bb9c382ed73e7cd9bb0c5fd01a5
This commit is contained in:
parent
ae53b01ca1
commit
059ea21b41
|
|
@ -58,6 +58,8 @@ class NAZARA_API NzShaderProgram : public NzResource, NzNonCopyable
|
|||
bool IsLoaded(nzShaderType type) const;
|
||||
bool IsValid() const;
|
||||
|
||||
bool LoadFromBinary(const void* buffer, unsigned int size);
|
||||
bool LoadFromBinary(const NzByteArray& byteArray);
|
||||
bool LoadShader(nzShaderType type, const NzString& source);
|
||||
bool LoadShaderFromFile(nzShaderType type, const NzString& source);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class NzAbstractShaderProgram
|
|||
virtual bool IsBinaryRetrievable() const = 0;
|
||||
virtual bool IsLoaded(nzShaderType type) const = 0;
|
||||
|
||||
virtual bool LoadFromBinary(const void* buffer, unsigned int size) = 0;
|
||||
virtual bool LoadShader(nzShaderType type, const NzString& source) = 0;
|
||||
|
||||
virtual bool SendBoolean(int location, bool value) = 0;
|
||||
|
|
|
|||
|
|
@ -48,72 +48,11 @@ bool NzGLSLProgram::Compile()
|
|||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
m_idCache.clear();
|
||||
m_textures.clear();
|
||||
|
||||
if (NzOpenGL::IsSupported(nzOpenGLExtension_GetProgramBinary))
|
||||
glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
PreLinkage();
|
||||
|
||||
glLinkProgram(m_program);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
static NzString successStr("Linkage successful");
|
||||
m_log = successStr;
|
||||
|
||||
// Pour éviter de se tromper entre le nom et la constante
|
||||
#define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = GetUniformLocation(#name)
|
||||
|
||||
CacheUniform(CameraPosition);
|
||||
CacheUniform(InvTargetSize);
|
||||
CacheUniform(MaterialAlphaMap);
|
||||
CacheUniform(MaterialAlphaThreshold);
|
||||
CacheUniform(MaterialAmbient);
|
||||
CacheUniform(MaterialDiffuse);
|
||||
CacheUniform(MaterialDiffuseMap);
|
||||
CacheUniform(MaterialEmissiveMap);
|
||||
CacheUniform(MaterialHeightMap);
|
||||
CacheUniform(MaterialNormalMap);
|
||||
CacheUniform(MaterialShininess);
|
||||
CacheUniform(MaterialSpecular);
|
||||
CacheUniform(MaterialSpecularMap);
|
||||
CacheUniform(ProjMatrix);
|
||||
CacheUniform(SceneAmbient);
|
||||
CacheUniform(TargetSize);
|
||||
CacheUniform(ViewMatrix);
|
||||
CacheUniform(ViewProjMatrix);
|
||||
CacheUniform(WorldMatrix);
|
||||
CacheUniform(WorldViewMatrix);
|
||||
CacheUniform(WorldViewProjMatrix);
|
||||
|
||||
#undef CacheUniform
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
GLint length = 0;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Clear(true);
|
||||
m_log.Reserve(length+15-2); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Linkage error: ");
|
||||
m_log.Resize(length+15-2); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetProgramInfoLog(m_program, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Linkage failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
return PostLinkage();
|
||||
}
|
||||
|
||||
bool NzGLSLProgram::Create()
|
||||
|
|
@ -160,6 +99,9 @@ bool NzGLSLProgram::Create()
|
|||
for (int i = 0; i <= nzShaderType_Max; ++i)
|
||||
m_shaders[i] = 0;
|
||||
|
||||
if (NzOpenGL::IsSupported(nzOpenGLExtension_GetProgramBinary))
|
||||
glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -179,21 +121,20 @@ NzByteArray NzGLSLProgram::GetBinary() const
|
|||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
GLint binaryLength;
|
||||
GLint binaryLength = 0;
|
||||
glGetProgramiv(m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
|
||||
|
||||
if (binaryLength > 0)
|
||||
{
|
||||
byteArray.Resize(sizeof(nzUInt64) + binaryLength);
|
||||
|
||||
nzUInt8* ptr = byteArray.GetBuffer();
|
||||
nzUInt8* buffer = byteArray.GetBuffer();
|
||||
|
||||
GLenum binaryFormat;
|
||||
glGetProgramBinary(m_program, binaryLength, nullptr, &binaryFormat, &ptr[sizeof(nzUInt64)]);
|
||||
glGetProgramBinary(m_program, binaryLength, nullptr, &binaryFormat, &buffer[sizeof(nzUInt64)]);
|
||||
|
||||
// On stocke le format au début du binaire
|
||||
nzUInt64* format = reinterpret_cast<nzUInt64*>(&ptr[0]);
|
||||
*format = binaryFormat;
|
||||
*reinterpret_cast<nzUInt64*>(&buffer[0]) = binaryFormat;
|
||||
}
|
||||
|
||||
return byteArray;
|
||||
|
|
@ -211,11 +152,11 @@ nzShaderLanguage NzGLSLProgram::GetLanguage() const
|
|||
|
||||
NzString NzGLSLProgram::GetSourceCode(nzShaderType type) const
|
||||
{
|
||||
NzString source;
|
||||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
GLint length;
|
||||
NzString source;
|
||||
|
||||
GLint length = 0;
|
||||
glGetShaderiv(m_shaders[type], GL_SHADER_SOURCE_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
|
|
@ -258,6 +199,32 @@ bool NzGLSLProgram::IsLoaded(nzShaderType type) const
|
|||
return m_shaders[type] != 0;
|
||||
}
|
||||
|
||||
bool NzGLSLProgram::LoadFromBinary(const void* buffer, unsigned int size)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!glProgramBinary)
|
||||
{
|
||||
NazaraError("GL_ARB_get_program_binary not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
const nzUInt8* ptr = reinterpret_cast<const nzUInt8*>(buffer);
|
||||
|
||||
// On récupère le format au début du binaire
|
||||
///TODO: ByteStream ?
|
||||
GLenum binaryFormat = static_cast<GLenum>(*reinterpret_cast<const nzUInt64*>(&ptr[0]));
|
||||
ptr += sizeof(nzUInt64);
|
||||
|
||||
PreLinkage();
|
||||
|
||||
glProgramBinary(m_program, binaryFormat, ptr, size-sizeof(nzUInt64));
|
||||
|
||||
return PostLinkage();
|
||||
}
|
||||
|
||||
bool NzGLSLProgram::LoadShader(nzShaderType type, const NzString& source)
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
|
@ -615,3 +582,72 @@ void NzGLSLProgram::OnResourceReleased(const NzResource* resource, int index)
|
|||
|
||||
resource->RemoveResourceListener(this);
|
||||
}
|
||||
|
||||
void NzGLSLProgram::PreLinkage()
|
||||
{
|
||||
m_idCache.clear();
|
||||
m_textures.clear();
|
||||
}
|
||||
|
||||
bool NzGLSLProgram::PostLinkage()
|
||||
{
|
||||
// On suppose qu'un contexte OpenGL est actif à l'appel de cette fonction
|
||||
GLint success;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
static NzString successStr("Linkage successful");
|
||||
m_log = successStr;
|
||||
|
||||
// Pour éviter de se tromper entre le nom et la constante
|
||||
#define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = GetUniformLocation(#name)
|
||||
|
||||
CacheUniform(CameraPosition);
|
||||
CacheUniform(InvTargetSize);
|
||||
CacheUniform(MaterialAlphaMap);
|
||||
CacheUniform(MaterialAlphaThreshold);
|
||||
CacheUniform(MaterialAmbient);
|
||||
CacheUniform(MaterialDiffuse);
|
||||
CacheUniform(MaterialDiffuseMap);
|
||||
CacheUniform(MaterialEmissiveMap);
|
||||
CacheUniform(MaterialHeightMap);
|
||||
CacheUniform(MaterialNormalMap);
|
||||
CacheUniform(MaterialShininess);
|
||||
CacheUniform(MaterialSpecular);
|
||||
CacheUniform(MaterialSpecularMap);
|
||||
CacheUniform(ProjMatrix);
|
||||
CacheUniform(SceneAmbient);
|
||||
CacheUniform(TargetSize);
|
||||
CacheUniform(ViewMatrix);
|
||||
CacheUniform(ViewProjMatrix);
|
||||
CacheUniform(WorldMatrix);
|
||||
CacheUniform(WorldViewMatrix);
|
||||
CacheUniform(WorldViewProjMatrix);
|
||||
|
||||
#undef CacheUniform
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
GLint length = 0;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Clear(true);
|
||||
m_log.Reserve(length+15-2); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Linkage error: ");
|
||||
m_log.Resize(length+15-2); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetProgramInfoLog(m_program, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Linkage failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class NzGLSLProgram : public NzAbstractShaderProgram, NzResourceListener
|
|||
bool IsBinaryRetrievable() const;
|
||||
bool IsLoaded(nzShaderType type) const;
|
||||
|
||||
bool LoadFromBinary(const void* buffer, unsigned int size);
|
||||
bool LoadShader(nzShaderType type, const NzString& source);
|
||||
|
||||
bool SendBoolean(int location, bool value);
|
||||
|
|
@ -62,6 +63,8 @@ class NzGLSLProgram : public NzAbstractShaderProgram, NzResourceListener
|
|||
void OnResourceCreated(const NzResource* resource, int index) override;
|
||||
void OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||
void PreLinkage();
|
||||
bool PostLinkage();
|
||||
|
||||
struct TextureSlot
|
||||
{
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ bool NzShaderProgram::Compile()
|
|||
|
||||
void NzShaderProgram::Destroy()
|
||||
{
|
||||
m_compiled = false;
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
NotifyDestroy();
|
||||
|
|
@ -128,7 +130,19 @@ NzByteArray NzShaderProgram::GetBinary() const
|
|||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetBinary();
|
||||
NzByteArray binary(m_impl->GetBinary());
|
||||
if (binary.IsEmpty())
|
||||
return NzByteArray();
|
||||
|
||||
NzByteArray byteArray;
|
||||
|
||||
///TODO: ByteStream
|
||||
|
||||
nzUInt32 language = static_cast<nzUInt32>(m_impl->GetLanguage());
|
||||
byteArray.Append(&language, sizeof(nzUInt32));
|
||||
byteArray.Append(binary);
|
||||
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
nzUInt32 NzShaderProgram::GetFlags() const
|
||||
|
|
@ -286,6 +300,43 @@ bool NzShaderProgram::IsValid() const
|
|||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzShaderProgram::LoadFromBinary(const void* buffer, unsigned int size)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (size <= sizeof(nzUInt32))
|
||||
{
|
||||
NazaraError("Invalid binary");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
///TODO: ByteStream
|
||||
const nzUInt8* ptr = static_cast<const nzUInt8*>(buffer);
|
||||
|
||||
nzShaderLanguage language = static_cast<nzShaderLanguage>(*reinterpret_cast<const nzUInt32*>(&ptr[0]));
|
||||
ptr += sizeof(nzUInt32);
|
||||
|
||||
if (!Create(language))
|
||||
{
|
||||
NazaraError("Failed to create shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->LoadFromBinary(ptr, size-sizeof(nzUInt32)))
|
||||
{
|
||||
m_compiled = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzShaderProgram::LoadFromBinary(const NzByteArray& byteArray)
|
||||
{
|
||||
return LoadFromBinary(byteArray.GetConstBuffer(), byteArray.GetSize());
|
||||
}
|
||||
|
||||
bool NzShaderProgram::LoadShader(nzShaderType type, const NzString& source)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
|
|||
Loading…
Reference in New Issue