Circle layer final (#1227)
This commit is contained in:
committed by
Bart Louwers
parent
008f584b9e
commit
52b9e099e5
@@ -148,6 +148,7 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/renderable.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/shader_group.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader_registry.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/shader.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_state.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/mtl/shader_program_mtl.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/renderer_backend.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/stencil_mode.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/texture.hpp
|
||||
|
||||
@@ -41,6 +41,7 @@ enum class AttributeDataType : uint8_t {
|
||||
UShort2,
|
||||
UShort3,
|
||||
UShort4,
|
||||
UShort8,
|
||||
|
||||
Int,
|
||||
Int2,
|
||||
|
||||
153
include/mbgl/gfx/shader_group.hpp
Normal file
153
include/mbgl/gfx/shader_group.hpp
Normal 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
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/shader.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -10,8 +10,10 @@
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
/// @brief A ShaderRegistry contains a collection of gfx::Shader instances.
|
||||
/// Using the registry, shaders may be dynamically registered or replaced
|
||||
using ShaderGroupPtr = std::shared_ptr<gfx::ShaderGroup>;
|
||||
|
||||
/// @brief A ShaderRegistry contains a collection of gfx::ShaderGroup instances.
|
||||
/// Using the registry, shader groups may be dynamically registered or replaced
|
||||
/// at runtime.
|
||||
class ShaderRegistry {
|
||||
public:
|
||||
@@ -22,120 +24,44 @@ public:
|
||||
ShaderRegistry& operator=(ShaderRegistry&&) noexcept = delete;
|
||||
virtual ~ShaderRegistry() = default;
|
||||
|
||||
/// @brief Checks if a shader exists in the registry 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 the legacy shader group.
|
||||
/// @return A `gfx::ShaderGroup`
|
||||
[[nodiscard]] ShaderGroup& getLegacyGroup() noexcept;
|
||||
|
||||
/// @brief Get a shader from the registry by name.
|
||||
/// @param shaderName Name of shader
|
||||
/// @return A `gfx::Shader` or `nullptr` if no shader is found with the
|
||||
/// @brief Checks if a shader group exists in the registry for the given name.
|
||||
/// @param shaderGroupName Name of shader group
|
||||
/// @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
|
||||
[[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
|
||||
/// instance. Shader type-names must match.
|
||||
/// @param shader A `gfx::Shader`. The ShaderRegistry will take ownership.
|
||||
/// @return True if a match was found and the shader was replaced, false
|
||||
/// @brief Replace a matching shader group in the registry with the provided
|
||||
/// name.
|
||||
/// @param shaderGroup A `gfx::ShaderGroup`. The ShaderRegistry will take ownership.
|
||||
/// @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.
|
||||
[[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
|
||||
/// instance. Shader type-names must match.
|
||||
/// This variant replaces by explicit name.
|
||||
/// @param shader A `gfx::Shader`. The ShaderRegistry 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 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
|
||||
/// @brief Register a new shader group with the registry for the given name.
|
||||
/// If a shader group is present in the registry with a conflicting name,
|
||||
/// registration will fail.
|
||||
/// @param shaderGroup A `gfx::ShaderGroup` to register. The ShaderRegistry will
|
||||
/// 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.
|
||||
[[nodiscard]] virtual bool registerShader(std::shared_ptr<Shader>&& shader) 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;
|
||||
}
|
||||
[[nodiscard]] virtual bool registerShaderGroup(ShaderGroupPtr&& shaderGroup,
|
||||
const std::string& shaderGroupName) noexcept;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<gfx::Shader>> programs;
|
||||
mutable std::shared_mutex programLock;
|
||||
gfx::ShaderGroup legacyGroup;
|
||||
std::unordered_map<std::string, ShaderGroupPtr> shaderGroups;
|
||||
mutable std::shared_mutex shaderGroupLock;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -33,8 +33,10 @@ public:
|
||||
using int2 = std::array<std::int32_t, 2>;
|
||||
using int3 = std::array<std::int32_t, 3>;
|
||||
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_)
|
||||
: index(index_),
|
||||
@@ -106,6 +108,19 @@ public:
|
||||
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:
|
||||
VertexAttribute& operator=(const VertexAttribute&) = default;
|
||||
VertexAttribute& operator=(VertexAttribute&& other) {
|
||||
@@ -219,6 +234,33 @@ public:
|
||||
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:
|
||||
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>()));
|
||||
|
||||
53
include/mbgl/shaders/gl/shader_group_gl.hpp
Normal file
53
include/mbgl/shaders/gl/shader_group_gl.hpp
Normal 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
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -10,4 +11,14 @@ using vec3f = std::array<float, 3>;
|
||||
using vec3i = std::array<int, 3>;
|
||||
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
|
||||
|
||||
@@ -63,6 +63,8 @@ struct AttributeDataTypeOf<uint16_t, 3> : std::integral_constant<AttributeDataTy
|
||||
template <>
|
||||
struct AttributeDataTypeOf<uint16_t, 4> : std::integral_constant<AttributeDataType, AttributeDataType::UShort4> {};
|
||||
template <>
|
||||
struct AttributeDataTypeOf<uint16_t, 8> : std::integral_constant<AttributeDataType, AttributeDataType::UShort8> {};
|
||||
template <>
|
||||
struct AttributeDataTypeOf<int32_t, 1> : std::integral_constant<AttributeDataType, AttributeDataType::Int> {};
|
||||
template <>
|
||||
struct AttributeDataTypeOf<int32_t, 2> : std::integral_constant<AttributeDataType, AttributeDataType::Int2> {};
|
||||
|
||||
51
src/mbgl/gfx/shader_group.cpp
Normal file
51
src/mbgl/gfx/shader_group.cpp
Normal 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
|
||||
@@ -1,51 +1,48 @@
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/gfx/shader.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
ShaderRegistry::ShaderRegistry() {}
|
||||
ShaderRegistry::ShaderRegistry()
|
||||
: legacyGroup() {}
|
||||
|
||||
bool ShaderRegistry::isShader(const std::string& shaderName) const noexcept {
|
||||
std::shared_lock<std::shared_mutex> readerLock(programLock);
|
||||
return programs.find(shaderName) != programs.end();
|
||||
ShaderGroup& ShaderRegistry::getLegacyGroup() noexcept {
|
||||
return legacyGroup;
|
||||
}
|
||||
|
||||
const std::shared_ptr<gfx::Shader> ShaderRegistry::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()) {
|
||||
bool ShaderRegistry::isShaderGroup(const std::string& shaderGroupName) const noexcept {
|
||||
std::shared_lock<std::shared_mutex> readerLock(shaderGroupLock);
|
||||
return shaderGroups.find(shaderGroupName) != shaderGroups.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 it->second;
|
||||
}
|
||||
|
||||
bool ShaderRegistry::replaceShader(std::shared_ptr<gfx::Shader>&& shader) noexcept {
|
||||
return replaceShader(std::move(shader), std::string{shader->typeName()});
|
||||
}
|
||||
|
||||
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()) {
|
||||
bool ShaderRegistry::replaceShader(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
|
||||
if (shaderGroups.find(shaderGroupName) == shaderGroups.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
programs[shaderName] = std::move(shader);
|
||||
shaderGroups[shaderGroupName] = std::move(shader);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderRegistry::registerShader(std::shared_ptr<gfx::Shader>&& shader) noexcept {
|
||||
return registerShader(std::move(shader), std::string{shader->typeName()});
|
||||
}
|
||||
|
||||
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()) {
|
||||
bool ShaderRegistry::registerShaderGroup(ShaderGroupPtr&& shader, const std::string& shaderGroupName) noexcept {
|
||||
std::unique_lock<std::shared_mutex> writerLock(shaderGroupLock);
|
||||
if (shaderGroups.find(shaderGroupName) != shaderGroups.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
programs.emplace(shaderName, std::move(shader));
|
||||
shaderGroups.emplace(shaderGroupName, std::move(shader));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
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) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/extension.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 <cassert>
|
||||
@@ -69,10 +69,9 @@ RendererBackend::~RendererBackend() = default;
|
||||
/// @brief Register a list of types with a shader registry instance
|
||||
/// @tparam ...ShaderID Pack of BuiltIn:: shader IDs
|
||||
/// @param registry A shader registry instance
|
||||
/// @param glContext The GL context instance
|
||||
/// @param programParameters ProgramParameters used to initialize each instance
|
||||
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
|
||||
/// 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
|
||||
/// 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>;
|
||||
if (!registry.registerShader(gl::ShaderProgramGL::create(glContext, programParameters, name, vert, frag),
|
||||
name)) {
|
||||
if (!registry.registerShaderGroup(std::make_shared<ShaderGroupGL<ShaderID>>(programParameters), Ty::name)) {
|
||||
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::FillOutlinePatternShader,
|
||||
shaders::BuiltIn::FillPatternShader,
|
||||
shaders::BuiltIn::RasterShader>(shaders, static_cast<gl::Context&>(*context), programParameters);
|
||||
shaders::BuiltIn::RasterShader>(shaders, programParameters);
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -37,7 +37,7 @@ void registerTypes(gfx::ShaderRegistry& registry, const ProgramParameters& progr
|
||||
if (!expr) {
|
||||
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_))),
|
||||
...);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,17 +40,9 @@ struct alignas(16) CircleEvaluatedPropsUBO {
|
||||
};
|
||||
static_assert(sizeof(CircleEvaluatedPropsUBO) % 16 == 0);
|
||||
|
||||
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 constexpr std::string_view CircleDrawableUBOName = "CircleDrawableUBO";
|
||||
static constexpr std::string_view CirclePaintParamsUBOName = "CirclePaintParamsUBO";
|
||||
static constexpr std::string_view CircleEvaluatedPropsUBOName = "CircleEvaluatedPropsUBO";
|
||||
|
||||
void CircleLayerTweaker::execute(LayerGroup& layerGroup,
|
||||
const RenderTree& renderTree,
|
||||
@@ -66,9 +58,10 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
|
||||
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
|
||||
#endif
|
||||
|
||||
CirclePaintParamsUBO paintParamsUBO;
|
||||
paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance();
|
||||
paintParamsUBO.device_pixel_ratio = parameters.pixelRatio;
|
||||
CirclePaintParamsUBO paintParamsUBO = {
|
||||
/* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(),
|
||||
/* .device_pixel_ratio = */ parameters.pixelRatio,
|
||||
/* .padding = */ {0}};
|
||||
|
||||
if (!paintParamsUniformBuffer) {
|
||||
paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO));
|
||||
@@ -79,39 +72,25 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
|
||||
const bool pitchWithMap = evaluated.get<CirclePitchAlignment>() == AlignmentType::Map;
|
||||
|
||||
if (!evaluatedPropsUniformBuffer) {
|
||||
CircleEvaluatedPropsUBO evaluatedPropsUBO;
|
||||
evaluatedPropsUBO.color = evaluated.get<CircleColor>().constantOr(Color());
|
||||
evaluatedPropsUBO.radius = evaluated.get<CircleRadius>().constantOr(0);
|
||||
evaluatedPropsUBO.blur = evaluated.get<CircleBlur>().constantOr(0);
|
||||
evaluatedPropsUBO.opacity = evaluated.get<CircleOpacity>().constantOr(0);
|
||||
evaluatedPropsUBO.stroke_color = evaluated.get<CircleStrokeColor>().constantOr(Color());
|
||||
evaluatedPropsUBO.stroke_width = evaluated.get<CircleStrokeWidth>().constantOr(0);
|
||||
evaluatedPropsUBO.stroke_opacity = evaluated.get<CircleStrokeOpacity>().constantOr(0);
|
||||
evaluatedPropsUBO.scale_with_map = evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map;
|
||||
evaluatedPropsUBO.pitch_with_map = pitchWithMap;
|
||||
CircleEvaluatedPropsUBO evaluatedPropsUBO = {
|
||||
/* .color = */ evaluated.get<CircleColor>().constantOr(CircleColor::defaultValue()),
|
||||
/* .stroke_color = */ evaluated.get<CircleStrokeColor>().constantOr(CircleStrokeColor::defaultValue()),
|
||||
/* .radius = */ evaluated.get<CircleRadius>().constantOr(CircleRadius::defaultValue()),
|
||||
/* .blur = */ evaluated.get<CircleBlur>().constantOr(CircleBlur::defaultValue()),
|
||||
/* .opacity = */ evaluated.get<CircleOpacity>().constantOr(CircleOpacity::defaultValue()),
|
||||
/* .stroke_width = */ evaluated.get<CircleStrokeWidth>().constantOr(CircleStrokeWidth::defaultValue()),
|
||||
/* .stroke_opacity = */
|
||||
evaluated.get<CircleStrokeOpacity>().constantOr(CircleStrokeOpacity::defaultValue()),
|
||||
/* .scale_with_map = */ evaluated.get<CirclePitchScale>() == CirclePitchScaleType::Map,
|
||||
/* .pitch_with_map = */ pitchWithMap,
|
||||
/* .padding = */ 0};
|
||||
evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&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) {
|
||||
drawable.mutableUniformBuffers().addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer);
|
||||
drawable.mutableUniformBuffers().addOrReplace("CircleEvaluatedPropsUBO", evaluatedPropsUniformBuffer);
|
||||
drawable.mutableUniformBuffers().addOrReplace("CircleInterpolateUBO", interpolateUniformBuffer);
|
||||
drawable.mutableUniformBuffers().addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer);
|
||||
drawable.mutableUniformBuffers().addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
|
||||
|
||||
if (!drawable.getTileID()) {
|
||||
return;
|
||||
@@ -124,20 +103,15 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup,
|
||||
const auto matrix = getTileMatrix(
|
||||
tileID, renderTree, parameters.state, translation, anchor, inViewportPixelUnits);
|
||||
|
||||
CircleDrawableUBO drawableUBO;
|
||||
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;
|
||||
const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()));
|
||||
|
||||
if (auto& ubo = drawable.mutableUniformBuffers().get("CircleDrawableUBO")) {
|
||||
ubo->update(&drawableUBO, sizeof(drawableUBO));
|
||||
} else {
|
||||
auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO));
|
||||
drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer);
|
||||
}
|
||||
CircleDrawableUBO drawableUBO = {
|
||||
/* .matrix = */ util::cast<float>(matrix),
|
||||
/* .extrude_scale = */
|
||||
pitchWithMap ? std::array<float, 2>{{pixelsToTileUnits}} : parameters.pixelsToGLUnits,
|
||||
/* .padding = */ {0}};
|
||||
|
||||
drawable.mutableUniformBuffers().createOrUpdate(CircleDrawableUBOName, &drawableUBO, parameters.context);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,8 @@ public:
|
||||
void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override;
|
||||
|
||||
protected:
|
||||
gfx::UniformBufferPtr paintParamsUniformBuffer = nullptr;
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr;
|
||||
gfx::UniformBufferPtr interpolateUniformBuffer = nullptr;
|
||||
gfx::UniformBufferPtr paintParamsUniformBuffer;
|
||||
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -79,8 +79,8 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) {
|
||||
// is drawn with glClear rather than this method.
|
||||
|
||||
// Ensure programs are available
|
||||
if (!parameters.shaders.populate(backgroundProgram)) return;
|
||||
if (!parameters.shaders.populate(backgroundPatternProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(backgroundProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(backgroundPatternProgram)) return;
|
||||
|
||||
const Properties<>::PossiblyEvaluated properties;
|
||||
const BackgroundProgram::Binders paintAttributeData(properties, 0);
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
#include <mbgl/programs/circle_program.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/style/layers/circle_layer_impl.hpp>
|
||||
#include <mbgl/shaders/shader_program_base.hpp>
|
||||
#include <mbgl/geometry/feature_index.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/shader_group.hpp>
|
||||
#include <mbgl/gfx/shader_registry.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/intersection_tests.hpp>
|
||||
@@ -92,7 +94,7 @@ void RenderCircleLayer::render(PaintParameters& parameters) {
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
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,
|
||||
gfx::Context& context,
|
||||
const TransformState& /*state*/,
|
||||
const TransformState& state,
|
||||
[[maybe_unused]] const RenderTree& renderTree,
|
||||
UniqueChangeRequestVec& changes) {
|
||||
std::unique_lock<std::mutex> guard(mutex);
|
||||
|
||||
if (!renderTiles || renderTiles->empty()) {
|
||||
const auto removeAll = [&]() {
|
||||
if (tileLayerGroup) {
|
||||
stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount();
|
||||
tileLayerGroup->clearDrawables();
|
||||
}
|
||||
};
|
||||
|
||||
if (!renderTiles || renderTiles->empty()) {
|
||||
removeAll();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -280,8 +301,12 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
|
||||
}
|
||||
|
||||
if (!circleShader) {
|
||||
circleShader = context.getGenericShader(shaders, "CircleShader");
|
||||
if (!circleShaderGroup) {
|
||||
circleShaderGroup = shaders.getShaderGroup(CircleShaderGroupName);
|
||||
}
|
||||
if (!circleShaderGroup) {
|
||||
removeAll();
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
const auto& tileID = tile.getOverscaledTileID();
|
||||
|
||||
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const LayerRenderData* renderData = getRenderDataForPass(tile, renderPass);
|
||||
if (!renderData) {
|
||||
removeTile(renderPass, tileID);
|
||||
@@ -322,6 +345,45 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
}
|
||||
|
||||
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;
|
||||
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->setShader(circleShader);
|
||||
circleBuilder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(circleShader));
|
||||
circleBuilder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None);
|
||||
circleBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
|
||||
: gfx::DepthMaskType::ReadOnly);
|
||||
@@ -432,14 +408,15 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
|
||||
buildVertices();
|
||||
circleBuilder->addVertices(rawVerts, 0, rawVerts.size());
|
||||
|
||||
for (const auto& seg : bucket.segments) {
|
||||
circleBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
|
||||
}
|
||||
circleBuilder->setSegments(gfx::Triangles(),
|
||||
bucket.triangles.vector(),
|
||||
reinterpret_cast<const std::vector<Segment<void>>&>(bucket.segments));
|
||||
|
||||
circleBuilder->flush();
|
||||
|
||||
for (auto& drawable : circleBuilder->clearDrawables()) {
|
||||
drawable->setTileID(tileID);
|
||||
drawable->mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context);
|
||||
|
||||
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
|
||||
++stats.tileDrawablesAdded;
|
||||
|
||||
@@ -8,6 +8,13 @@ namespace mbgl {
|
||||
|
||||
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 {
|
||||
public:
|
||||
explicit RenderCircleLayer(Immutable<style::CircleLayer::Impl>);
|
||||
@@ -46,7 +53,7 @@ private:
|
||||
// Programs
|
||||
std::shared_ptr<CircleProgram> circleProgram;
|
||||
|
||||
gfx::ShaderProgramBasePtr circleShader;
|
||||
gfx::ShaderGroupPtr circleShaderGroup;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -71,8 +71,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parameters.shaders.populate(fillExtrusionProgram)) return;
|
||||
if (!parameters.shaders.populate(fillExtrusionPatternProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillExtrusionProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillExtrusionPatternProgram)) return;
|
||||
|
||||
const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
const auto& crossfade = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).crossfade;
|
||||
|
||||
@@ -84,10 +84,10 @@ bool RenderFillLayer::hasCrossfade() const {
|
||||
void RenderFillLayer::render(PaintParameters& parameters) {
|
||||
assert(renderTiles);
|
||||
|
||||
if (!parameters.shaders.populate(fillProgram)) return;
|
||||
if (!parameters.shaders.populate(fillPatternProgram)) return;
|
||||
if (!parameters.shaders.populate(fillOutlineProgram)) return;
|
||||
if (!parameters.shaders.populate(fillOutlinePatternProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillPatternProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillOutlineProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(fillOutlinePatternProgram)) return;
|
||||
|
||||
if (unevaluated.get<FillPattern>().isUndefined()) {
|
||||
parameters.renderTileClippingMasks(renderTiles);
|
||||
@@ -301,10 +301,8 @@ bool bindFloat(const FloatBinder& binder, gfx::VertexAttributeArray& attrs, std:
|
||||
const auto count = binder.getVertexCount();
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
|
||||
attr->set(i, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -321,10 +319,8 @@ bool bindFloatPair(const FloatPairBinder& binder, gfx::VertexAttributeArray& att
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
|
||||
attr->set(i, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -341,10 +337,8 @@ bool bindColor(const ColorBinder& binder, gfx::VertexAttributeArray& attrs, std:
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const FloatPairVertex*>(binder.getVertexValue(i))->a1;
|
||||
const auto& from = value; // TODO: should be two different values, right?
|
||||
const auto& to = value;
|
||||
attr->set(i, util::concat(from, to));
|
||||
const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
|
||||
attr->set(i, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -361,8 +355,8 @@ bool bindImage(const ImageBinder& binder, gfx::VertexAttributeArray& attrs, std:
|
||||
// check that vertexVector.elements() == sum(segments.vertexLength)
|
||||
if (auto& attr = attrs.getOrAdd(std::move(attributeName))) {
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
const auto& value = static_cast<const UShortQuadVertex*>(binder.getVertexValue(i))->a1;
|
||||
attr->set(i, util::cast<int32_t>(value));
|
||||
const auto& value = std::get<0>(binder.getVertexValue(i)).a1;
|
||||
attr->set(i, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parameters.shaders.populate(heatmapProgram)) return;
|
||||
if (!parameters.shaders.populate(heatmapTextureProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(heatmapProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(heatmapTextureProgram)) return;
|
||||
|
||||
if (parameters.pass == RenderPass::Pass3D) {
|
||||
const auto& viewportSize = parameters.staticData.backendSize;
|
||||
|
||||
@@ -79,8 +79,8 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) {
|
||||
assert(renderTiles);
|
||||
if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D) return;
|
||||
|
||||
if (!parameters.shaders.populate(hillshadeProgram)) return;
|
||||
if (!parameters.shaders.populate(hillshadePrepareProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(hillshadeProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(hillshadePrepareProgram)) return;
|
||||
|
||||
const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
auto draw = [&](const mat4& matrix,
|
||||
|
||||
@@ -95,10 +95,10 @@ void RenderLineLayer::render(PaintParameters& parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parameters.shaders.populate(lineProgram)) return;
|
||||
if (!parameters.shaders.populate(lineGradientProgram)) return;
|
||||
if (!parameters.shaders.populate(lineSDFProgram)) return;
|
||||
if (!parameters.shaders.populate(linePatternProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(lineProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(lineGradientProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(lineSDFProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(linePatternProgram)) return;
|
||||
|
||||
parameters.renderTileClippingMasks(renderTiles);
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ void RenderRasterLayer::render(PaintParameters& parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parameters.shaders.populate(rasterProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(rasterProgram)) return;
|
||||
|
||||
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
|
||||
RasterProgram::Binders paintAttributeData{evaluated, 0};
|
||||
|
||||
@@ -359,12 +359,12 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parameters.shaders.populate(programs.symbolIconProgram)) return;
|
||||
if (!parameters.shaders.populate(programs.symbolSDFIconProgram)) return;
|
||||
if (!parameters.shaders.populate(programs.symbolSDFTextProgram)) return;
|
||||
if (!parameters.shaders.populate(programs.symbolTextAndIconProgram)) return;
|
||||
if (!parameters.shaders.populate(programs.collisionBoxProgram)) return;
|
||||
if (!parameters.shaders.populate(programs.collisionCircleProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.symbolIconProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.symbolSDFIconProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.symbolSDFTextProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.symbolTextAndIconProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.collisionBoxProgram)) return;
|
||||
if (!parameters.shaders.getLegacyGroup().populate(programs.collisionCircleProgram)) return;
|
||||
|
||||
const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined();
|
||||
std::multiset<RenderableSegment> renderableSegments;
|
||||
|
||||
@@ -138,7 +138,8 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun
|
||||
clearStencil();
|
||||
}
|
||||
|
||||
auto program = staticData.shaders->get<ClippingMaskProgram>();
|
||||
auto program = staticData.shaders->getLegacyGroup().get<ClippingMaskProgram>();
|
||||
|
||||
if (!program) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/attribute.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/uniform.hpp>
|
||||
#include <mbgl/gfx/attribute.hpp>
|
||||
#include <mbgl/gfx/upload_pass.hpp>
|
||||
#include <mbgl/layout/pattern_layout.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/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/renderer/image_atlas.hpp>
|
||||
#include <mbgl/util/indexed_tuple.hpp>
|
||||
#include <mbgl/layout/pattern_layout.hpp>
|
||||
|
||||
#include <bitset>
|
||||
#include <mbgl/util/vectors.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -38,6 +37,9 @@ template <class AttributeType>
|
||||
using ZoomInterpolatedAttributeType =
|
||||
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) {
|
||||
return {{v}};
|
||||
}
|
||||
@@ -129,8 +131,8 @@ public:
|
||||
const PossiblyEvaluatedType& currentValue) 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);
|
||||
|
||||
@@ -170,10 +172,10 @@ public:
|
||||
using BaseAttributeType = A;
|
||||
using BaseVertex = gfx::VertexType<BaseAttributeType>;
|
||||
|
||||
std::size_t getVertexCount() const override { return 1; }
|
||||
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override {
|
||||
convertedValue = BaseVertex{attributeValue(constant)};
|
||||
return &convertedValue;
|
||||
std::size_t getVertexCount() const override { return 0; }
|
||||
|
||||
std::tuple<ZoomInterpolatedVertexType<A>> getVertexValue(std::size_t) const override {
|
||||
return {ZoomInterpolatedVertexType<A>{0}};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -222,9 +224,10 @@ public:
|
||||
return constantPatternPositions;
|
||||
}
|
||||
|
||||
std::size_t getVertexCount() const override { return 1; }
|
||||
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override {
|
||||
return &constantPatternPositions;
|
||||
std::size_t getVertexCount() const override { return 0; }
|
||||
|
||||
std::tuple<ZoomInterpolatedVertexType<As>...> getVertexValue(std::size_t) const override {
|
||||
return {ZoomInterpolatedVertexType<As>{0}...};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -238,8 +241,6 @@ public:
|
||||
using BaseAttributeType = A;
|
||||
using BaseVertex = gfx::VertexType<BaseAttributeType>;
|
||||
|
||||
using AttributeType = ZoomInterpolatedAttributeType<A>;
|
||||
|
||||
SourceFunctionPaintPropertyBinder(style::PropertyExpression<T> expression_, T defaultValue_)
|
||||
: expression(std::move(expression_)),
|
||||
defaultValue(std::move(defaultValue_)) {}
|
||||
@@ -326,8 +327,10 @@ public:
|
||||
}
|
||||
|
||||
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:
|
||||
@@ -450,8 +453,9 @@ public:
|
||||
}
|
||||
|
||||
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:
|
||||
@@ -467,9 +471,6 @@ template <class T, class A1, class A2>
|
||||
class CompositeCrossFadedPaintPropertyBinder final
|
||||
: public PaintPropertyBinder<T, std::array<uint16_t, 4>, PossiblyEvaluatedPropertyValue<Faded<T>>, A1, A2> {
|
||||
public:
|
||||
using AttributeType = ZoomInterpolatedAttributeType<A1>;
|
||||
using AttributeType2 = ZoomInterpolatedAttributeType<A2>;
|
||||
|
||||
using BaseAttributeType = A1;
|
||||
using BaseAttributeType2 = A2;
|
||||
|
||||
@@ -564,8 +565,16 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
std::size_t getVertexCount() const override { return 0; }
|
||||
const /*std::tuple<ExpandToType<A, T>>&*/ void* getVertexValue(std::size_t) const override { return nullptr; }
|
||||
std::size_t getVertexCount() const override { return patternToVertexVector.elements(); }
|
||||
|
||||
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:
|
||||
style::PropertyExpression<T> expression;
|
||||
|
||||
@@ -171,7 +171,7 @@ void RenderTile::finishRender(PaintParameters& parameters) const {
|
||||
static const style::Properties<>::PossiblyEvaluated properties{};
|
||||
static const DebugProgram::Binders paintAttributeData(properties, 0);
|
||||
|
||||
auto program = parameters.shaders.get<DebugProgram>();
|
||||
auto program = parameters.shaders.getLegacyGroup().get<DebugProgram>();
|
||||
if (!program) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void ImageSourceRenderData::render(PaintParameters& parameters) const {
|
||||
static const style::Properties<>::PossiblyEvaluated properties{};
|
||||
static const DebugProgram::Binders paintAttributeData(properties, 0);
|
||||
|
||||
auto programInstance = parameters.shaders.get<DebugProgram>();
|
||||
auto programInstance = parameters.shaders.getLegacyGroup().get<DebugProgram>();
|
||||
if (!programInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
using AttributeList = TypeList<A>;
|
||||
using Uniform = 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>
|
||||
@@ -56,6 +58,8 @@ public:
|
||||
using AttributeList = TypeList<A1, A2>;
|
||||
using Uniform = U1;
|
||||
using UniformList = TypeList<U1, U2>;
|
||||
|
||||
static constexpr const std::array<std::string_view, 2> AttributeNames = {A1::name(), A2::name()};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -82,7 +82,7 @@ class StubShaderConsumer {
|
||||
public:
|
||||
template <typename T>
|
||||
uint32_t useShader(gfx::ShaderRegistry& registry) {
|
||||
auto program = registry.get<T>();
|
||||
auto program = registry.getLegacyGroup().get<T>();
|
||||
return program ? program->draw() : 0;
|
||||
}
|
||||
};
|
||||
@@ -94,17 +94,17 @@ TEST(ShaderRegistry, RegisterShader) {
|
||||
gfx::ShaderRegistry registry;
|
||||
|
||||
// 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
|
||||
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
|
||||
ASSERT_FALSE(registry.registerShader(program));
|
||||
ASSERT_FALSE(registry.getLegacyGroup().registerShader(program));
|
||||
// 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
|
||||
ASSERT_EQ(registry.get<StubProgram_1>(), program);
|
||||
ASSERT_EQ(registry.getLegacyGroup().get<StubProgram_1>(), program);
|
||||
|
||||
// Make sure downcasting to program1 works as expected
|
||||
StubShaderConsumer consumer;
|
||||
@@ -115,13 +115,13 @@ TEST(ShaderRegistry, RegisterShader) {
|
||||
TEST(ShaderRegistry, ReplaceShaderType) {
|
||||
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>();
|
||||
ASSERT_TRUE(registry.registerShader(program));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().registerShader(program));
|
||||
// Ensure the shader is present in the registry now
|
||||
ASSERT_TRUE(registry.isShader(std::string{StubProgram_1::Name}));
|
||||
ASSERT_TRUE(registry.isShader(std::string{program->typeName()}));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().isShader(std::string{StubProgram_1::Name}));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().isShader(std::string{program->typeName()}));
|
||||
|
||||
// Make sure downcasting to program1 works as expected
|
||||
StubShaderConsumer consumer;
|
||||
@@ -131,13 +131,13 @@ TEST(ShaderRegistry, ReplaceShaderType) {
|
||||
// and as such this replacement should fail as StubProgram_2
|
||||
// has never been registered.
|
||||
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
|
||||
auto program3 = std::make_shared<StubProgram_1>();
|
||||
program3->setToken(30);
|
||||
// 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_EQ(consumer.useShader<StubProgram_1>(registry), 30);
|
||||
}
|
||||
@@ -156,28 +156,29 @@ TEST(ShaderRegistry, ShaderRTTI) {
|
||||
TEST(ShaderRegistry, MultiRegister) {
|
||||
gfx::ShaderRegistry registry;
|
||||
|
||||
ASSERT_TRUE(registry.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>()));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>(), "SecondProgram"));
|
||||
|
||||
// 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
|
||||
ASSERT_NE(registry.get<StubProgram_1>("SecondProgram"), nullptr);
|
||||
ASSERT_NE(registry.get<StubProgram_1>(), registry.get<StubProgram_1>("SecondProgram"));
|
||||
ASSERT_NE(registry.getLegacyGroup().get<StubProgram_1>("SecondProgram"), nullptr);
|
||||
ASSERT_NE(registry.getLegacyGroup().get<StubProgram_1>(),
|
||||
registry.getLegacyGroup().get<StubProgram_1>("SecondProgram"));
|
||||
}
|
||||
|
||||
// Test fetching
|
||||
TEST(ShaderRegistry, RegistryFetch) {
|
||||
gfx::ShaderRegistry registry;
|
||||
|
||||
ASSERT_TRUE(registry.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>()));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().registerShader(std::make_shared<StubProgram_1>(), "SecondProgram"));
|
||||
|
||||
std::shared_ptr<StubProgram_1> progA;
|
||||
std::shared_ptr<StubProgram_1> progB;
|
||||
|
||||
ASSERT_TRUE(registry.populate(progA));
|
||||
ASSERT_TRUE(registry.populate(progB, "SecondProgram"));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().populate(progA));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().populate(progB, "SecondProgram"));
|
||||
ASSERT_NE(progA, progB);
|
||||
ASSERT_NE(progA, nullptr);
|
||||
ASSERT_NE(progB, nullptr);
|
||||
@@ -188,17 +189,17 @@ TEST(ShaderRegistry, NamedReplace) {
|
||||
gfx::ShaderRegistry registry;
|
||||
|
||||
// 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;
|
||||
ASSERT_TRUE(registry.populate(progA, "CustomName"));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().populate(progA, "CustomName"));
|
||||
ASSERT_NE(progA, nullptr);
|
||||
|
||||
// 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;
|
||||
ASSERT_TRUE(registry.populate(progB, "CustomName"));
|
||||
ASSERT_TRUE(registry.getLegacyGroup().populate(progB, "CustomName"));
|
||||
ASSERT_NE(progB, nullptr);
|
||||
|
||||
// Should be different instances
|
||||
@@ -213,7 +214,7 @@ TEST(ShaderRegistry, GLSLReplacement_NoOp) {
|
||||
|
||||
// Just replace with a default instance
|
||||
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!");
|
||||
}
|
||||
};
|
||||
@@ -239,7 +240,7 @@ TEST(ShaderRegistry, GLSLReplacement1) {
|
||||
|
||||
// Replace with an instance that only renders blue
|
||||
observer.registerShaders = [&](gfx::ShaderRegistry& registry) {
|
||||
if (!registry.replaceShader(std::make_shared<FillProgram>(
|
||||
if (!registry.getLegacyGroup().replaceShader(std::make_shared<FillProgram>(
|
||||
ProgramParameters(1.0f, false)
|
||||
.withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL,
|
||||
"",
|
||||
@@ -273,7 +274,7 @@ TEST(ShaderRegistry, GLSLReplacement2) {
|
||||
|
||||
// Replace with an instance that adds some red and green
|
||||
observer.registerShaders = [&](gfx::ShaderRegistry& registry) {
|
||||
if (!registry.replaceShader(std::make_shared<FillProgram>(
|
||||
if (!registry.getLegacyGroup().replaceShader(std::make_shared<FillProgram>(
|
||||
ProgramParameters(1.0f, false)
|
||||
.withShaderSource(ProgramParameters::ProgramSource(gfx::Backend::Type::OpenGL,
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user