mirror of
https://github.com/lubosz/overte.git
synced 2025-04-07 15:22:09 +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);
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
this->index = index;
|
||||
GLint length = 0;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct Uniform : public ShaderBinding {
|
|||
static Vector load(GLuint glprogram);
|
||||
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<std::string>& names);
|
||||
|
||||
template <typename C>
|
||||
static Vector loadByName(GLuint glprogram, const C& names) {
|
||||
|
|
|
@ -260,7 +260,7 @@ public:
|
|||
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
||||
|
||||
protected:
|
||||
virtual GLint getRealUniformLocation(GLint location) const { return location; }
|
||||
virtual GLint getRealUniformLocation(GLint location) const;
|
||||
|
||||
void recycle() const override;
|
||||
|
||||
|
@ -494,7 +494,7 @@ protected:
|
|||
} _pipeline;
|
||||
|
||||
// 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* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
|
||||
virtual std::string getBackendShaderHeader() const = 0;
|
||||
|
|
|
@ -244,6 +244,42 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
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) {
|
||||
switch (gltype) {
|
||||
|
|
|
@ -17,10 +17,8 @@ struct ShaderObject {
|
|||
GLuint glshader { 0 };
|
||||
GLuint glprogram { 0 };
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
using LocationMap = std::unordered_map <GLuint, GLuint>;
|
||||
LocationMap uniformRemap;
|
||||
#endif
|
||||
};
|
||||
|
||||
class GLShader : public GPUObject {
|
||||
|
|
|
@ -173,7 +173,6 @@ protected:
|
|||
std::string getBackendShaderHeader() 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;
|
||||
}
|
||||
|
||||
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 {
|
||||
Parent::postLinkProgram(programObject, program);
|
||||
const auto& glprogram = programObject.glprogram;
|
||||
// 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