Fix procedural rendering with custom uniforms

This commit is contained in:
Brad Davis 2018-07-30 14:46:16 -07:00 committed by Bradley Austin Davis
parent eca803503c
commit df031b5d93
7 changed files with 54 additions and 55 deletions

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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) {

View file

@ -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 {

View file

@ -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;
};
} }

View file

@ -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;
}