Circle layer final (#1227)

This commit is contained in:
Alex Cristici
2023-06-09 20:49:46 +03:00
committed by Bart Louwers
parent 008f584b9e
commit 52b9e099e5
31 changed files with 605 additions and 402 deletions

View File

@@ -148,6 +148,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderable.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderer_backend.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/rendering_stats.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/rendering_stats.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_registry.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_registry.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_block.hpp
@@ -190,6 +191,7 @@ list(APPEND INCLUDE_FILES
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_observer.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_state.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/renderer/renderer_state.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_program_base.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_program_base.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_program_gl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/shader_program_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program_mtl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program_mtl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/storage/database_file_source.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/storage/database_file_source.hpp
@@ -393,6 +395,7 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/renderbuffer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/renderbuffer.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/renderer_backend.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/rendering_stats.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/rendering_stats.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/shader_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/shader_registry.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/shader_registry.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/stencil_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/stencil_mode.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/texture.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/texture.hpp

View File

@@ -41,6 +41,7 @@ enum class AttributeDataType : uint8_t {
UShort2, UShort2,
UShort3, UShort3,
UShort4, UShort4,
UShort8,
Int, Int,
Int2, Int2,

View File

@@ -0,0 +1,153 @@
#pragma once
#include <mbgl/gfx/shader.hpp>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include <vector>
namespace mbgl {
namespace gfx {
class Context;
/// @brief A ShaderGroup contains a collection of gfx::Shader.
/// Using the group, shaders may be dynamically registered or replaced
/// at runtime.
class ShaderGroup {
public:
ShaderGroup() = default;
ShaderGroup(const ShaderGroup&) = delete;
ShaderGroup(ShaderGroup&&) noexcept = delete;
ShaderGroup& operator=(const ShaderGroup&) = delete;
ShaderGroup& operator=(ShaderGroup&&) noexcept = delete;
virtual ~ShaderGroup() = default;
/// @brief Checks if a shader exists in the group for the given name.
/// @param shaderName Name of shader
/// @return If a shader is found, true
[[nodiscard]] virtual bool isShader(const std::string& shaderName) const noexcept;
/// @brief Get a shader from the group by name.
/// @param shaderName Name of shader
/// @return A `gfx::Shader` or `nullptr` if no shader is found with the
/// given name
[[nodiscard]] virtual const std::shared_ptr<gfx::Shader> getShader(const std::string& shaderName) const noexcept;
/// @brief Replace a matching shader in the group with the provided
/// instance. Shader type-names must match.
/// @param shader A `gfx::Shader`. The ShaderGroup will take ownership.
/// @return True if a match was found and the shader was replaced, false
/// otherwise.
[[nodiscard]] virtual bool replaceShader(std::shared_ptr<Shader>&& shader) noexcept;
/// @brief Replace a matching shader in the group with the provided
/// instance. Shader type-names must match.
/// This variant replaces by explicit name.
/// @param shader A `gfx::Shader`. The ShaderGroup will take ownership.
/// @param shaderName Unique name to register the shader under.
/// @return True if a match was found and the shader was replaced, false
/// otherwise.
[[nodiscard]] virtual bool replaceShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept;
/// @brief Register a new shader with the group. If a shader is present
/// in the group with a conflicting name, registration will fail.
/// @param shader A `gfx::Shader` to register. The ShaderGroup will
/// take ownership.
/// @return True if the shader was registered, false if another shader is
/// already present with a conflicting name.
[[nodiscard]] virtual bool registerShader(std::shared_ptr<Shader>&& shader) noexcept;
/// @brief Register a new shader with the group. If a shader is present
/// in the group with a conflicting name, registration will fail.
/// This variant registers using an explicit name.
/// @param shader A `gfx::Shader` to register. The ShaderGroup will
/// take ownership.
/// @param shaderName Unique name to register the shader under.
/// @return True if the shader was registered, false if another shader is
/// already present with a conflicting name.
[[nodiscard]] virtual bool registerShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept;
/// @brief Shorthand helper to quickly get a derived type from the group.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param shaderName The group name to look up
/// @return T or nullptr if not found in the group
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
std::shared_ptr<T> get(const std::string& shaderName) noexcept {
auto shader = getShader(shaderName);
if (!shader || shader->typeName() != T::Name) {
return nullptr;
}
return std::static_pointer_cast<T>(shader);
}
/// @brief Shorthand helper to quickly get a derived type from the group.
/// This variant looks up shaders only by type name.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @return T or nullptr if not found in the group
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
std::shared_ptr<T> get() noexcept {
auto shader = getShader(std::string(T::Name));
if (!shader || shader->typeName() != T::Name) {
return nullptr;
}
return std::static_pointer_cast<T>(shader);
}
/// @brief Ensure the destination 'to' is populated with the requested
/// shader. If already non-null, does nothing.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param to Location to store the shader
/// @param shaderName The group name to look up
/// @return True if 'to' has a valid program object, false otherwise.
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
bool populate(std::shared_ptr<T>& to, const std::string& shaderName) noexcept {
if (to) {
return true;
}
auto shader = getShader(shaderName);
if (!shader || shader->typeName() != T::Name) {
return false;
}
to = std::static_pointer_cast<T>(shader);
return true;
}
/// @brief Ensure the destination 'to' is populated with the requested
/// shader. If already non-null, does nothing. This variant looks up
/// shaders only by type name.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param to Location to store the shader
/// @return True if 'to' has a valid program object, false otherwise.
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
bool populate(std::shared_ptr<T>& to) noexcept {
if (to) {
return true;
}
auto shader = getShader(std::string(T::Name));
if (!shader || shader->typeName() != T::Name) {
return false;
}
to = std::static_pointer_cast<T>(shader);
return true;
}
/// @brief Get a shader from the group by its set of data driven properties as uniforms.
/// if no shader is found, create and register the shader.
/// @param propertiesAsUniforms Vector of data driven properties as uniforms.
/// @return A `gfx::Shader`
virtual const std::shared_ptr<gfx::Shader> getOrCreateShader(gfx::Context&, const std::vector<std::string>&) {
return nullptr;
}
private:
std::unordered_map<std::string, std::shared_ptr<gfx::Shader>> programs;
mutable std::shared_mutex programLock;
};
} // namespace gfx
} // namespace mbgl

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <mbgl/gfx/shader.hpp> #include <mbgl/gfx/shader_group.hpp>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@@ -10,8 +10,10 @@
namespace mbgl { namespace mbgl {
namespace gfx { namespace gfx {
/// @brief A ShaderRegistry contains a collection of gfx::Shader instances. using ShaderGroupPtr = std::shared_ptr<gfx::ShaderGroup>;
/// Using the registry, shaders may be dynamically registered or replaced
/// @brief A ShaderRegistry contains a collection of gfx::ShaderGroup instances.
/// Using the registry, shader groups may be dynamically registered or replaced
/// at runtime. /// at runtime.
class ShaderRegistry { class ShaderRegistry {
public: public:
@@ -22,120 +24,44 @@ public:
ShaderRegistry& operator=(ShaderRegistry&&) noexcept = delete; ShaderRegistry& operator=(ShaderRegistry&&) noexcept = delete;
virtual ~ShaderRegistry() = default; virtual ~ShaderRegistry() = default;
/// @brief Checks if a shader exists in the registry for the given name. /// @brief Get the legacy shader group.
/// @param shaderName Name of shader /// @return A `gfx::ShaderGroup`
/// @return If a shader is found, true [[nodiscard]] ShaderGroup& getLegacyGroup() noexcept;
[[nodiscard]] virtual bool isShader(const std::string& shaderName) const noexcept;
/// @brief Get a shader from the registry by name. /// @brief Checks if a shader group exists in the registry for the given name.
/// @param shaderName Name of shader /// @param shaderGroupName Name of shader group
/// @return A `gfx::Shader` or `nullptr` if no shader is found with the /// @return If a shader group is found, true
[[nodiscard]] virtual bool isShaderGroup(const std::string& shaderGroupName) const noexcept;
/// @brief Get a shader group from the registry by name.
/// @param shaderGroupName Name of shader group
/// @return A `gfx::ShaderGroup` or `nullptr` if no shader group is found with the
/// given name /// given name
[[nodiscard]] virtual const std::shared_ptr<gfx::Shader> getShader(const std::string& shaderName) const noexcept; [[nodiscard]] virtual const ShaderGroupPtr getShaderGroup(const std::string& shaderGroupName) const noexcept;
/// @brief Replace a matching shader in the registry with the provided /// @brief Replace a matching shader group in the registry with the provided
/// instance. Shader type-names must match. /// name.
/// @param shader A `gfx::Shader`. The ShaderRegistry will take ownership. /// @param shaderGroup A `gfx::ShaderGroup`. The ShaderRegistry will take ownership.
/// @return True if a match was found and the shader was replaced, false /// @param shaderGroupName Unique name to register the shader group under.
/// @return True if a match was found and the shader group was replaced, false
/// otherwise. /// otherwise.
[[nodiscard]] virtual bool replaceShader(std::shared_ptr<Shader>&& shader) noexcept; [[nodiscard]] virtual bool replaceShader(ShaderGroupPtr&& shaderGroup, const std::string& shaderName) noexcept;
/// @brief Replace a matching shader in the registry with the provided /// @brief Register a new shader group with the registry for the given name.
/// instance. Shader type-names must match. /// If a shader group is present in the registry with a conflicting name,
/// This variant replaces by explicit name. /// registration will fail.
/// @param shader A `gfx::Shader`. The ShaderRegistry will take ownership. /// @param shaderGroup A `gfx::ShaderGroup` to register. The ShaderRegistry will
/// @param shaderName Unique name to register the shader under.
/// @return True if a match was found and the shader was replaced, false
/// otherwise.
[[nodiscard]] virtual bool replaceShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept;
/// @brief Register a new shader with the registry. If a shader is present
/// in the registry with a conflicting name, registration will fail.
/// @param shader A `gfx::Shader` to register. The ShaderRegistry will
/// take ownership. /// take ownership.
/// @return True if the shader was registered, false if another shader is /// @param shaderGroupName Unique name to register the shader group under.
/// @return True if the shader group was registered, false if another shader group is
/// already present with a conflicting name. /// already present with a conflicting name.
[[nodiscard]] virtual bool registerShader(std::shared_ptr<Shader>&& shader) noexcept; [[nodiscard]] virtual bool registerShaderGroup(ShaderGroupPtr&& shaderGroup,
const std::string& shaderGroupName) noexcept;
/// @brief Register a new shader with the registry. If a shader is present
/// in the registry with a conflicting name, registration will fail.
/// This variant registers using an explicit name.
/// @param shader A `gfx::Shader` to register. The ShaderRegistry will
/// take ownership.
/// @param shaderName Unique name to register the shader under.
/// @return True if the shader was registered, false if another shader is
/// already present with a conflicting name.
[[nodiscard]] virtual bool registerShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept;
/// @brief Shorthand helper to quickly get a derived type from the registry.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param shaderName The registry name to look up
/// @return T or nullptr if not found in the registry
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
std::shared_ptr<T> get(const std::string& shaderName) noexcept {
auto shader = getShader(shaderName);
if (!shader || shader->typeName() != T::Name) {
return nullptr;
}
return std::static_pointer_cast<T>(shader);
}
/// @brief Shorthand helper to quickly get a derived type from the registry.
/// This variant looks up shaders only by type name.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @return T or nullptr if not found in the registry
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
std::shared_ptr<T> get() noexcept {
auto shader = getShader(std::string(T::Name));
if (!shader || shader->typeName() != T::Name) {
return nullptr;
}
return std::static_pointer_cast<T>(shader);
}
/// @brief Ensure the destination 'to' is populated with the requested
/// shader. If already non-null, does nothing.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param to Location to store the shader
/// @param shaderName The registry name to look up
/// @return True if 'to' has a valid program object, false otherwise.
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
bool populate(std::shared_ptr<T>& to, const std::string& shaderName) noexcept {
if (to) {
return true;
}
auto shader = getShader(shaderName);
if (!shader || shader->typeName() != T::Name) {
return false;
}
to = std::static_pointer_cast<T>(shader);
return true;
}
/// @brief Ensure the destination 'to' is populated with the requested
/// shader. If already non-null, does nothing. This variant looks up
/// shaders only by type name.
/// @tparam T Derived type, inheriting `gfx::Shader`
/// @param to Location to store the shader
/// @return True if 'to' has a valid program object, false otherwise.
template <typename T, typename std::enable_if_t<is_shader_v<T>, bool>* = nullptr>
bool populate(std::shared_ptr<T>& to) noexcept {
if (to) {
return true;
}
auto shader = getShader(std::string(T::Name));
if (!shader || shader->typeName() != T::Name) {
return false;
}
to = std::static_pointer_cast<T>(shader);
return true;
}
private: private:
std::unordered_map<std::string, std::shared_ptr<gfx::Shader>> programs; gfx::ShaderGroup legacyGroup;
mutable std::shared_mutex programLock; std::unordered_map<std::string, ShaderGroupPtr> shaderGroups;
mutable std::shared_mutex shaderGroupLock;
}; };
} // namespace gfx } // namespace gfx

View File

@@ -33,8 +33,10 @@ public:
using int2 = std::array<std::int32_t, 2>; using int2 = std::array<std::int32_t, 2>;
using int3 = std::array<std::int32_t, 3>; using int3 = std::array<std::int32_t, 3>;
using int4 = std::array<std::int32_t, 4>; using int4 = std::array<std::int32_t, 4>;
using ushort8 = std::array<std::uint16_t, 8>;
using ElementType = std::variant<std::int32_t, int2, int3, int4, float, float2, float3, float4, matf3, matf4>; using ElementType =
std::variant<std::int32_t, ushort8, int2, int3, int4, float, float2, float3, float4, matf3, matf4>;
VertexAttribute(int index_, AttributeDataType dataType_, int size_, std::size_t count_, std::size_t stride_) VertexAttribute(int index_, AttributeDataType dataType_, int size_, std::size_t count_, std::size_t stride_)
: index(index_), : index(index_),
@@ -106,6 +108,19 @@ public:
rawData.clear(); rawData.clear();
} }
template <std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type set(std::size_t, std::tuple<Tp...>, std::size_t) {}
template <std::size_t I = 0, typename... Tp>
inline typename std::enable_if <
I<sizeof...(Tp), void>::type set(std::size_t i, std::tuple<Tp...> tuple, std::size_t tupleIndex) {
if (tupleIndex == 0) {
set(i, std::get<I>(tuple).a1);
} else {
set<I + 1, Tp...>(i, tuple, tupleIndex - 1);
}
}
protected: protected:
VertexAttribute& operator=(const VertexAttribute&) = default; VertexAttribute& operator=(const VertexAttribute&) = default;
VertexAttribute& operator=(VertexAttribute&& other) { VertexAttribute& operator=(VertexAttribute&& other) {
@@ -219,6 +234,33 @@ public:
return newAttrs; return newAttrs;
} }
template <class... DataDrivenPaintProperty, class Binders, class Evaluated>
std::vector<std::string> readDataDrivenPaintProperties(const Binders& binders, const Evaluated& evaluated) {
std::vector<std::string> propertiesAsUniforms;
(
[&](const auto& attributeNames) {
for (std::size_t attrIndex = 0; attrIndex < attributeNames.size(); ++attrIndex) {
const auto& attributeName = std::string(attributeNames[attrIndex]);
if (auto& binder = binders.template get<DataDrivenPaintProperty>()) {
const auto vertexCount = binder->getVertexCount();
const auto isConstant = evaluated.template get<DataDrivenPaintProperty>().isConstant();
if (vertexCount > 0 && !isConstant) {
if (auto& attr = getOrAdd("a_" + attributeName)) {
for (std::size_t i = 0; i < vertexCount; ++i) {
attr->set(i, binder->getVertexValue(i), attrIndex);
}
}
propertiesAsUniforms.emplace_back("");
} else {
propertiesAsUniforms.emplace_back(attributeName);
}
}
}
}(DataDrivenPaintProperty::AttributeNames),
...);
return propertiesAsUniforms;
}
protected: protected:
const std::unique_ptr<VertexAttribute>& add(std::string name, std::unique_ptr<VertexAttribute>&& attr) { const std::unique_ptr<VertexAttribute>& add(std::string name, std::unique_ptr<VertexAttribute>&& attr) {
const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>())); const auto result = attrs.insert(std::make_pair(std::move(name), std::unique_ptr<VertexAttribute>()));

View File

@@ -0,0 +1,53 @@
#pragma once
#include <mbgl/gfx/shader_group.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/programs/program_parameters.hpp>
namespace mbgl {
namespace gl {
template <shaders::BuiltIn ShaderID>
class ShaderGroupGL final : public gfx::ShaderGroup {
public:
ShaderGroupGL(const ProgramParameters& programParameters_)
: ShaderGroup(),
programParameters(programParameters_){};
~ShaderGroupGL() noexcept override = default;
const std::shared_ptr<gfx::Shader> getOrCreateShader(
gfx::Context& context, const std::vector<std::string>& propertiesAsUniforms) override {
const auto& name = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::name;
const auto& vert = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::vertex;
const auto& frag = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::fragment;
uint32_t key = 0;
std::string additionalDefines;
for (unsigned int i = 0; i < propertiesAsUniforms.size(); i++) {
if (propertiesAsUniforms[i].empty()) {
continue;
}
key |= 1 << i;
additionalDefines += "#define HAS_UNIFORM_u_";
additionalDefines += propertiesAsUniforms[i];
additionalDefines += "\n";
}
std::string shaderName = std::string(name) + "#" + std::to_string(key);
auto shader = get<gl::ShaderProgramGL>(shaderName);
if (!shader) {
shader = ShaderProgramGL::create(
static_cast<gl::Context&>(context), programParameters, shaderName, vert, frag, additionalDefines);
if (!registerShader(shader, shaderName)) {
throw std::runtime_error("Failed to register " + shaderName + " with shader group!");
}
}
return shader;
}
private:
ProgramParameters programParameters;
};
} // namespace gl
} // namespace mbgl

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <algorithm>
namespace mbgl { namespace mbgl {
@@ -10,4 +11,14 @@ using vec3f = std::array<float, 3>;
using vec3i = std::array<int, 3>; using vec3i = std::array<int, 3>;
using vec4 = std::array<double, 4>; using vec4 = std::array<double, 4>;
} // namespace mbgl template <typename Type, std::size_t... sizes>
auto concatenate(const std::array<Type, sizes>&... arrays) {
std::array<Type, (sizes + ...)> result;
std::size_t index{};
((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...);
return result;
}
} // namespace mbgl

View File

@@ -63,6 +63,8 @@ struct AttributeDataTypeOf<uint16_t, 3> : std::integral_constant<AttributeDataTy
template <> template <>
struct AttributeDataTypeOf<uint16_t, 4> : std::integral_constant<AttributeDataType, AttributeDataType::UShort4> {}; struct AttributeDataTypeOf<uint16_t, 4> : std::integral_constant<AttributeDataType, AttributeDataType::UShort4> {};
template <> template <>
struct AttributeDataTypeOf<uint16_t, 8> : std::integral_constant<AttributeDataType, AttributeDataType::UShort8> {};
template <>
struct AttributeDataTypeOf<int32_t, 1> : std::integral_constant<AttributeDataType, AttributeDataType::Int> {}; struct AttributeDataTypeOf<int32_t, 1> : std::integral_constant<AttributeDataType, AttributeDataType::Int> {};
template <> template <>
struct AttributeDataTypeOf<int32_t, 2> : std::integral_constant<AttributeDataType, AttributeDataType::Int2> {}; struct AttributeDataTypeOf<int32_t, 2> : std::integral_constant<AttributeDataType, AttributeDataType::Int2> {};

View File

@@ -0,0 +1,51 @@
#include <mbgl/gfx/shader_group.hpp>
#include <mbgl/gfx/shader.hpp>
namespace mbgl {
namespace gfx {
bool ShaderGroup::isShader(const std::string& shaderName) const noexcept {
std::shared_lock<std::shared_mutex> readerLock(programLock);
return programs.find(shaderName) != programs.end();
}
const std::shared_ptr<gfx::Shader> ShaderGroup::getShader(const std::string& shaderName) const noexcept {
std::shared_lock<std::shared_mutex> readerLock(programLock);
const auto it = programs.find(shaderName);
if (it == programs.end()) {
return nullptr;
}
return it->second;
}
bool ShaderGroup::replaceShader(std::shared_ptr<gfx::Shader>&& shader) noexcept {
return replaceShader(std::move(shader), std::string{shader->typeName()});
}
bool ShaderGroup::replaceShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
std::unique_lock<std::shared_mutex> writerLock(programLock);
if (programs.find(shaderName) == programs.end()) {
return false;
}
programs[shaderName] = std::move(shader);
return true;
}
bool ShaderGroup::registerShader(std::shared_ptr<gfx::Shader>&& shader) noexcept {
return registerShader(std::move(shader), std::string{shader->typeName()});
}
bool ShaderGroup::registerShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
std::unique_lock<std::shared_mutex> writerLock(programLock);
if (programs.find(shaderName) != programs.end()) {
return false;
}
programs.emplace(shaderName, std::move(shader));
return true;
}
} // namespace gfx
} // namespace mbgl

View File

@@ -1,51 +1,48 @@
#include <mbgl/gfx/shader_registry.hpp> #include <mbgl/gfx/shader_registry.hpp>
#include <mbgl/gfx/shader.hpp> #include <mbgl/gfx/shader_group.hpp>
namespace mbgl { namespace mbgl {
namespace gfx { namespace gfx {
ShaderRegistry::ShaderRegistry() {} ShaderRegistry::ShaderRegistry()
: legacyGroup() {}
bool ShaderRegistry::isShader(const std::string& shaderName) const noexcept { ShaderGroup& ShaderRegistry::getLegacyGroup() noexcept {
std::shared_lock<std::shared_mutex> readerLock(programLock); return legacyGroup;
return programs.find(shaderName) != programs.end();
} }
const std::shared_ptr<gfx::Shader> ShaderRegistry::getShader(const std::string& shaderName) const noexcept { bool ShaderRegistry::isShaderGroup(const std::string& shaderGroupName) const noexcept {
std::shared_lock<std::shared_mutex> readerLock(programLock); std::shared_lock<std::shared_mutex> readerLock(shaderGroupLock);
const auto it = programs.find(shaderName); return shaderGroups.find(shaderGroupName) != shaderGroups.end();
if (it == programs.end()) { }
const ShaderGroupPtr ShaderRegistry::getShaderGroup(const std::string& shaderGroupName) const noexcept {
std::shared_lock<std::shared_mutex> readerLock(shaderGroupLock);
const auto it = shaderGroups.find(shaderGroupName);
if (it == shaderGroups.end()) {
return nullptr; return nullptr;
} }
return it->second; return it->second;
} }
bool ShaderRegistry::replaceShader(std::shared_ptr<gfx::Shader>&& shader) noexcept { bool ShaderRegistry::replaceShader(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
return replaceShader(std::move(shader), std::string{shader->typeName()}); std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
} if (shaderGroups.find(shaderGroupName) == shaderGroups.end()) {
bool ShaderRegistry::replaceShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
std::unique_lock<std::shared_mutex> writerLock(programLock);
if (programs.find(shaderName) == programs.end()) {
return false; return false;
} }
programs[shaderName] = std::move(shader); shaderGroups[shaderGroupName] = std::move(shader);
return true; return true;
} }
bool ShaderRegistry::registerShader(std::shared_ptr<gfx::Shader>&& shader) noexcept { bool ShaderRegistry::registerShaderGroup(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
return registerShader(std::move(shader), std::string{shader->typeName()}); std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
} if (shaderGroups.find(shaderGroupName) != shaderGroups.end()) {
bool ShaderRegistry::registerShader(std::shared_ptr<Shader>&& shader, const std::string& shaderName) noexcept {
std::unique_lock<std::shared_mutex> writerLock(programLock);
if (programs.find(shaderName) != programs.end()) {
return false; return false;
} }
programs.emplace(shaderName, std::move(shader)); shaderGroups.emplace(shaderGroupName, std::move(shader));
return true; return true;
} }

View File

@@ -468,7 +468,9 @@ gfx::UniformBufferPtr Context::createUniformBuffer(const void* data, std::size_t
} }
gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) { gfx::ShaderProgramBasePtr Context::getGenericShader(gfx::ShaderRegistry& shaders, const std::string& name) {
return shaders.get<gl::ShaderProgramGL>(name); std::vector<std::string> emptyAttributes(0);
return std::static_pointer_cast<gfx::ShaderProgramBase>(
shaders.getShaderGroup(name)->getOrCreateShader(*this, emptyAttributes));
} }
TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {

View File

@@ -4,7 +4,7 @@
#include <mbgl/gl/context.hpp> #include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp> #include <mbgl/gl/extension.hpp>
#include <mbgl/shaders/shader_manifest.hpp> #include <mbgl/shaders/shader_manifest.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp> #include <mbgl/shaders/gl/shader_group_gl.hpp>
#include <mbgl/util/logging.hpp> #include <mbgl/util/logging.hpp>
#include <cassert> #include <cassert>
@@ -69,10 +69,9 @@ RendererBackend::~RendererBackend() = default;
/// @brief Register a list of types with a shader registry instance /// @brief Register a list of types with a shader registry instance
/// @tparam ...ShaderID Pack of BuiltIn:: shader IDs /// @tparam ...ShaderID Pack of BuiltIn:: shader IDs
/// @param registry A shader registry instance /// @param registry A shader registry instance
/// @param glContext The GL context instance
/// @param programParameters ProgramParameters used to initialize each instance /// @param programParameters ProgramParameters used to initialize each instance
template <shaders::BuiltIn... ShaderID> template <shaders::BuiltIn... ShaderID>
void registerTypes(gfx::ShaderRegistry& registry, gl::Context& glContext, const ProgramParameters& programParameters) { void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& programParameters) {
/// The following fold expression will create a shader for every type /// The following fold expression will create a shader for every type
/// in the parameter pack and register it with the shader registry. /// in the parameter pack and register it with the shader registry.
@@ -80,15 +79,12 @@ void registerTypes(gfx::ShaderRegistry& registry, gl::Context& glContext, const
/// failure, we shouldn't expect registration to faill unless the shader /// failure, we shouldn't expect registration to faill unless the shader
/// registry instance provided already has conflicting programs present. /// registry instance provided already has conflicting programs present.
( (
[&](const std::string& name, const std::string& vert, const std::string& frag) { [&]() {
using Ty = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>; using Ty = shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>;
if (!registry.registerShader(gl::ShaderProgramGL::create(glContext, programParameters, name, vert, frag), if (!registry.registerShaderGroup(std::make_shared<ShaderGroupGL<ShaderID>>(programParameters), Ty::name)) {
name)) {
throw std::runtime_error("Failed to register " + std::string(Ty::name) + " with shader registry!"); throw std::runtime_error("Failed to register " + std::string(Ty::name) + " with shader registry!");
} }
}(shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::name, }(),
shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::vertex,
shaders::ShaderSource<ShaderID, gfx::Backend::Type::OpenGL>::fragment),
...); ...);
} }
@@ -100,7 +96,7 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
shaders::BuiltIn::FillOutlineShader, shaders::BuiltIn::FillOutlineShader,
shaders::BuiltIn::FillOutlinePatternShader, shaders::BuiltIn::FillOutlinePatternShader,
shaders::BuiltIn::FillPatternShader, shaders::BuiltIn::FillPatternShader,
shaders::BuiltIn::RasterShader>(shaders, static_cast<gl::Context&>(*context), programParameters); shaders::BuiltIn::RasterShader>(shaders, programParameters);
} }
} // namespace gl } // namespace gl

View File

@@ -37,7 +37,7 @@ void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& progr
if (!expr) { if (!expr) {
throw std::runtime_error("Failed to register " + std::string(T::Name) + " with shader registry!"); throw std::runtime_error("Failed to register " + std::string(T::Name) + " with shader registry!");
} }
}(registry.registerShader(std::make_shared<T>(programParameters_))), }(registry.getLegacyGroup().registerShader(std::make_shared<T>(programParameters_))),
...); ...);
} }

