mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 20:56:52 +02:00
Fix procedural rendering with custom uniforms
This commit is contained in:
parent
eca803503c
commit
df031b5d93
7 changed files with 54 additions and 55 deletions
|
@ -110,6 +110,20 @@ Uniforms Uniform::load(GLuint glprogram, const std::vector<const char*>& cnames)
|
||||||
return load(glprogram, indices);
|
return load(glprogram, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename C, typename F>
|
||||||
|
std::vector<const char*> toCNames(const C& container, F lambda) {
|
||||||
|
std::vector<const char*> result;
|
||||||
|
result.reserve(container.size());
|
||||||
|
std::transform(container.begin(), container.end(), std::back_inserter(result), lambda);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uniforms Uniform::load(GLuint glprogram, const std::vector<std::string>& names) {
|
||||||
|
auto cnames = toCNames(names, [](const std::string& name) { return name.c_str(); });
|
||||||
|
return load(glprogram, cnames);
|
||||||
|
}
|
||||||
|
|
||||||
void UniformBlock::load(GLuint glprogram, int index) {
|
void UniformBlock::load(GLuint glprogram, int index) {
|
||||||
this->index = index;
|
this->index = index;
|
||||||
GLint length = 0;
|
GLint length = 0;
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct Uniform : public ShaderBinding {
|
||||||
static Vector load(GLuint glprogram);
|
static Vector load(GLuint glprogram);
|
||||||
static Vector load(GLuint glprogram, const std::vector<GLuint>& indices);
|
static Vector load(GLuint glprogram, const std::vector<GLuint>& indices);
|
||||||
static Vector load(GLuint glprogram, const std::vector<const char*>& names);
|
static Vector load(GLuint glprogram, const std::vector<const char*>& names);
|
||||||
|
static Vector load(GLuint glprogram, const std::vector<std::string>& names);
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
static Vector loadByName(GLuint glprogram, const C& names) {
|
static Vector loadByName(GLuint glprogram, const C& names) {
|
||||||
|
|
|
@ -260,7 +260,7 @@ public:
|
||||||
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual GLint getRealUniformLocation(GLint location) const { return location; }
|
virtual GLint getRealUniformLocation(GLint location) const;
|
||||||
|
|
||||||
void recycle() const override;
|
void recycle() const override;
|
||||||
|
|
||||||
|
@ -494,7 +494,7 @@ protected:
|
||||||
} _pipeline;
|
} _pipeline;
|
||||||
|
|
||||||
// Backend dependant compilation of the shader
|
// Backend dependant compilation of the shader
|
||||||
virtual void postLinkProgram(ShaderObject& programObject, const Shader& program) const {}
|
virtual void postLinkProgram(ShaderObject& programObject, const Shader& program) const;
|
||||||
virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
|
virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
|
||||||
virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
|
virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
|
||||||
virtual std::string getBackendShaderHeader() const = 0;
|
virtual std::string getBackendShaderHeader() const = 0;
|
||||||
|
|
|
@ -244,6 +244,42 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const GLint INVALID_UNIFORM_INDEX = -1;
|
||||||
|
|
||||||
|
GLint GLBackend::getRealUniformLocation(GLint location) const {
|
||||||
|
auto& shader = _pipeline._programShader->_shaderObjects[(GLShader::Version)isStereo()];
|
||||||
|
auto itr = shader.uniformRemap.find(location);
|
||||||
|
if (itr == shader.uniformRemap.end()) {
|
||||||
|
// This shouldn't happen, because we use reflection to determine all the possible
|
||||||
|
// uniforms. If someone is requesting a uniform that isn't in the remapping structure
|
||||||
|
// that's a bug from the calling code, because it means that location wasn't in the
|
||||||
|
// reflection
|
||||||
|
qWarning() << "Unexpected location requested for shader";
|
||||||
|
return INVALID_UNIFORM_INDEX;
|
||||||
|
}
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const {
|
||||||
|
const auto& glprogram = shaderObject.glprogram;
|
||||||
|
const auto& expectedUniforms = program.getUniforms();
|
||||||
|
const auto expectedLocationsByName = expectedUniforms.getLocationsByName();
|
||||||
|
const auto uniforms = ::gl::Uniform::load(glprogram, expectedUniforms.getNames());
|
||||||
|
auto& uniformRemap = shaderObject.uniformRemap;
|
||||||
|
|
||||||
|
// Pre-initialize all the uniforms with an invalid location
|
||||||
|
for (const auto& entry : expectedLocationsByName) {
|
||||||
|
uniformRemap[entry.second] = INVALID_UNIFORM_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now load up all the actual found uniform location
|
||||||
|
for (const auto& uniform : uniforms) {
|
||||||
|
const auto& name = uniform.name;
|
||||||
|
const auto& expectedLocation = expectedLocationsByName.at(name);
|
||||||
|
const auto& location = uniform.binding;
|
||||||
|
uniformRemap[expectedLocation] = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GLBackend::ElementResource GLBackend::getFormatFromGLUniform(GLenum gltype) {
|
GLBackend::ElementResource GLBackend::getFormatFromGLUniform(GLenum gltype) {
|
||||||
switch (gltype) {
|
switch (gltype) {
|
||||||
|
|
|
@ -17,10 +17,8 @@ struct ShaderObject {
|
||||||
GLuint glshader { 0 };
|
GLuint glshader { 0 };
|
||||||
GLuint glprogram { 0 };
|
GLuint glprogram { 0 };
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
using LocationMap = std::unordered_map <GLuint, GLuint>;
|
using LocationMap = std::unordered_map <GLuint, GLuint>;
|
||||||
LocationMap uniformRemap;
|
LocationMap uniformRemap;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GLShader : public GPUObject {
|
class GLShader : public GPUObject {
|
||||||
|
|
|
@ -173,7 +173,6 @@ protected:
|
||||||
std::string getBackendShaderHeader() const override;
|
std::string getBackendShaderHeader() const override;
|
||||||
|
|
||||||
void postLinkProgram(ShaderObject& programObject, const Shader& program) const override;
|
void postLinkProgram(ShaderObject& programObject, const Shader& program) const override;
|
||||||
GLint getRealUniformLocation(GLint location) const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -22,46 +22,8 @@ std::string GL41Backend::getBackendShaderHeader() const {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename F>
|
|
||||||
std::vector<const char*> toCNames(const C& container, F lambda) {
|
|
||||||
std::vector<const char*> result;
|
|
||||||
result.reserve(container.size());
|
|
||||||
std::transform(container.begin(), container.end(), std::back_inserter(result), lambda);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
ShaderObject::LocationMap buildRemap(GLuint glprogram, const gpu::Shader::SlotSet& slotSet) {
|
|
||||||
static const GLint INVALID_INDEX = -1;
|
|
||||||
ShaderObject::LocationMap result;
|
|
||||||
const auto expectedNames = slotSet.getNames();
|
|
||||||
const auto count = expectedNames.size();
|
|
||||||
std::vector<GLint> indices;
|
|
||||||
indices.resize(count);
|
|
||||||
glGetUniformIndices(glprogram, (GLsizei)count,
|
|
||||||
toCNames(expectedNames, [](const std::string& name) { return name.c_str(); }).data(),
|
|
||||||
(GLuint*)indices.data());
|
|
||||||
|
|
||||||
const auto expectedLocationsByName = slotSet.getLocationsByName();
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
|
||||||
const auto& index = indices[i];
|
|
||||||
const auto& name = expectedNames[i];
|
|
||||||
const auto& expectedLocation = expectedLocationsByName.at(name);
|
|
||||||
if (INVALID_INDEX == index) {
|
|
||||||
result[expectedLocation] = gpu::Shader::INVALID_LOCATION;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
::gl::Uniform uniformInfo(glprogram, index);
|
|
||||||
if (expectedLocation != uniformInfo.binding) {
|
|
||||||
result[expectedLocation] = uniformInfo.binding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const {
|
void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const {
|
||||||
|
Parent::postLinkProgram(programObject, program);
|
||||||
const auto& glprogram = programObject.glprogram;
|
const auto& glprogram = programObject.glprogram;
|
||||||
// For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection
|
// For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection
|
||||||
{
|
{
|
||||||
|
@ -106,14 +68,3 @@ void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& pro
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GLint GL41Backend::getRealUniformLocation(GLint location) const {
|
|
||||||
GLint result = location;
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
auto& shader = _pipeline._programShader->_shaderObjects[(GLShader::Version)isStereo()];
|
|
||||||
auto itr = shader.uniformRemap.find(location);
|
|
||||||
if (itr != shader.uniformRemap.end()) {
|
|
||||||
result = itr->second;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue