[core] Eliminate constant attribute bindings

Rather than binding constant attributes that will never be used, just disable the attribute.
This commit is contained in:
John Firebaugh
2017-06-13 16:45:12 -07:00
parent 7a3f7980b0
commit f3bb99f919
6 changed files with 77 additions and 230 deletions

View File

@@ -10,6 +10,10 @@ AttributeLocation bindAttributeLocation(ProgramID id, AttributeLocation location
return location;
}
void DisabledAttribute::bind(Context&, AttributeLocation location, std::size_t) const {
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
}
template <class T> DataType DataTypeOf = static_cast<DataType>(0);
template <> DataType DataTypeOf< int8_t> = DataType::Byte;
template <> DataType DataTypeOf<uint8_t> = DataType::UnsignedByte;
@@ -20,16 +24,9 @@ template <> DataType DataTypeOf<uint32_t> = DataType::UnsignedInteger;
template <> DataType DataTypeOf<float> = DataType::Float;
template <class T, std::size_t N>
void VariableAttributeBinding<T, N>::bind(Context& context,
AttributeLocation location,
optional<VariableAttributeBinding<T, N>>& oldBinding,
std::size_t vertexOffset) const {
if (oldBinding == *this) {
return;
}
void AttributeBinding<T, N>::bind(Context& context, AttributeLocation location, std::size_t vertexOffset) const {
context.vertexBuffer = vertexBuffer;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(location));
oldBinding = *this;
MBGL_CHECK_ERROR(glVertexAttribPointer(
location,
static_cast<GLint>(attributeSize),
@@ -39,156 +36,25 @@ void VariableAttributeBinding<T, N>::bind(Context& context,
reinterpret_cast<GLvoid*>(attributeOffset + (vertexSize * vertexOffset))));
}
template class VariableAttributeBinding<uint8_t, 1>;
template class VariableAttributeBinding<uint8_t, 2>;
template class VariableAttributeBinding<uint8_t, 3>;
template class VariableAttributeBinding<uint8_t, 4>;
template class AttributeBinding<uint8_t, 1>;
template class AttributeBinding<uint8_t, 2>;
template class AttributeBinding<uint8_t, 3>;
template class AttributeBinding<uint8_t, 4>;
template class VariableAttributeBinding<uint16_t, 1>;
template class VariableAttributeBinding<uint16_t, 2>;
template class VariableAttributeBinding<uint16_t, 3>;
template class VariableAttributeBinding<uint16_t, 4>;
template class AttributeBinding<uint16_t, 1>;
template class AttributeBinding<uint16_t, 2>;
template class AttributeBinding<uint16_t, 3>;
template class AttributeBinding<uint16_t, 4>;
template class VariableAttributeBinding<int16_t, 1>;
template class VariableAttributeBinding<int16_t, 2>;
template class VariableAttributeBinding<int16_t, 3>;
template class VariableAttributeBinding<int16_t, 4>;
template class AttributeBinding<int16_t, 1>;
template class AttributeBinding<int16_t, 2>;
template class AttributeBinding<int16_t, 3>;
template class AttributeBinding<int16_t, 4>;
template class VariableAttributeBinding<float, 1>;
template class VariableAttributeBinding<float, 2>;
template class VariableAttributeBinding<float, 3>;
template class VariableAttributeBinding<float, 4>;
template <>
void ConstantAttributeBinding<uint8_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 1>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
}
template <>
void ConstantAttributeBinding<uint8_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 2>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
}
template <>
void ConstantAttributeBinding<uint8_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 3>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
}
template <>
void ConstantAttributeBinding<uint8_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint8_t, 4>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
}
template <>
void ConstantAttributeBinding<uint16_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 1>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
}
template <>
void ConstantAttributeBinding<uint16_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 2>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
}
template <>
void ConstantAttributeBinding<uint16_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 3>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
}
template <>
void ConstantAttributeBinding<uint16_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<uint16_t, 4>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
}
template <>
void ConstantAttributeBinding<int16_t, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 1>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
}
template <>
void ConstantAttributeBinding<int16_t, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 2>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
}
template <>
void ConstantAttributeBinding<int16_t, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 3>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
}
template <>
void ConstantAttributeBinding<int16_t, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<int16_t, 4>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
}
template <>
void ConstantAttributeBinding<float, 1>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 1>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib1f(location, value[0]));
}
template <>
void ConstantAttributeBinding<float, 2>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 2>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib2f(location, value[0], value[1]));
}
template <>
void ConstantAttributeBinding<float, 3>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 3>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib3f(location, value[0], value[1], value[2]));
}
template <>
void ConstantAttributeBinding<float, 4>::bind(Context&, AttributeLocation location, optional<VariableAttributeBinding<float, 4>>& oldBinding, std::size_t) const {
assert(location != 0);
oldBinding = {};
MBGL_CHECK_ERROR(glDisableVertexAttribArray(location));
MBGL_CHECK_ERROR(glVertexAttrib4f(location, value[0], value[1], value[2], value[3]));
}
template class AttributeBinding<float, 1>;
template class AttributeBinding<float, 2>;
template class AttributeBinding<float, 3>;
template class AttributeBinding<float, 4>;
} // namespace gl
} // namespace mbgl

View File

@@ -13,23 +13,33 @@
namespace mbgl {
namespace gl {
template <class T, std::size_t N>
class VariableAttributeBinding {
class DisabledAttribute {
public:
VariableAttributeBinding(BufferID vertexBuffer_,
std::size_t vertexSize_,
std::size_t attributeOffset_,
std::size_t attributeSize_ = N)
void bind(Context&, AttributeLocation, std::size_t vertexOffset) const;
friend bool operator==(const DisabledAttribute&,
const DisabledAttribute&) {
return true;
}
};
template <class T, std::size_t N>
class AttributeBinding {
public:
AttributeBinding(BufferID vertexBuffer_,
std::size_t vertexSize_,
std::size_t attributeOffset_,
std::size_t attributeSize_ = N)
: vertexBuffer(vertexBuffer_),
vertexSize(vertexSize_),
attributeOffset(attributeOffset_),
attributeSize(attributeSize_)
{}
void bind(Context&, AttributeLocation, optional<VariableAttributeBinding<T, N>>&, std::size_t vertexOffset) const;
void bind(Context&, AttributeLocation, std::size_t vertexOffset) const;
friend bool operator==(const VariableAttributeBinding& lhs,
const VariableAttributeBinding& rhs) {
friend bool operator==(const AttributeBinding& lhs,
const AttributeBinding& rhs) {
return lhs.vertexBuffer == rhs.vertexBuffer
&& lhs.vertexSize == rhs.vertexSize
&& lhs.attributeOffset == rhs.attributeOffset
@@ -43,28 +53,8 @@ private:
std::size_t attributeSize;
};
template <class T, std::size_t N>
class ConstantAttributeBinding {
public:
ConstantAttributeBinding() { value.fill(T()); }
explicit ConstantAttributeBinding(std::array<T, N> value_)
: value(std::move(value_))
{}
void bind(Context&, AttributeLocation, optional<VariableAttributeBinding<T, N>>&, std::size_t) const;
friend bool operator==(const ConstantAttributeBinding& lhs,
const ConstantAttributeBinding& rhs) {
return lhs.value == rhs.value;
}
private:
std::array<T, N> value;
};
/*
gl::Attribute<T,N> manages the binding of a constant value or vertex buffer to a GL program attribute.
gl::Attribute<T,N> manages the binding of a vertex buffer to a GL program attribute.
- T is the underlying primitive type (exposed as Attribute<T,N>::ValueType)
- N is the number of components in the attribute declared in the shader (exposed as Attribute<T,N>::Dimensions)
*/
@@ -75,27 +65,23 @@ public:
static constexpr size_t Dimensions = N;
using Value = std::array<T, N>;
using VariableBinding = VariableAttributeBinding<T, N>;
using ConstantBinding = ConstantAttributeBinding<T, N>;
using Location = AttributeLocation;
using Binding = variant<
ConstantBinding,
VariableBinding>;
DisabledAttribute,
AttributeBinding<T, N>>;
/*
Create a variable (i.e. data-driven) binding for this attribute. The `attributeSize`
parameter may be used to override the number of components available in the buffer for
each vertex. Thus, a buffer with only one float for each vertex can be bound to a
`vec2` attribute
Create a binding for this attribute. The `attributeSize` parameter may be used to
override the number of components available in the buffer for each vertex. Thus,
a buffer with only one float for each vertex can be bound to a `vec2` attribute
*/
template <class Vertex, class DrawMode>
static VariableBinding variableBinding(const VertexBuffer<Vertex, DrawMode>& buffer,
std::size_t attributeIndex,
std::size_t attributeSize = N) {
static Binding binding(const VertexBuffer<Vertex, DrawMode>& buffer,
std::size_t attributeIndex,
std::size_t attributeSize = N) {
static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
return VariableBinding {
return AttributeBinding<T, N> {
buffer.buffer,
sizeof(Vertex),
Vertex::attributeOffsets[attributeIndex],
@@ -105,12 +91,18 @@ public:
static void bind(Context& context,
const Location& location,
optional<VariableBinding>& oldBinding,
Binding& oldBinding,
const Binding& newBinding,
std::size_t vertexOffset) {
if (oldBinding == newBinding) {
return;
}
Binding::visit(newBinding, [&] (const auto& binding) {
binding.bind(context, location, oldBinding, vertexOffset);
binding.bind(context, location, vertexOffset);
});
oldBinding = newBinding;
}
};
@@ -242,9 +234,6 @@ public:
using Bindings = IndexedTuple<
TypeList<As...>,
TypeList<typename As::Type::Binding...>>;
using VariableBindings = IndexedTuple<
TypeList<As...>,
TypeList<optional<typename As::Type::VariableBinding>...>>;
using NamedLocations = std::vector<std::pair<const std::string, AttributeLocation>>;
using Vertex = detail::Vertex<typename As::Type...>;
@@ -266,13 +255,13 @@ public:
}
template <class DrawMode>
static Bindings allVariableBindings(const VertexBuffer<Vertex, DrawMode>& buffer) {
return Bindings { As::Type::variableBinding(buffer, Index<As>)... };
static Bindings bindings(const VertexBuffer<Vertex, DrawMode>& buffer) {
return Bindings { As::Type::binding(buffer, Index<As>)... };
}
static void bind(Context& context,
const Locations& locations,
VariableBindings& oldBindings,
Bindings& oldBindings,
const Bindings& newBindings,
std::size_t vertexOffset) {
util::ignore({ (As::Type::bind(context,

View File

@@ -47,12 +47,12 @@ public:
} else {
// No VAO support. Force attributes to be rebound.
context.elementBuffer = indexBuffer_;
variableBindings = {};
attributeBindings = {};
}
Attributes::bind(context,
attributeLocations,
variableBindings,
attributeBindings,
attributeBindings_,
vertexOffset);
}
@@ -60,7 +60,7 @@ public:
private:
mutable optional<UniqueVertexArray> vao;
mutable optional<BufferID> indexBuffer;
mutable typename Attributes::VariableBindings variableBindings;
mutable typename Attributes::Bindings attributeBindings;
};
template <class Attributes>

View File

@@ -66,7 +66,7 @@ public:
std::move(colorMode),
uniformValues
.concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties)),
LayoutAttributes::allVariableBindings(layoutVertexBuffer)
LayoutAttributes::bindings(layoutVertexBuffer)
.concat(paintPropertyBinders.attributeBindings(currentProperties)),
indexBuffer,
segments

View File

@@ -156,8 +156,9 @@ public:
}
SymbolSizeAttributes::Bindings attributeBindings() const override {
return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::ConstantBinding {{{0, 0, 0}}} };
return SymbolSizeAttributes::Bindings { gl::DisabledAttribute() };
}
void upload(gl::Context&) override {}
void populateVertexVector(const GeometryTileFeature&) override {};
@@ -210,9 +211,9 @@ public:
}
SymbolSizeAttributes::Bindings attributeBindings() const override {
return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::variableBinding(*buffer, 0, 1) };
return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::binding(*buffer, 0, 1) };
}
void populateVertexVector(const GeometryTileFeature& feature) override {
const auto sizeVertex = Vertex {
{{
@@ -263,7 +264,7 @@ public:
{}
SymbolSizeAttributes::Bindings attributeBindings() const override {
return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::variableBinding(*buffer, 0) };
return SymbolSizeAttributes::Bindings { SymbolSizeAttributes::Attribute::binding(*buffer, 0) };
}
void populateVertexVector(const GeometryTileFeature& feature) override {
@@ -368,7 +369,7 @@ public:
uniformValues
.concat(symbolSizeBinder.uniformValues(currentZoom))
.concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties)),
LayoutAttributes::allVariableBindings(layoutVertexBuffer)
LayoutAttributes::bindings(layoutVertexBuffer)
.concat(symbolSizeBinder.attributeBindings())
.concat(paintPropertyBinders.attributeBindings(currentProperties)),
indexBuffer,

View File

@@ -103,11 +103,8 @@ public:
void populateVertexVector(const GeometryTileFeature&, std::size_t) override {}
void upload(gl::Context&) override {}
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
auto value = attributeValue(currentValue.constantOr(constant));
return typename Attribute::ConstantBinding {
zoomInterpolatedAttributeValue(value, value)
};
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>&) const override {
return gl::DisabledAttribute();
}
float interpolationFactor(float) const override {
@@ -152,12 +149,9 @@ public:
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
BaseAttributeValue value = attributeValue(*currentValue.constant());
return typename Attribute::ConstantBinding {
zoomInterpolatedAttributeValue(value, value)
};
return gl::DisabledAttribute();
} else {
return Attribute::variableBinding(*vertexBuffer, 0, BaseAttribute::Dimensions);
return Attribute::binding(*vertexBuffer, 0, BaseAttribute::Dimensions);
}
}
@@ -216,12 +210,9 @@ public:
AttributeBinding attributeBinding(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
if (currentValue.isConstant()) {
BaseAttributeValue value = attributeValue(*currentValue.constant());
return typename Attribute::ConstantBinding {
zoomInterpolatedAttributeValue(value, value)
};
return gl::DisabledAttribute();
} else {
return Attribute::variableBinding(*vertexBuffer, 0);
return Attribute::binding(*vertexBuffer, 0);
}
}