View File

@@ -40,17 +40,9 @@ struct alignas(16) CircleEvaluatedPropsUBO {
}; };
static_assert(sizeof(CircleEvaluatedPropsUBO) % 16 == 0); static_assert(sizeof(CircleEvaluatedPropsUBO) % 16 == 0);
struct alignas(16) CircleInterpolateUBO { static constexpr std::string_view CircleDrawableUBOName = "CircleDrawableUBO";
float color_t; static constexpr std::string_view CirclePaintParamsUBOName = "CirclePaintParamsUBO";
float radius_t; static constexpr std::string_view CircleEvaluatedPropsUBOName = "CircleEvaluatedPropsUBO";
float blur_t;
float opacity_t;
float stroke_color_t;
float stroke_width_t;
float stroke_opacity_t;
float padding;
};
static_assert(sizeof(CircleInterpolateUBO) % 16 == 0);
void CircleLayerTweaker::execute(LayerGroup& layerGroup, void CircleLayerTweaker::execute(LayerGroup& layerGroup,
const RenderTree& renderTree, const RenderTree& renderTree,
@@ -66,9 +58,10 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
#endif #endif
CirclePaintParamsUBO paintParamsUBO; CirclePaintParamsUBO paintParamsUBO = {
paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance(); /* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(),
paintParamsUBO.device_pixel_ratio = parameters.pixelRatio; /* .device_pixel_ratio = */ parameters.pixelRatio,
/* .padding = */ {0}};
if (!paintParamsUniformBuffer) { if (!paintParamsUniformBuffer) {
paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO));
@@ -79,39 +72,25 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map; const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map;
if (!evaluatedPropsUniformBuffer) { if (!evaluatedPropsUniformBuffer) {
CircleEvaluatedPropsUBO evaluatedPropsUBO; CircleEvaluatedPropsUBO evaluatedPropsUBO = {
evaluatedPropsUBO.color = evaluated.get<CircleColor>().constantOr(Color()); /* .color = */ evaluated.get<CircleColor>().constantOr(CircleColor::defaultValue()),
evaluatedPropsUBO.radius = evaluated.get<CircleRadius>().constantOr(0); /* .stroke_color = */ evaluated.get<CircleStrokeColor>().constantOr(CircleStrokeColor::defaultValue()),
evaluatedPropsUBO.blur = evaluated.get<CircleBlur>().constantOr(0); /* .radius = */ evaluated.get<CircleRadius>().constantOr(CircleRadius::defaultValue()),
evaluatedPropsUBO.opacity = evaluated.get<CircleOpacity>().constantOr(0); /* .blur = */ evaluated.get<CircleBlur>().constantOr(CircleBlur::defaultValue()),
evaluatedPropsUBO.stroke_color = evaluated.get<CircleStrokeColor>().constantOr(Color()); /* .opacity = */ evaluated.get<CircleOpacity>().constantOr(CircleOpacity::defaultValue()),
evaluatedPropsUBO.stroke_width = evaluated.get<CircleStrokeWidth>().constantOr(0); /* .stroke_width = */ evaluated.get<CircleStrokeWidth>().constantOr(CircleStrokeWidth::defaultValue()),
evaluatedPropsUBO.stroke_opacity = evaluated.get<CircleStrokeOpacity>().constantOr(0); /* .stroke_opacity = */
evaluatedPropsUBO.scale_with_map = evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map; evaluated.get<CircleStrokeOpacity>().constantOr(CircleStrokeOpacity::defaultValue()),
evaluatedPropsUBO.pitch_with_map = pitchWithMap; /* .scale_with_map = */ evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map,
/* .pitch_with_map = */ pitchWithMap,
/* .padding = */ 0};
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO, evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO,
sizeof(evaluatedPropsUBO)); sizeof(evaluatedPropsUBO));
} }
CircleInterpolateUBO interpolateUBO;
interpolateUBO.color_t = 0;
interpolateUBO.radius_t = 0;
interpolateUBO.blur_t = 0;
interpolateUBO.opacity_t = 0;
interpolateUBO.stroke_color_t = 0;
interpolateUBO.stroke_width_t = 0;
interpolateUBO.stroke_opacity_t = 0;
if (!interpolateUniformBuffer) {
interpolateUniformBuffer = parameters.context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO));
} else {
interpolateUniformBuffer->update(&interpolateUBO, sizeof(CircleInterpolateUBO));
}
layerGroup.observeDrawables([&](gfx::Drawable& drawable) { layerGroup.observeDrawables([&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer); drawable.mutableUniformBuffers().addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer);
drawable.mutableUniformBuffers().addOrReplace("CircleEvaluatedPropsUBO", evaluatedPropsUniformBuffer); drawable.mutableUniformBuffers().addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
drawable.mutableUniformBuffers().addOrReplace("CircleInterpolateUBO", interpolateUniformBuffer);
if (!drawable.getTileID()) { if (!drawable.getTileID()) {
return; return;
@@ -124,20 +103,15 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
const auto matrix = getTileMatrix( const auto matrix = getTileMatrix(
tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits); tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits);
CircleDrawableUBO drawableUBO; const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()));
drawableUBO.matrix = util::cast<float>(matrix);
drawableUBO.extrude_scale =
pitchWithMap
? std::array<float, 2>{{tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()))}}
: parameters.pixelsToGLUnits;
if (auto& ubo = drawable.mutableUniformBuffers().get("CircleDrawableUBO")) { CircleDrawableUBO drawableUBO = {
ubo->update(&drawableUBO, sizeof(drawableUBO)); /* .matrix = */ util::cast<float>(matrix),
} else { /* .extrude_scale = */
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); pitchWithMap ? std::array<float, 2>{{pixelsToTileUnits}} : parameters.pixelsToGLUnits,
drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer); /* .padding = */ {0}};
}
drawable.mutableUniformBuffers().createOrUpdate(CircleDrawableUBOName, &drawableUBO, parameters.context);
}); });
} }

View File

@@ -23,9 +23,8 @@ public:
void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override;
protected: protected:
gfx::UniformBufferPtr paintParamsUniformBuffer = nullptr; gfx::UniformBufferPtr paintParamsUniformBuffer;
gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr; gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
gfx::UniformBufferPtr interpolateUniformBuffer = nullptr;
}; };
} // namespace mbgl } // namespace mbgl

View File

@@ -79,8 +79,8 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) {
// is drawn with glClear rather than this method. // is drawn with glClear rather than this method.
// Ensure programs are available // Ensure programs are available
if (!parameters.shaders.populate(backgroundProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(backgroundProgram)) return;
if (!parameters.shaders.populate(backgroundPatternProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(backgroundPatternProgram)) return;
const Properties<>::PossiblyEvaluated properties; const Properties<>::PossiblyEvaluated properties;
const BackgroundProgram::Binders paintAttributeData(properties, 0); const BackgroundProgram::Binders paintAttributeData(properties, 0);

View File

@@ -8,9 +8,11 @@
#include <mbgl/programs/circle_program.hpp> #include <mbgl/programs/circle_program.hpp>
#include <mbgl/tile/tile.hpp> #include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp> #include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/geometry/feature_index.hpp> #include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/drawable_builder.hpp> #include <mbgl/gfx/drawable_builder.hpp>
#include <mbgl/gfx/cull_face_mode.hpp> #include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/shader_group.hpp>
#include <mbgl/gfx/shader_registry.hpp> #include <mbgl/gfx/shader_registry.hpp>
#include <mbgl/util/math.hpp> #include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp> #include <mbgl/util/intersection_tests.hpp>
@@ -92,7 +94,7 @@ void RenderCircleLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(circleProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(circleProgram)) return;
const auto drawTile = [&](const RenderTile& tile, const LayerRenderData* data, const auto& segments) { const auto drawTile = [&](const RenderTile& tile, const LayerRenderData* data, const auto& segments) {
auto& circleBucket = static_cast<CircleBucket&>(*data->bucket); auto& circleBucket = static_cast<CircleBucket&>(*data->bucket);
@@ -255,18 +257,37 @@ void RenderCircleLayer::removeTile(RenderPass renderPass, const OverscaledTileID
stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size();
} }
struct alignas(16) CircleInterpolateUBO {
float color_t;
float radius_t;
float blur_t;
float opacity_t;
float stroke_color_t;
float stroke_width_t;
float stroke_opacity_t;
float padding;
};
static_assert(sizeof(CircleInterpolateUBO) % 16 == 0);
static const std::string CircleShaderGroupName = "CircleShader";
static constexpr std::string_view CircleInterpolateUBOName = "CircleInterpolateUBO";
void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context, gfx::Context& context,
const TransformState& /*state*/, const TransformState& state,
[[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] const RenderTree& renderTree,
UniqueChangeRequestVec& changes) { UniqueChangeRequestVec& changes) {
std::unique_lock<std::mutex> guard(mutex); std::unique_lock<std::mutex> guard(mutex);
if (!renderTiles || renderTiles->empty()) { const auto removeAll = [&]() {
if (tileLayerGroup) { if (tileLayerGroup) {
stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount(); stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount();
tileLayerGroup->clearDrawables(); tileLayerGroup->clearDrawables();
} }
};
if (!renderTiles || renderTiles->empty()) {
removeAll();
return; return;
} }
@@ -280,8 +301,12 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true)); changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
} }
if (!circleShader) { if (!circleShaderGroup) {
circleShader = context.getGenericShader(shaders, "CircleShader"); circleShaderGroup = shaders.getShaderGroup(CircleShaderGroupName);
}
if (!circleShaderGroup) {
removeAll();
return;
} }
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size()); std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
@@ -308,13 +333,11 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
} }
}); });
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
for (const RenderTile& tile : *renderTiles) { for (const RenderTile& tile : *renderTiles) {
const auto& tileID = tile.getOverscaledTileID(); const auto& tileID = tile.getOverscaledTileID();
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
continue;
}
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass); const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
if (!renderData) { if (!renderData) {
removeTile(renderPass, tileID); removeTile(renderPass, tileID);
@@ -322,6 +345,45 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
} }
auto& bucket = static_cast<CircleBucket&>(*renderData->bucket); auto& bucket = static_cast<CircleBucket&>(*renderData->bucket);
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
float zoom = static_cast<float>(state.getZoom());
const CircleInterpolateUBO interpolateUBO = {
/* .color_t = */ std::get<0>(paintPropertyBinders.get<CircleColor>()->interpolationFactor(zoom)),
/* .radius_t = */ std::get<0>(paintPropertyBinders.get<CircleRadius>()->interpolationFactor(zoom)),
/* .blur_t = */ std::get<0>(paintPropertyBinders.get<CircleBlur>()->interpolationFactor(zoom)),
/* .opacity_t = */ std::get<0>(paintPropertyBinders.get<CircleOpacity>()->interpolationFactor(zoom)),
/* .stroke_color_t = */
std::get<0>(paintPropertyBinders.get<CircleStrokeColor>()->interpolationFactor(zoom)),
/* .stroke_width_t = */
std::get<0>(paintPropertyBinders.get<CircleStrokeWidth>()->interpolationFactor(zoom)),
/* .stroke_opacity_t = */
std::get<0>(paintPropertyBinders.get<CircleStrokeOpacity>()->interpolationFactor(zoom)),
/* .padding = */ 0};
tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) {
drawable.mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context);
});
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
continue;
}
circleVertexAttrs.clear();
auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintProperties<CircleColor,
CircleRadius,
CircleBlur,
CircleOpacity,
CircleStrokeColor,
CircleStrokeWidth,
CircleStrokeOpacity>(
paintPropertyBinders, evaluated);
auto circleShader = circleShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
if (!circleShader) {
continue;
}
std::vector<std::array<int16_t, 2>> rawVerts; std::vector<std::array<int16_t, 2>> rawVerts;
const auto buildVertices = [&]() { const auto buildVertices = [&]() {
@@ -333,94 +395,8 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
} }
}; };
circleVertexAttrs.clear();
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
if (auto& binder = paintPropertyBinders.get<CircleColor>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packedColor = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(
i, {packedColor[0], packedColor[1], packedColor[0], packedColor[1]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleRadius>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_radius")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& radius = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {radius[0], radius[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleBlur>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_blur")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& blur = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {blur[0], blur[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleOpacity>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& opacity = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeColor>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packedStrokeColor =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(
i, {packedStrokeColor[0], packedStrokeColor[1], packedStrokeColor[0], packedStrokeColor[1]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeWidth>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_width")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& strokeWidth = static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {strokeWidth[0], strokeWidth[0]});
}
}
}
if (auto& binder = paintPropertyBinders.get<CircleStrokeOpacity>()) {
const auto count = binder->getVertexCount();
if (auto& attr = circleVertexAttrs.getOrAdd("a_stroke_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& strokeOpacity =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {strokeOpacity[0], strokeOpacity[0]});
}
}
}
circleBuilder = context.createDrawableBuilder("circle"); circleBuilder = context.createDrawableBuilder("circle");
circleBuilder->setShader(circleShader); circleBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(circleShader));
circleBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); circleBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None);
circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
: gfx::DepthMaskType::ReadOnly); : gfx::DepthMaskType::ReadOnly);
@@ -432,14 +408,15 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
buildVertices(); buildVertices();
circleBuilder->addVertices(rawVerts, 0, rawVerts.size()); circleBuilder->addVertices(rawVerts, 0, rawVerts.size());
for (const auto& seg : bucket.segments) { circleBuilder->setSegments(gfx::Triangles(),
circleBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength); bucket.triangles.vector(),
} reinterpret_cast<const std::vector<Segment<void>>&>(bucket.segments));
circleBuilder->flush(); circleBuilder->flush();
for (auto& drawable : circleBuilder->clearDrawables()) { for (auto& drawable : circleBuilder->clearDrawables()) {
drawable->setTileID(tileID); drawable->setTileID(tileID);
drawable->mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded; ++stats.tileDrawablesAdded;

View File

@@ -8,6 +8,13 @@ namespace mbgl {
class CircleProgram; class CircleProgram;
namespace gfx {
class ShaderGroup;
class UniformBuffer;
using ShaderGroupPtr = std::shared_ptr<ShaderGroup>;
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
} // namespace gfx
class RenderCircleLayer final : public RenderLayer { class RenderCircleLayer final : public RenderLayer {
public: public:
explicit RenderCircleLayer(Immutable<style::CircleLayer::Impl>); explicit RenderCircleLayer(Immutable<style::CircleLayer::Impl>);
@@ -46,7 +53,7 @@ private:
// Programs // Programs
std::shared_ptr<CircleProgram> circleProgram; std::shared_ptr<CircleProgram> circleProgram;
gfx::ShaderProgramBasePtr circleShader; gfx::ShaderGroupPtr circleShaderGroup;
}; };
} // namespace mbgl } // namespace mbgl

View File

@@ -71,8 +71,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(fillExtrusionProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillExtrusionProgram)) return;
if (!parameters.shaders.populate(fillExtrusionPatternProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillExtrusionPatternProgram)) return;
const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).crossfade; const auto& crossfade = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).crossfade;

View File

@@ -84,10 +84,10 @@ bool RenderFillLayer::hasCrossfade() const {
void RenderFillLayer::render(PaintParameters& parameters) { void RenderFillLayer::render(PaintParameters& parameters) {
assert(renderTiles); assert(renderTiles);
if (!parameters.shaders.populate(fillProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillProgram)) return;
if (!parameters.shaders.populate(fillPatternProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillPatternProgram)) return;
if (!parameters.shaders.populate(fillOutlineProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillOutlineProgram)) return;
if (!parameters.shaders.populate(fillOutlinePatternProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(fillOutlinePatternProgram)) return;
if (unevaluated.get<FillPattern>().isUndefined()) { if (unevaluated.get<FillPattern>().isUndefined()) {
parameters.renderTileClippingMasks(renderTiles); parameters.renderTileClippingMasks(renderTiles);
@@ -301,10 +301,8 @@ bool bindFloat(const FloatBinder& binder, gfx::VertexAttributeArray& attrs, std:
const auto count = binder.getVertexCount(); const auto count = binder.getVertexCount();
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
for (std::size_t i = 0; i < count; ++i) { for (std::size_t i = 0; i < count; ++i) {
const auto& value = static_cast<const FloatVertex*>(binder.getVertexValue(i))->a1; const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
const auto& from = value; // TODO: should be two different values, right? attr->set(i, value);
const auto& to = value;
attr->set(i, util::concat(from, to));
} }
return true; return true;
} }
@@ -321,10 +319,8 @@ bool bindFloatPair(const FloatPairBinder& binder, gfx::VertexAttributeArray& att
// check that vertexVector.elements() == sum(segments.vertexLength) // check that vertexVector.elements() == sum(segments.vertexLength)
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
for (std::size_t i = 0; i < count; ++i) { for (std::size_t i = 0; i < count; ++i) {
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1; const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
const auto& from = value; // TODO: should be two different values, right? attr->set(i, value);
const auto& to = value;
attr->set(i, util::concat(from, to));
} }
return true; return true;
} }
@@ -341,10 +337,8 @@ bool bindColor(const ColorBinder& binder, gfx::VertexAttributeArray& attrs, std:
// check that vertexVector.elements() == sum(segments.vertexLength) // check that vertexVector.elements() == sum(segments.vertexLength)
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
for (std::size_t i = 0; i < count; ++i) { for (std::size_t i = 0; i < count; ++i) {
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1; const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
const auto& from = value; // TODO: should be two different values, right? attr->set(i, value);
const auto& to = value;
attr->set(i, util::concat(from, to));
} }
return true; return true;
} }
@@ -361,8 +355,8 @@ bool bindImage(const ImageBinder& binder, gfx::VertexAttributeArray& attrs, std:
// check that vertexVector.elements() == sum(segments.vertexLength) // check that vertexVector.elements() == sum(segments.vertexLength)
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) { if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
for (std::size_t i = 0; i < count; ++i) { for (std::size_t i = 0; i < count; ++i) {
const auto& value = static_cast<const UShortQuadVertex*>(binder.getVertexValue(i))->a1; const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
attr->set(i, util::cast<int32_t>(value)); attr->set(i, value);
} }
return true; return true;
} }

View File

@@ -69,8 +69,8 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(heatmapProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(heatmapProgram)) return;
if (!parameters.shaders.populate(heatmapTextureProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(heatmapTextureProgram)) return;
if (parameters.pass == RenderPass::Pass3D) { if (parameters.pass == RenderPass::Pass3D) {
const auto& viewportSize = parameters.staticData.backendSize; const auto& viewportSize = parameters.staticData.backendSize;

View File

@@ -79,8 +79,8 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) {
assert(renderTiles); assert(renderTiles);
if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D) return; if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D) return;
if (!parameters.shaders.populate(hillshadeProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(hillshadeProgram)) return;
if (!parameters.shaders.populate(hillshadePrepareProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(hillshadePrepareProgram)) return;
const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated;
auto draw = [&](const mat4& matrix, auto draw = [&](const mat4& matrix,

View File

@@ -95,10 +95,10 @@ void RenderLineLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(lineProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(lineProgram)) return;
if (!parameters.shaders.populate(lineGradientProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(lineGradientProgram)) return;
if (!parameters.shaders.populate(lineSDFProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(lineSDFProgram)) return;
if (!parameters.shaders.populate(linePatternProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(linePatternProgram)) return;
parameters.renderTileClippingMasks(renderTiles); parameters.renderTileClippingMasks(renderTiles);

View File

@@ -96,7 +96,7 @@ void RenderRasterLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(rasterProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(rasterProgram)) return;
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated; const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
RasterProgram::Binders paintAttributeData{evaluated, 0}; RasterProgram::Binders paintAttributeData{evaluated, 0};

View File

@@ -359,12 +359,12 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
return; return;
} }
if (!parameters.shaders.populate(programs.symbolIconProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.symbolIconProgram)) return;
if (!parameters.shaders.populate(programs.symbolSDFIconProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.symbolSDFIconProgram)) return;
if (!parameters.shaders.populate(programs.symbolSDFTextProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.symbolSDFTextProgram)) return;
if (!parameters.shaders.populate(programs.symbolTextAndIconProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.symbolTextAndIconProgram)) return;
if (!parameters.shaders.populate(programs.collisionBoxProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.collisionBoxProgram)) return;
if (!parameters.shaders.populate(programs.collisionCircleProgram)) return; if (!parameters.shaders.getLegacyGroup().populate(programs.collisionCircleProgram)) return;
const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined(); const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined();
std::multiset<RenderableSegment> renderableSegments; std::multiset<RenderableSegment> renderableSegments;

View File

@@ -138,7 +138,8 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun
clearStencil(); clearStencil();
} }
auto program = staticData.shaders->get<ClippingMaskProgram>(); auto program = staticData.shaders->getLegacyGroup().get<ClippingMaskProgram>();
if (!program) { if (!program) {
return; return;
} }

View File

@@ -1,21 +1,20 @@
#pragma once #pragma once
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/gfx/context.hpp> #include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/uniform.hpp> #include <mbgl/gfx/uniform.hpp>
#include <mbgl/gfx/attribute.hpp>
#include <mbgl/gfx/upload_pass.hpp> #include <mbgl/gfx/upload_pass.hpp>
#include <mbgl/layout/pattern_layout.hpp>
#include <mbgl/programs/attributes.hpp> #include <mbgl/programs/attributes.hpp>
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/renderer/paint_property_statistics.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/util/literal.hpp> #include <mbgl/util/literal.hpp>
#include <mbgl/util/type_list.hpp> #include <mbgl/util/type_list.hpp>
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
#include <mbgl/renderer/paint_property_statistics.hpp>
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <mbgl/util/variant.hpp> #include <mbgl/util/variant.hpp>
#include <mbgl/renderer/image_atlas.hpp> #include <mbgl/util/vectors.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <mbgl/layout/pattern_layout.hpp>
#include <bitset>
namespace mbgl { namespace mbgl {
@@ -38,6 +37,9 @@ template <class AttributeType>
using ZoomInterpolatedAttributeType = using ZoomInterpolatedAttributeType =
gfx::AttributeType<typename AttributeType::ElementType, AttributeType::Dimensions * 2>; gfx::AttributeType<typename AttributeType::ElementType, AttributeType::Dimensions * 2>;
template <class A>
using ZoomInterpolatedVertexType = typename gfx::detail::VertexType<ZoomInterpolatedAttributeType<A>>;
inline std::array<float, 1> attributeValue(float v) { inline std::array<float, 1> attributeValue(float v) {
return {{v}}; return {{v}};
} }
@@ -129,8 +131,8 @@ public:
const PossiblyEvaluatedType& currentValue) const = 0; const PossiblyEvaluatedType& currentValue) const = 0;
virtual std::size_t getVertexCount() const = 0; virtual std::size_t getVertexCount() const = 0;
virtual const /*std::tuple<ExpandToType<As, UniformValueType>...>&*/ void* getVertexValue(
std::size_t index) const = 0; virtual std::tuple<ZoomInterpolatedVertexType<As>...> getVertexValue(std::size_t index) const = 0;
static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue); static std::unique_ptr<PaintPropertyBinder> create(const PossiblyEvaluatedType& value, float zoom, T defaultValue);
@@ -170,10 +172,10 @@ public:
using BaseAttributeType = A; using BaseAttributeType = A;
using BaseVertex = gfx::VertexType<BaseAttributeType>; using BaseVertex = gfx::VertexType<BaseAttributeType>;
std::size_t getVertexCount() const override { return 1; } std::size_t getVertexCount() const override { return 0; }
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override {
convertedValue = BaseVertex{attributeValue(constant)}; std::tuple<ZoomInterpolatedVertexType<A>> getVertexValue(std::size_t) const override {
return &convertedValue; return {ZoomInterpolatedVertexType<A>{0}};
} }
private: private:
@@ -222,9 +224,10 @@ public:
return constantPatternPositions; return constantPatternPositions;
} }
std::size_t getVertexCount() const override { return 1; } std::size_t getVertexCount() const override { return 0; }
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override {
return &constantPatternPositions; std::tuple<ZoomInterpolatedVertexType<As>...> getVertexValue(std::size_t) const override {
return {ZoomInterpolatedVertexType<As>{0}...};
} }
private: private:
@@ -238,8 +241,6 @@ public:
using BaseAttributeType = A; using BaseAttributeType = A;
using BaseVertex = gfx::VertexType<BaseAttributeType>; using BaseVertex = gfx::VertexType<BaseAttributeType>;
using AttributeType = ZoomInterpolatedAttributeType<A>;
SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_) SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_)
: expression(std::move(expression_)), : expression(std::move(expression_)),
defaultValue(std::move(defaultValue_)) {} defaultValue(std::move(defaultValue_)) {}
@@ -326,8 +327,10 @@ public:
} }
std::size_t getVertexCount() const override { return vertexVector.elements(); } std::size_t getVertexCount() const override { return vertexVector.elements(); }
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t index) const override {
return &vertexVector.at(index); std::tuple<ZoomInterpolatedVertexType<A>> getVertexValue(std::size_t index) const override {
const BaseVertex& value = vertexVector.at(index);
return {ZoomInterpolatedVertexType<A>{concatenate(value.a1, value.a1)}};
} }
private: private:
@@ -450,8 +453,9 @@ public:
} }
std::size_t getVertexCount() const override { return vertexVector.elements(); } std::size_t getVertexCount() const override { return vertexVector.elements(); }
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t index) const override {
return &vertexVector.at(index); std::tuple<ZoomInterpolatedVertexType<A>> getVertexValue(std::size_t index) const override {
return {vertexVector.at(index)};
} }
private: private:
@@ -467,9 +471,6 @@ template <class T, class A1, class A2>
class CompositeCrossFadedPaintPropertyBinder final class CompositeCrossFadedPaintPropertyBinder final
: public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> { : public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
public: public:
using AttributeType = ZoomInterpolatedAttributeType<A1>;
using AttributeType2 = ZoomInterpolatedAttributeType<A2>;
using BaseAttributeType = A1; using BaseAttributeType = A1;
using BaseAttributeType2 = A2; using BaseAttributeType2 = A2;
@@ -564,8 +565,16 @@ public:
return {}; return {};
} }
std::size_t getVertexCount() const override { return 0; } std::size_t getVertexCount() const override { return patternToVertexVector.elements(); }
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override { return nullptr; }
std::tuple<ZoomInterpolatedVertexType<A1>, ZoomInterpolatedVertexType<A2>> getVertexValue(
std::size_t index) const override {
const Vertex& patternValue = patternToVertexVector.at(index);
const Vertex2& zoomValue = crossfade.fromScale == 2 ? zoomInVertexVector.at(index)
: zoomOutVertexVector.at(index);
return {ZoomInterpolatedVertexType<A1>{concatenate(patternValue.a1, patternValue.a1)},
ZoomInterpolatedVertexType<A2>{concatenate(zoomValue.a1, zoomValue.a1)}};
}
private: private:
style::PropertyExpression<T> expression; style::PropertyExpression<T> expression;

View File

@@ -171,7 +171,7 @@ void RenderTile::finishRender(PaintParameters& parameters) const {
static const style::Properties<>::PossiblyEvaluated properties{}; static const style::Properties<>::PossiblyEvaluated properties{};
static const DebugProgram::Binders paintAttributeData(properties, 0); static const DebugProgram::Binders paintAttributeData(properties, 0);
auto program = parameters.shaders.get<DebugProgram>(); auto program = parameters.shaders.getLegacyGroup().get<DebugProgram>();
if (!program) { if (!program) {
return; return;
} }

View File

@@ -39,7 +39,7 @@ void ImageSourceRenderData::render(PaintParameters& parameters) const {
static const style::Properties<>::PossiblyEvaluated properties{}; static const style::Properties<>::PossiblyEvaluated properties{};
static const DebugProgram::Binders paintAttributeData(properties, 0); static const DebugProgram::Binders paintAttributeData(properties, 0);
auto programInstance = parameters.shaders.get<DebugProgram>(); auto programInstance = parameters.shaders.getLegacyGroup().get<DebugProgram>();
if (!programInstance) { if (!programInstance) {
return; return;
} }

View File

@@ -39,6 +39,8 @@ public:
using AttributeList = TypeList<A>; using AttributeList = TypeList<A>;
using Uniform = U; using Uniform = U;
using UniformList = TypeList<U>; using UniformList = TypeList<U>;
static constexpr const std::array<std::string_view, 1> AttributeNames = {A::name()};
}; };
template <class T, class A1, class U1, class A2, class U2> template <class T, class A1, class U1, class A2, class U2>
@@ -56,6 +58,8 @@ public:
using AttributeList = TypeList<A1, A2>; using AttributeList = TypeList<A1, A2>;
using Uniform = U1; using Uniform = U1;
using UniformList = TypeList<U1, U2>; using UniformList = TypeList<U1, U2>;
static constexpr const std::array<std::string_view, 2> AttributeNames = {A1::name(), A2::name()};
}; };
template <class T> template <class T>

View File

@@ -82,7 +82,7 @@ class StubShaderConsumer {
public: public:
template <typename T> template <typename T>
uint32_t useShader(gfx::ShaderRegistry& registry) { uint32_t useShader(gfx::ShaderRegistry& registry) {
auto program = registry.get<T>(); auto program = registry.getLegacyGroup().get<T>();
return program ? program->draw() : 0; return program ? program->draw() : 0;
} }
}; };
@@ -94,17 +94,17 @@ TEST(ShaderRegistry, RegisterShader) {
gfx::ShaderRegistry registry; gfx::ShaderRegistry registry;
// The registry should start empty // The registry should start empty
ASSERT_FALSE(registry.isShader(std::string{StubProgram_1::Name})); ASSERT_FALSE(registry.getLegacyGroup().isShader(std::string{StubProgram_1::Name}));
// Register the program // Register the program
auto program = std::make_shared<StubProgram_1>(); auto program = std::make_shared<StubProgram_1>();
ASSERT_TRUE(registry.registerShader(program)); ASSERT_TRUE(registry.getLegacyGroup().registerShader(program));
// We can't re-register the same program name // We can't re-register the same program name
ASSERT_FALSE(registry.registerShader(program)); ASSERT_FALSE(registry.getLegacyGroup().registerShader(program));
// Ensure the shader is present in the registry now // Ensure the shader is present in the registry now
ASSERT_TRUE(registry.isShader(std::string{StubProgram_1::Name})); ASSERT_TRUE(registry.getLegacyGroup().isShader(std::string{StubProgram_1::Name}));
// And we can fetch it // And we can fetch it
ASSERT_EQ(registry.get<StubProgram_1>(), program); ASSERT_EQ(registry.getLegacyGroup().get<StubProgram_1>(), program);
// Make sure downcasting to program1 works as expected // Make sure downcasting to program1 works as expected
StubShaderConsumer consumer; StubShaderConsumer consumer;
@@ -115,13 +115,13 @@ TEST(ShaderRegistry, RegisterShader) {
TEST(ShaderRegistry, ReplaceShaderType) { TEST(ShaderRegistry, ReplaceShaderType) {
gfx::ShaderRegistry registry; gfx::ShaderRegistry registry;
ASSERT_FALSE(registry.isShader(std::string{StubProgram_1::Name})); ASSERT_FALSE(registry.getLegacyGroup().isShader(std::string{StubProgram_1::Name}));
auto program = std::make_shared<StubProgram_1>(); auto program = std::make_shared<StubProgram_1>();
ASSERT_TRUE(registry.registerShader(program)); ASSERT_TRUE(registry.getLegacyGroup().registerShader(program));
// Ensure the shader is present in the registry now // Ensure the shader is present in the registry now
ASSERT_TRUE(registry.isShader(std::string{StubProgram_1::Name})); ASSERT_TRUE(registry.getLegacyGroup().isShader(std::string{StubProgram_1::Name}));
ASSERT_TRUE(registry.isShader(std::string{program->typeName()})); ASSERT_TRUE(registry.getLegacyGroup().isShader(std::string{program->typeName()}));
// Make sure downcasting to program1 works as expected // Make sure downcasting to program1 works as expected
StubShaderConsumer consumer; StubShaderConsumer consumer;
@@ -131,13 +131,13 @@ TEST(ShaderRegistry, ReplaceShaderType) {
// and as such this replacement should fail as StubProgram_2 // and as such this replacement should fail as StubProgram_2
// has never been registered. // has never been registered.
auto program2 = std::make_shared<StubProgram_2>(); auto program2 = std::make_shared<StubProgram_2>();
ASSERT_FALSE(registry.replaceShader(program2)); ASSERT_FALSE(registry.getLegacyGroup().replaceShader(program2));
// Make a second instance of program1 and change the token // Make a second instance of program1 and change the token
auto program3 = std::make_shared<StubProgram_1>(); auto program3 = std::make_shared<StubProgram_1>();
program3->setToken(30); program3->setToken(30);
// Replace it in the registry // Replace it in the registry
ASSERT_TRUE(registry.replaceShader(program3)); ASSERT_TRUE(registry.getLegacyGroup().replaceShader(program3));
// Assert the new program downcasts from the registry as expected // Assert the new program downcasts from the registry as expected
ASSERT_EQ(consumer.useShader<StubProgram_1>(registry), 30); ASSERT_EQ(consumer.useShader<StubProgram_1>(registry), 30);
} }
@@ -156,28 +156,29 @@ TEST(ShaderRegistry, ShaderRTTI) {
TEST(ShaderRegistry, MultiRegister) { TEST(ShaderRegistry, MultiRegister) {
gfx::ShaderRegistry registry; gfx::ShaderRegistry registry;
ASSERT_TRUE(registry.registerShader(std::make_shared<StubProgram_1>())); ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>()));
ASSERT_TRUE(registry.registerShader(std::make_shared<StubProgram_1>(), "SecondProgram")); ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>(), "SecondProgram"));
// Default option, register as the type name // Default option, register as the type name
ASSERT_NE(registry.get<StubProgram_1>(), nullptr); ASSERT_NE(registry.getLegacyGroup().get<StubProgram_1>(), nullptr);
// Register with an explicit name // Register with an explicit name
ASSERT_NE(registry.get<StubProgram_1>("SecondProgram"), nullptr); ASSERT_NE(registry.getLegacyGroup().get<StubProgram_1>("SecondProgram"), nullptr);
ASSERT_NE(registry.get<StubProgram_1>(), registry.get<StubProgram_1>("SecondProgram")); ASSERT_NE(registry.getLegacyGroup().get<StubProgram_1>(),
registry.getLegacyGroup().get<StubProgram_1>("SecondProgram"));
} }
// Test fetching // Test fetching
TEST(ShaderRegistry, RegistryFetch) { TEST(ShaderRegistry, RegistryFetch) {
gfx::ShaderRegistry registry; gfx::ShaderRegistry registry;
ASSERT_TRUE(registry.registerShader(std::make_shared<StubProgram_1>())); ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>()));
ASSERT_TRUE(registry.registerShader(std::make_shared<StubProgram_1>(), "SecondProgram")); ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>(), "SecondProgram"));
std::shared_ptr<StubProgram_1> progA; std::shared_ptr<StubProgram_1> progA;
std::shared_ptr<StubProgram_1> progB; std::shared_ptr<StubProgram_1> progB;
ASSERT_TRUE(registry.populate(progA)); ASSERT_TRUE(registry.getLegacyGroup().populate(progA));
ASSERT_TRUE(registry.populate(progB, "SecondProgram")); ASSERT_TRUE(registry.getLegacyGroup().populate(progB, "SecondProgram"));
ASSERT_NE(progA, progB); ASSERT_NE(progA, progB);
ASSERT_NE(progA, nullptr); ASSERT_NE(progA, nullptr);
ASSERT_NE(progB, nullptr); ASSERT_NE(progB, nullptr);
@@ -188,17 +189,17 @@ TEST(ShaderRegistry, NamedReplace) {
gfx::ShaderRegistry registry; gfx::ShaderRegistry registry;
// Register // Register
ASSERT_TRUE(registry.registerShader(std::make_shared<StubProgram_1>(), "CustomName")); ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>(), "CustomName"));
std::shared_ptr<StubProgram_1> progA; std::shared_ptr<StubProgram_1> progA;
ASSERT_TRUE(registry.populate(progA, "CustomName")); ASSERT_TRUE(registry.getLegacyGroup().populate(progA, "CustomName"));
ASSERT_NE(progA, nullptr); ASSERT_NE(progA, nullptr);
// Replace it with a new instance // Replace it with a new instance
ASSERT_TRUE(registry.replaceShader(std::make_shared<StubProgram_1>(), "CustomName")); ASSERT_TRUE(registry.getLegacyGroup().replaceShader(std::make_shared<StubProgram_1>(), "CustomName"));
std::shared_ptr<StubProgram_1> progB; std::shared_ptr<StubProgram_1> progB;
ASSERT_TRUE(registry.populate(progB, "CustomName")); ASSERT_TRUE(registry.getLegacyGroup().populate(progB, "CustomName"));
ASSERT_NE(progB, nullptr); ASSERT_NE(progB, nullptr);
// Should be different instances // Should be different instances
@@ -213,7 +214,7 @@ TEST(ShaderRegistry, GLSLReplacement_NoOp) {
// Just replace with a default instance // Just replace with a default instance
observer.registerShaders = [&](gfx::ShaderRegistry& registry) { observer.registerShaders = [&](gfx::ShaderRegistry& registry) {
if (!registry.replaceShader(std::make_shared<FillProgram>(ProgramParameters(1.0f, false)))) { if (!registry.getLegacyGroup().replaceShader(std::make_shared<FillProgram>(ProgramParameters(1.0f, false)))) {
throw std::runtime_error("Failed to register shader!"); throw std::runtime_error("Failed to register shader!");
} }
}; };
@@ -239,7 +240,7 @@ TEST(ShaderRegistry, GLSLReplacement1) {
// Replace with an instance that only renders blue // Replace with an instance that only renders blue
observer.registerShaders = [&](gfx::ShaderRegistry& registry) { observer.registerShaders = [&](gfx::ShaderRegistry& registry) {
if (!registry.replaceShader(std::make_shared<FillProgram>( if (!registry.getLegacyGroup().replaceShader(std::make_shared<FillProgram>(
ProgramParameters(1.0f, false) ProgramParameters(1.0f, false)
.withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL, .withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL,
"", "",
@@ -273,7 +274,7 @@ TEST(ShaderRegistry, GLSLReplacement2) {
// Replace with an instance that adds some red and green // Replace with an instance that adds some red and green
observer.registerShaders = [&](gfx::ShaderRegistry& registry) { observer.registerShaders = [&](gfx::ShaderRegistry& registry) {
if (!registry.replaceShader(std::make_shared<FillProgram>( if (!registry.getLegacyGroup().replaceShader(std::make_shared<FillProgram>(
ProgramParameters(1.0f, false) ProgramParameters(1.0f, false)
.withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL, .withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL,
"", "",