Files
MapLibreParticleLab/src/mbgl/shaders/gl/shader_program_gl.cpp
Tim Sylvester b8c0b1a97c Drawable Renderer (#1570), Move layer update to where more state is available.
Evaluate properties and use actual style color.
Fix problems with attribute bindings and depth modes.
2023-08-31 15:36:19 +02:00

157 lines
6.1 KiB
C++

#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/gl/vertex_attribute_gl.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <cstring>
#include <utility>
namespace mbgl {
namespace gl {
static gfx::AttributeDataType mapType(platform::GLenum attrType) {
using T = gfx::AttributeDataType;
switch (attrType) {
case GL_FLOAT: return T::Float;
case GL_FLOAT_VEC2: return T::Float2;
case GL_FLOAT_VEC3: return T::Float3;
case GL_FLOAT_VEC4: return T::Float4;
case GL_FLOAT_MAT2: return T::Float4; // does that work ?
case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4: return T::Float4;
case GL_INT: return T::Int;
case GL_INT_VEC2: return T::Int2;
case GL_INT_VEC3: return T::Int3;
case GL_INT_VEC4: return T::Int4;
case GL_UNSIGNED_INT: return T::UInt;
// ES3 stuff that isn't defined yet:
//case GL_FLOAT_MAT2x3:
//case GL_FLOAT_MAT2x4:
//case GL_FLOAT_MAT3x2:
//case GL_FLOAT_MAT3x4:
//case GL_FLOAT_MAT4x2:
//case GL_FLOAT_MAT4x3: return T::Invalid;
//case GL_UNSIGNED_INT_VEC2: return T::UInt2;
//case GL_UNSIGNED_INT_VEC3: return T::UInt3;
//case GL_UNSIGNED_INT_VEC4: return T::UInt4;
//case GL_DOUBLE: return T::Float;
//case GL_DOUBLE_VEC2: return T::Float2;
//case GL_DOUBLE_VEC3: return T::Float3;
//case GL_DOUBLE_VEC4: return T::Float4;
//case GL_DOUBLE_MAT2: return T::Float4;
//case GL_DOUBLE_MAT3:
//case GL_DOUBLE_MAT4:
//case GL_DOUBLE_MAT2x3:
//case GL_DOUBLE_MAT2x4:
//case GL_DOUBLE_MAT3x2:
//case GL_DOUBLE_MAT3x4:
//case GL_DOUBLE_MAT4x2:
//case GL_DOUBLE_MAT4x3:
default: return T::Invalid;
}
}
// No `AttributeDataType` for 4x4, so we have to account for it separately...
static int mapCount(const platform::GLenum attrType) {
switch (attrType) {
case GL_FLOAT_MAT3: return 3;
case GL_FLOAT_MAT4: return 4;
default: return 1;
}
}
ShaderProgramGL::ShaderProgramGL(UniqueProgram&& glProgram_)
: ShaderProgramBase(),
glProgram(std::move(glProgram_)) {
}
ShaderProgramGL::ShaderProgramGL(UniqueProgram&& program,
VertexAttributeArrayGL&& uniforms_,
VertexAttributeArrayGL&& attributes_)
: ShaderProgramBase(),
glProgram(std::move(program)),
uniforms(std::move(uniforms_)),
vertexAttributes(std::move(attributes_)) {
}
ShaderProgramGL::ShaderProgramGL(ShaderProgramGL&& other)
: ShaderProgramBase(std::forward<ShaderProgramBase&&>(other)),
glProgram(std::move(other.glProgram)),
uniforms(std::move(other.uniforms)),
vertexAttributes(std::move(other.vertexAttributes)) {
}
using namespace platform;
static void addAttr(VertexAttributeArrayGL& attrs, const char* name, GLint index,
GLsizei length, GLint count, GLenum glType) {
const auto elementType = mapType(glType);
const auto elementCount = mapCount(glType); // number of `elementType`, hopefully temporary
if (elementType != gfx::AttributeDataType::Invalid && length > 0) {
if (auto newAttr = attrs.add(name, index, elementType, elementCount, count)) {
auto* glAttr = static_cast<VertexAttributeGL*>(newAttr);
glAttr->setGLType(glType);
}
}
}
std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(
Context& context,
std::string_view /*name*/,
std::string_view vertexSource,
std::string_view fragmentSource) noexcept(false) {
const auto firstAttrib = "a_pos";
// throws on compile error
auto vertProg = context.createShader(ShaderType::Vertex, std::initializer_list<const char*>{vertexSource.data()});
auto fragProg = context.createShader(ShaderType::Fragment, std::initializer_list<const char*>{fragmentSource.data()});
auto program = context.createProgram(vertProg, fragProg, firstAttrib);
// GLES3.1
//GLint numAttribs;
//glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs);
VertexAttributeArrayGL uniforms;
GLint count = 0;
GLint maxLength = 0;
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength));
auto name = std::vector<GLchar>(maxLength);
for (GLint index = 0; index < count; ++index) {
GLsizei length = 0;
GLint size = 0;
GLenum glType = 0;
MBGL_CHECK_ERROR(glGetActiveUniform(program, index, maxLength, &length, &size, &glType, name.data()));
const GLint location = MBGL_CHECK_ERROR(glGetUniformLocation(program, name.data()));
addAttr(uniforms, name.data(), location, length, size, glType);
}
VertexAttributeArrayGL attrs;
count = 0;
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &count));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength));
name.resize(maxLength);
for (GLint index = 0; index < count; ++index) {
GLsizei length = 0; // "number of characters actually written in name (excluding the null terminator)"
GLint size = 0; // "size of the attribute variable, in units of the type returned in type"
GLenum glType = 0;
MBGL_CHECK_ERROR(glGetActiveAttrib(program, index, maxLength, &length, &size, &glType, name.data()));
if (!strncmp(name.data(), "gl_", 3)) { // Is there a better way to detect built-in attributes?
continue;
}
const GLint location = MBGL_CHECK_ERROR(glGetAttribLocation(program, name.data()));
addAttr(attrs, name.data(), location, length, size, glType);
}
return std::make_shared<ShaderProgramGL>(std::move(program), std::move(uniforms), std::move(attrs));
}
} // namespace gl
} // namespace mbgl