Use drawables for location indicator layer (#2836)
Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
@@ -203,6 +203,8 @@ if(MLN_DRAWABLE_RENDERER)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/line_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/line_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/location_indicator_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/location_indicator_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/raster_layer_tweaker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp
|
||||
@@ -1135,6 +1137,7 @@ if(MLN_WITH_OPENGL)
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/background_layer_ubo.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/circle_layer_ubo.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/collision_layer_ubo.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/common_ubo.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_drawable_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/custom_drawable_layer_factory.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/debug_layer_ubo.hpp
|
||||
@@ -1351,6 +1354,7 @@ if(MLN_WITH_VULKAN)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/circle.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/clipping_mask.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/collision.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/common.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/debug.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/fill.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/heatmap.cpp
|
||||
|
||||
@@ -999,6 +999,7 @@ MLN_DRAWABLES_HEADERS = [
|
||||
"include/mbgl/shaders/background_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/circle_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/collision_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/common_ubo.hpp",
|
||||
"include/mbgl/shaders/custom_drawable_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/debug_layer_ubo.hpp",
|
||||
"include/mbgl/shaders/fill_layer_ubo.hpp",
|
||||
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
TextureWrapType wrapU{TextureWrapType::Clamp};
|
||||
/// Wrapping behavior along V coordinate
|
||||
TextureWrapType wrapV{TextureWrapType::Clamp};
|
||||
|
||||
uint8_t maxAnisotropy{1};
|
||||
bool mipmapped{false};
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
20
include/mbgl/shaders/common_ubo.hpp
Normal file
20
include/mbgl/shaders/common_ubo.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/layer_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
struct alignas(16) CommonUBO {
|
||||
std::array<float, 4 * 4> matrix;
|
||||
Color color;
|
||||
};
|
||||
static_assert(sizeof(CommonUBO) % 16 == 0);
|
||||
|
||||
enum {
|
||||
idCommonUBO = globalUBOCount,
|
||||
commonUBOCount
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/common_ubo.hpp>
|
||||
#include <mbgl/shaders/background_layer_ubo.hpp>
|
||||
#include <mbgl/shaders/circle_layer_ubo.hpp>
|
||||
#include <mbgl/shaders/collision_layer_ubo.hpp>
|
||||
@@ -31,6 +32,7 @@ static constexpr auto maxUBOCountPerShader = std::max({static_cast<size_t>(backg
|
||||
static_cast<size_t>(circleUBOCount),
|
||||
static_cast<size_t>(clippingMaskUBOCount),
|
||||
static_cast<size_t>(collisionUBOCount),
|
||||
static_cast<size_t>(commonUBOCount),
|
||||
static_cast<size_t>(customSymbolUBOCount),
|
||||
static_cast<size_t>(debugUBOCount),
|
||||
static_cast<size_t>(fillUBOCount),
|
||||
@@ -62,6 +64,11 @@ enum {
|
||||
collisionTextureCount
|
||||
};
|
||||
|
||||
enum {
|
||||
idCommonTexture,
|
||||
commonTextureCount
|
||||
};
|
||||
|
||||
enum {
|
||||
idCustomSymbolImageTexture,
|
||||
customSymbolTextureCount
|
||||
@@ -114,6 +121,7 @@ static constexpr auto maxTextureCountPerShader = std::max({static_cast<size_t>(b
|
||||
static_cast<size_t>(circleTextureCount),
|
||||
static_cast<size_t>(clippingMaskTextureCount),
|
||||
static_cast<size_t>(collisionTextureCount),
|
||||
static_cast<size_t>(commonTextureCount),
|
||||
static_cast<size_t>(customSymbolTextureCount),
|
||||
static_cast<size_t>(debugTextureCount),
|
||||
static_cast<size_t>(fillTextureCount),
|
||||
@@ -159,6 +167,12 @@ enum {
|
||||
collisionVertexAttributeCount
|
||||
};
|
||||
|
||||
enum {
|
||||
idCommonPosVertexAttribute,
|
||||
idCommonTexVertexAttribute,
|
||||
commonVertexAttributeCount
|
||||
};
|
||||
|
||||
enum {
|
||||
idCustomSymbolPosVertexAttribute,
|
||||
idCustomSymbolTexVertexAttribute,
|
||||
@@ -276,6 +290,7 @@ static constexpr auto maxVertexAttributeCountPerShader = std::max({
|
||||
static_cast<size_t>(circleVertexAttributeCount),
|
||||
static_cast<size_t>(clippingMaskVertexAttributeCount),
|
||||
static_cast<size_t>(collisionVertexAttributeCount),
|
||||
static_cast<size_t>(commonVertexAttributeCount),
|
||||
static_cast<size_t>(customSymbolVertexAttributeCount),
|
||||
static_cast<size_t>(debugVertexAttributeCount),
|
||||
static_cast<size_t>(fillVertexAttributeCount),
|
||||
|
||||
@@ -14,6 +14,8 @@ enum class BuiltIn {
|
||||
CircleShader,
|
||||
CollisionBoxShader,
|
||||
CollisionCircleShader,
|
||||
CommonShader,
|
||||
CommonTexturedShader,
|
||||
DebugShader,
|
||||
FillShader,
|
||||
FillOutlineShader,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
#include <mbgl/shaders/vulkan/shader_program.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
@@ -100,5 +101,82 @@ layout(set = 0, binding = 0) uniform GlobalPaintParamsUBO {
|
||||
)";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::CommonShader, gfx::Backend::Type::Vulkan> {
|
||||
static constexpr const char* name = "CommonShader";
|
||||
|
||||
static const std::array<UniformBlockInfo, 1> uniforms;
|
||||
static const std::array<AttributeInfo, 1> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static constexpr std::array<TextureInfo, 0> textures{};
|
||||
|
||||
static constexpr auto vertex = R"(
|
||||
layout(location = 0) in vec2 in_position;
|
||||
|
||||
layout(set = 0, binding = 1) uniform CommonUBO {
|
||||
mat4 matrix;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.matrix * vec4(in_position, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
}
|
||||
)";
|
||||
|
||||
static constexpr auto fragment = R"(
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
layout(set = 0, binding = 1) uniform CommonUBO {
|
||||
mat4 matrix;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
out_color = ubo.color;
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ShaderSource<BuiltIn::CommonTexturedShader, gfx::Backend::Type::Vulkan> {
|
||||
static constexpr const char* name = "CommonTexturedShader";
|
||||
|
||||
static const std::array<UniformBlockInfo, 1> uniforms;
|
||||
static const std::array<AttributeInfo, 2> attributes;
|
||||
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||
static const std::array<TextureInfo, 1> textures;
|
||||
|
||||
static constexpr auto vertex = R"(
|
||||
layout(location = 0) in vec2 in_position;
|
||||
layout(location = 1) in vec2 in_texcoord;
|
||||
|
||||
layout(set = 0, binding = 1) uniform CommonUBO {
|
||||
mat4 matrix;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout(location = 0) out vec2 frag_uv;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.matrix * vec4(in_position, 0, 1);
|
||||
gl_Position.y *= -1.0;
|
||||
|
||||
frag_uv = in_texcoord;
|
||||
}
|
||||
)";
|
||||
|
||||
static constexpr auto fragment = R"(
|
||||
layout(location = 0) in vec2 frag_uv;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D image_sampler;
|
||||
|
||||
void main() {
|
||||
out_color = texture(image_sampler, frag_uv);
|
||||
}
|
||||
)";
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -96,6 +96,9 @@ private:
|
||||
void transitionToShaderReadLayout(const vk::UniqueCommandBuffer&);
|
||||
void transitionToGeneralLayout(const vk::UniqueCommandBuffer&);
|
||||
|
||||
uint32_t getMipLevels() const;
|
||||
void generateMips(const vk::UniqueCommandBuffer& buffer);
|
||||
|
||||
private:
|
||||
Context& context;
|
||||
|
||||
|
||||
@@ -48,4 +48,4 @@ task unzip(dependsOn: download, type: Copy) {
|
||||
|
||||
android.sourceSets.vulkan.jniLibs {
|
||||
srcDir(tasks.unzip)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ LayerManagerDefault::LayerManagerDefault() {
|
||||
#if !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL)
|
||||
addLayerType(std::make_unique<CustomLayerFactory>());
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) || MLN_RENDER_BACKEND_VULKAN
|
||||
#if !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
|
||||
addLayerType(std::make_unique<LocationIndicatorLayerFactory>());
|
||||
#endif
|
||||
|
||||
@@ -63,8 +63,7 @@
|
||||
|
||||
using namespace std::numbers;
|
||||
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
|
||||
#include <mbgl/style/layers/location_indicator_layer.hpp>
|
||||
#ifdef ENABLE_LOCATION_INDICATOR
|
||||
|
||||
namespace {
|
||||
const std::string mbglPuckAssetsPath{MAPBOX_PUCK_ASSETS_PATH};
|
||||
@@ -1244,7 +1243,7 @@ void GLFWView::toggleCustomSource() {
|
||||
void GLFWView::toggleLocationIndicatorLayer() {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
|
||||
#ifdef ENABLE_LOCATION_INDICATOR
|
||||
puck = static_cast<mbgl::style::LocationIndicatorLayer *>(map->getStyle().getLayer("puck"));
|
||||
static const mbgl::LatLng puckLocation{35.683389, 139.76525}; // A location on the crossing of 4 tiles
|
||||
if (puck == nullptr) {
|
||||
@@ -1309,7 +1308,7 @@ using Nanoseconds = std::chrono::nanoseconds;
|
||||
void GLFWView::onWillStartRenderingFrame() {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_LOCATION_INDICATOR_DISABLE_ALL)
|
||||
#ifdef ENABLE_LOCATION_INDICATOR
|
||||
puck = static_cast<mbgl::style::LocationIndicatorLayer *>(map->getStyle().getLayer("puck"));
|
||||
if (puck) {
|
||||
uint64_t ns = mbgl::Clock::now().time_since_epoch().count();
|
||||
|
||||
@@ -5,13 +5,19 @@
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL)
|
||||
#include <mbgl/style/layers/location_indicator_layer.hpp>
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
#if (defined(MLN_RENDER_BACKEND_OPENGL) || defined(MLN_RENDER_BACKEND_VULKAN)) && \
|
||||
!defined(MBGL_LAYER_CUSTOM_DISABLE_ALL)
|
||||
#define ENABLE_LOCATION_INDICATOR
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LOCATION_INDICATOR
|
||||
#include <mbgl/style/layers/location_indicator_layer.hpp>
|
||||
#endif
|
||||
|
||||
struct GLFWwindow;
|
||||
class GLFWBackend;
|
||||
class GLFWRendererFrontend;
|
||||
@@ -163,7 +169,7 @@ private:
|
||||
mbgl::ResourceOptions mapResourceOptions;
|
||||
mbgl::ClientOptions mapClientOptions;
|
||||
|
||||
#if defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL)
|
||||
#ifdef ENABLE_LOCATION_INDICATOR
|
||||
bool puckFollowsCameraCenter = false;
|
||||
mbgl::style::LocationIndicatorLayer *puck = nullptr;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <mbgl/renderer/layers/location_indicator_layer_tweaker.hpp>
|
||||
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/layers/render_location_indicator_layer.hpp>
|
||||
#include <mbgl/style/layers/location_indicator_layer_properties.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void LocationIndicatorLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters& params) {
|
||||
if (layerGroup.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& props = static_cast<const style::LocationIndicatorLayerProperties&>(*evaluatedProperties);
|
||||
|
||||
const shaders::CommonUBO quadUBO = {/* .matrix */ util::cast<float>(projectionPuck),
|
||||
/* .color */ Color::black()};
|
||||
|
||||
visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) {
|
||||
auto& drawableUniforms = drawable.mutableUniformBuffers();
|
||||
|
||||
if (!drawable.getEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (static_cast<RenderLocationIndicatorLayer::LocationIndicatorComponentType>(drawable.getType())) {
|
||||
case RenderLocationIndicatorLayer::LocationIndicatorComponentType::Circle: {
|
||||
shaders::CommonUBO circleUBO = {/* .matrix */ util::cast<float>(projectionCircle),
|
||||
/* .color */ props.evaluated.get<style::AccuracyRadiusColor>()};
|
||||
|
||||
drawableUniforms.createOrUpdate(shaders::idCommonUBO, &circleUBO, params.context);
|
||||
break;
|
||||
}
|
||||
|
||||
case RenderLocationIndicatorLayer::LocationIndicatorComponentType::CircleOutline: {
|
||||
shaders::CommonUBO circleUBO = {/* .matrix */ util::cast<float>(projectionCircle),
|
||||
/* .color */ props.evaluated.get<style::AccuracyRadiusBorderColor>()};
|
||||
|
||||
drawableUniforms.createOrUpdate(shaders::idCommonUBO, &circleUBO, params.context);
|
||||
break;
|
||||
}
|
||||
|
||||
case RenderLocationIndicatorLayer::LocationIndicatorComponentType::PuckShadow:
|
||||
[[fallthrough]];
|
||||
case RenderLocationIndicatorLayer::LocationIndicatorComponentType::Puck:
|
||||
[[fallthrough]];
|
||||
case RenderLocationIndicatorLayer::LocationIndicatorComponentType::PuckHat:
|
||||
drawableUniforms.createOrUpdate(shaders::idCommonUBO, &quadUBO, params.context);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
#include <mbgl/gfx/uniform_buffer.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
Location indicator layer specific tweaker
|
||||
*/
|
||||
class LocationIndicatorLayerTweaker : public LayerTweaker {
|
||||
public:
|
||||
LocationIndicatorLayerTweaker(std::string id_,
|
||||
Immutable<style::LayerProperties> properties,
|
||||
const mbgl::mat4& projectionCircle_,
|
||||
const mbgl::mat4& projectionPuck_)
|
||||
: LayerTweaker(std::move(id_), properties),
|
||||
projectionCircle(projectionCircle_),
|
||||
projectionPuck(projectionPuck_) {}
|
||||
|
||||
public:
|
||||
~LocationIndicatorLayerTweaker() override = default;
|
||||
|
||||
void execute(LayerGroupBase&, const PaintParameters& params) override;
|
||||
|
||||
private:
|
||||
const mbgl::mat4& projectionCircle;
|
||||
const mbgl::mat4& projectionPuck;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <mbgl/style/layers/location_indicator_layer_impl.hpp>
|
||||
#include <mbgl/style/layers/location_indicator_layer_properties.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/util/tile_cover.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
|
||||
#include <mapbox/eternal.hpp>
|
||||
#include <mbgl/renderer/image_manager.hpp>
|
||||
@@ -38,11 +40,20 @@
|
||||
#include <mbgl/gl/texture_resource.hpp>
|
||||
#include <mbgl/gl/types.hpp>
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#define MBGL_CHECK_ERROR(x) \
|
||||
while (0) { \
|
||||
}
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
|
||||
#include <mbgl/gfx/vertex_attribute.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/shaders/common_ubo.hpp>
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/gfx/drawable_impl.hpp>
|
||||
#include <mbgl/gfx/drawable_tweaker.hpp>
|
||||
#include <mbgl/gfx/texture2d.hpp>
|
||||
#include <mbgl/shaders/shader_defines.hpp>
|
||||
#include <mbgl/renderer/layers/location_indicator_layer_tweaker.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,20 +97,19 @@ struct LocationIndicatorRenderParameters {
|
||||
std::string puckHatImagePath;
|
||||
};
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
class RenderLocationIndicatorImpl {
|
||||
protected:
|
||||
public:
|
||||
struct vec2 {
|
||||
GLfloat x = 0.0f;
|
||||
GLfloat y = 0.0f;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
vec2(GLfloat x_, GLfloat y_)
|
||||
vec2(float x_, float y_)
|
||||
: x(x_),
|
||||
y(y_) {}
|
||||
vec2() = default;
|
||||
explicit vec2(const Point<double>& p)
|
||||
: x(static_cast<GLfloat>(p.x)),
|
||||
y(static_cast<GLfloat>(p.y)) {}
|
||||
: x(static_cast<float>(p.x)),
|
||||
y(static_cast<float>(p.y)) {}
|
||||
vec2(const vec2& o) = default;
|
||||
vec2(vec2&& o) = default;
|
||||
vec2& operator=(vec2&& o) = default;
|
||||
@@ -130,11 +140,12 @@ protected:
|
||||
Point<double> toPoint() const { return {x, y}; }
|
||||
|
||||
friend vec2 operator-(const vec2& v) { return {-v.x, -v.y}; }
|
||||
friend vec2 operator*(double a, const vec2& v) { return {GLfloat(v.x * a), GLfloat(v.y * a)}; }
|
||||
friend vec2 operator*(double a, const vec2& v) { return {float(v.x * a), float(v.y * a)}; }
|
||||
friend vec2 operator+(const vec2& v1, const vec2& v2) { return {v1.x + v2.x, v1.y + v2.y}; }
|
||||
friend vec2 operator-(const vec2& v1, const vec2& v2) { return {v1.x - v2.x, v1.y - v2.y}; }
|
||||
};
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
struct Shader {
|
||||
virtual ~Shader() { release(); }
|
||||
void release() {
|
||||
@@ -374,13 +385,6 @@ public:
|
||||
float pixelRatio = 1.0f;
|
||||
};
|
||||
|
||||
RenderLocationIndicatorImpl(std::string sourceLayer)
|
||||
: ruler(0, mapbox::cheap_ruler::CheapRuler::Meters),
|
||||
feature(std::make_shared<mbgl::Feature>()),
|
||||
featureEnvelope(std::make_shared<mapbox::geometry::polygon<int64_t>>()) {
|
||||
feature->sourceLayer = std::move(sourceLayer);
|
||||
}
|
||||
|
||||
static bool hasAnisotropicFiltering() {
|
||||
const auto* extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
GLenum error = glGetError();
|
||||
@@ -414,7 +418,74 @@ public:
|
||||
drawHat();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
struct TextureInfo {
|
||||
std::shared_ptr<gfx::Texture2D> texture;
|
||||
std::optional<Immutable<style::Image::Impl>> image;
|
||||
std::string id = "";
|
||||
float pixelRatio = 1.0f;
|
||||
size_t width = 0;
|
||||
size_t height = 0;
|
||||
bool dirty = false;
|
||||
|
||||
void assign(const Immutable<style::Image::Impl>& img) {
|
||||
reset();
|
||||
|
||||
image = img;
|
||||
|
||||
id = img->id;
|
||||
pixelRatio = img->pixelRatio;
|
||||
|
||||
width = img->image.size.width;
|
||||
height = img->image.size.height;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
texture.reset();
|
||||
image.reset();
|
||||
pixelRatio = 1.0f;
|
||||
width = 0;
|
||||
height = 0;
|
||||
dirty = true;
|
||||
}
|
||||
};
|
||||
|
||||
bool setTextureFromImageID(const std::string& imagePath,
|
||||
TextureInfo& textureInfo,
|
||||
const mbgl::LocationIndicatorRenderParameters& params) {
|
||||
bool updated = false;
|
||||
const Immutable<style::Image::Impl>* sharedImage = nullptr;
|
||||
|
||||
if (!imagePath.empty() && params.imageManager) {
|
||||
sharedImage = params.imageManager->getSharedImage(imagePath);
|
||||
}
|
||||
|
||||
if (sharedImage) {
|
||||
if (!textureInfo.texture || textureInfo.id != sharedImage->get()->id) {
|
||||
textureInfo.assign(*sharedImage);
|
||||
updated = true;
|
||||
}
|
||||
} else if (textureInfo.image) {
|
||||
textureInfo.reset();
|
||||
updated = true;
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
RenderLocationIndicatorImpl(std::string sourceLayer)
|
||||
: ruler(0, mapbox::cheap_ruler::CheapRuler::Meters),
|
||||
feature(std::make_shared<mbgl::Feature>()),
|
||||
featureEnvelope(std::make_shared<mapbox::geometry::polygon<int64_t>>()) {
|
||||
feature->sourceLayer = std::move(sourceLayer);
|
||||
}
|
||||
|
||||
void release() {
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
if (!simpleShader.program) return;
|
||||
for (const auto& t : textures) t.second->release();
|
||||
buffer.release();
|
||||
@@ -424,6 +495,11 @@ public:
|
||||
texCoordsBuffer.release();
|
||||
simpleShader.release();
|
||||
texturedShader.release();
|
||||
#else
|
||||
shadowDrawableInfo.reset();
|
||||
puckDrawableInfo.reset();
|
||||
hatDrawableInfo.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void updatePuckGeometry(const mbgl::LocationIndicatorRenderParameters& params) {
|
||||
@@ -439,9 +515,15 @@ public:
|
||||
params.puckShadowScale != oldParams.puckShadowScale)
|
||||
bearingChanged = true; // changes puck geometry but not necessarily the location
|
||||
if (params.errorRadiusMeters != oldParams.errorRadiusMeters) radiusChanged = true;
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
bearingChanged |= setTextureFromImageID(params.puckImagePath, texPuck, params);
|
||||
bearingChanged |= setTextureFromImageID(params.puckShadowImagePath, texShadow, params);
|
||||
bearingChanged |= setTextureFromImageID(params.puckHatImagePath, texPuckHat, params);
|
||||
#else
|
||||
bearingChanged |= setTextureFromImageID(params.puckShadowImagePath, shadowDrawableInfo.textureInfo, params);
|
||||
bearingChanged |= setTextureFromImageID(params.puckImagePath, puckDrawableInfo.textureInfo, params);
|
||||
bearingChanged |= setTextureFromImageID(params.puckHatImagePath, hatDrawableInfo.textureInfo, params);
|
||||
#endif
|
||||
|
||||
projectionCircle = params.projectionMatrix;
|
||||
const Point<double> positionMercator = project(params.puckPosition, *params.state);
|
||||
@@ -469,7 +551,13 @@ public:
|
||||
if (!dirtyFeature) return;
|
||||
dirtyFeature = false;
|
||||
featureEnvelope->clear();
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
if (!texPuck || !texPuck->isValid()) return;
|
||||
#else
|
||||
if (!puckDrawableInfo.textureInfo.texture) return;
|
||||
|
||||
auto& puckGeometry = puckDrawableInfo.geometry;
|
||||
#endif
|
||||
|
||||
feature->geometry = mapbox::geometry::point<double>{oldParams.puckPosition.latitude(),
|
||||
oldParams.puckPosition.longitude()};
|
||||
@@ -505,6 +593,11 @@ protected:
|
||||
}
|
||||
|
||||
void updateRadius(const mbgl::LocationIndicatorRenderParameters& params) {
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
auto& circle = circleDrawableInfo.geometry;
|
||||
circleDrawableInfo.dirty = true;
|
||||
#endif
|
||||
|
||||
const TransformState& s = *params.state;
|
||||
const auto numVtxCircumference = static_cast<unsigned long>(circle.size() - 1);
|
||||
const float bearingStep = 360.0f /
|
||||
@@ -617,6 +710,8 @@ protected:
|
||||
util::clamp(pixelSizeToWorldSizeH(params.puckPosition, s), 0.8f, 100.1f) *
|
||||
params.perspectiveCompensation; // Compensation factor for the perspective deformation
|
||||
// ^ clamping this to 0.8 to avoid growing the puck too much close to the camera.
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
const double shadowRadius = ((texShadow) ? texShadow->width / texShadow->pixelRatio : 0.0) *
|
||||
params.puckShadowScale * M_SQRT2 * 0.5 *
|
||||
horizontalScaleFactor; // Technically it's not the radius, but
|
||||
@@ -625,6 +720,24 @@ protected:
|
||||
M_SQRT2 * 0.5 * horizontalScaleFactor;
|
||||
const double hatRadius = ((texPuckHat) ? texPuckHat->width / texPuckHat->pixelRatio : 0.0) *
|
||||
params.puckHatScale * M_SQRT2 * 0.5 * horizontalScaleFactor;
|
||||
#else
|
||||
const double shadowScale = shadowDrawableInfo.textureInfo.width / shadowDrawableInfo.textureInfo.pixelRatio;
|
||||
const double shadowRadius = shadowScale * params.puckShadowScale * M_SQRT2 * 0.5 * horizontalScaleFactor;
|
||||
|
||||
const double puckScale = puckDrawableInfo.textureInfo.width / puckDrawableInfo.textureInfo.pixelRatio;
|
||||
const double puckRadius = puckScale * params.puckScale * M_SQRT2 * 0.5 * horizontalScaleFactor;
|
||||
|
||||
const double hatScale = hatDrawableInfo.textureInfo.width / hatDrawableInfo.textureInfo.pixelRatio;
|
||||
const double hatRadius = hatScale * params.puckHatScale * M_SQRT2 * 0.5 * horizontalScaleFactor;
|
||||
|
||||
auto& shadowGeometry = shadowDrawableInfo.geometry;
|
||||
auto& puckGeometry = puckDrawableInfo.geometry;
|
||||
auto& hatGeometry = hatDrawableInfo.geometry;
|
||||
|
||||
shadowDrawableInfo.dirty = true;
|
||||
puckDrawableInfo.dirty = true;
|
||||
hatDrawableInfo.dirty = true;
|
||||
#endif
|
||||
|
||||
for (unsigned long i = 0; i < 4; ++i) {
|
||||
const auto b = util::wrap<float>(static_cast<float>(params.puckBearing) + bearings[i], 0.0f, 360.0f);
|
||||
@@ -643,6 +756,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
void drawRadius(const mbgl::LocationIndicatorRenderParameters& params) {
|
||||
if (!(params.errorRadiusMeters > 0.0) ||
|
||||
(params.errorRadiusColor.a == 0.0 && params.errorRadiusBorderColor.a == 0.0))
|
||||
@@ -694,6 +808,7 @@ protected:
|
||||
void drawPuck() { drawQuad(puckBuffer, puckGeometry, texPuck); }
|
||||
|
||||
void drawHat() { drawQuad(hatBuffer, hatGeometry, texPuckHat); }
|
||||
#endif
|
||||
|
||||
static LatLng screenCoordinateToLatLng(const ScreenCoordinate& p,
|
||||
const TransformState& s,
|
||||
@@ -703,6 +818,7 @@ protected:
|
||||
return s.screenCoordinateToLatLng(flippedPoint, wrapMode);
|
||||
}
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
bool setTextureFromImageID(const std::string& imagePath,
|
||||
std::shared_ptr<Texture>& texture,
|
||||
const mbgl::LocationIndicatorRenderParameters& params) {
|
||||
@@ -731,7 +847,6 @@ protected:
|
||||
}
|
||||
|
||||
std::map<std::string, std::shared_ptr<Texture>> textures;
|
||||
mapbox::cheap_ruler::CheapRuler ruler;
|
||||
SimpleShader simpleShader;
|
||||
TexturedShader texturedShader;
|
||||
Buffer buffer;
|
||||
@@ -749,6 +864,10 @@ protected:
|
||||
std::array<vec2, 4> puckGeometry;
|
||||
std::array<vec2, 4> hatGeometry;
|
||||
std::array<vec2, 4> texCoords;
|
||||
#endif
|
||||
|
||||
mapbox::cheap_ruler::CheapRuler ruler;
|
||||
|
||||
mbgl::mat4 translation;
|
||||
mbgl::mat4 projectionCircle;
|
||||
mbgl::mat4 projectionPuck;
|
||||
@@ -760,34 +879,49 @@ protected:
|
||||
bool initialized = false;
|
||||
bool dirtyFeature = true;
|
||||
|
||||
public:
|
||||
mbgl::LocationIndicatorRenderParameters parameters;
|
||||
std::shared_ptr<mbgl::Feature> feature;
|
||||
std::shared_ptr<mapbox::geometry::polygon<int64_t>> featureEnvelope;
|
||||
static bool anisotropicFilteringAvailable;
|
||||
};
|
||||
|
||||
bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false;
|
||||
#else
|
||||
|
||||
class RenderLocationIndicatorImpl {
|
||||
public:
|
||||
RenderLocationIndicatorImpl(std::string) {}
|
||||
|
||||
void release() {}
|
||||
void updateFeature() {}
|
||||
void updatePuckGeometry([[maybe_unused]] const mbgl::LocationIndicatorRenderParameters& params) {}
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
|
||||
public:
|
||||
mbgl::LocationIndicatorRenderParameters parameters;
|
||||
std::shared_ptr<mbgl::Feature> feature;
|
||||
std::shared_ptr<mapbox::geometry::polygon<int64_t>> featureEnvelope;
|
||||
static bool anisotropicFilteringAvailable;
|
||||
};
|
||||
struct QuadDrawableInfo {
|
||||
std::optional<std::reference_wrapper<gfx::Drawable>> drawable;
|
||||
std::array<vec2, 4> geometry;
|
||||
TextureInfo textureInfo;
|
||||
bool dirty{false};
|
||||
|
||||
gfx::Drawable& getDrawable() { return drawable.value().get(); }
|
||||
void reset() { textureInfo.reset(); }
|
||||
};
|
||||
|
||||
struct CircleDrawableInfo {
|
||||
std::optional<std::reference_wrapper<gfx::Drawable>> drawable;
|
||||
std::optional<std::reference_wrapper<gfx::Drawable>> outlineDrawable;
|
||||
std::array<vec2, 73> geometry;
|
||||
TextureInfo textureInfo;
|
||||
bool dirty{false};
|
||||
|
||||
gfx::Drawable& getDrawable() { return drawable.value().get(); }
|
||||
void reset() { textureInfo.reset(); }
|
||||
};
|
||||
|
||||
CircleDrawableInfo circleDrawableInfo;
|
||||
QuadDrawableInfo shadowDrawableInfo;
|
||||
QuadDrawableInfo puckDrawableInfo;
|
||||
QuadDrawableInfo hatDrawableInfo;
|
||||
|
||||
const auto& getProjectionCircle() const { return projectionCircle; }
|
||||
const auto& getProjectionPuck() const { return projectionPuck; }
|
||||
|
||||
bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false;
|
||||
#endif
|
||||
|
||||
public:
|
||||
mbgl::LocationIndicatorRenderParameters parameters;
|
||||
std::shared_ptr<mbgl::Feature> feature;
|
||||
std::shared_ptr<mapbox::geometry::polygon<int64_t>> featureEnvelope;
|
||||
static bool anisotropicFilteringAvailable;
|
||||
};
|
||||
|
||||
bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false;
|
||||
|
||||
using namespace style;
|
||||
namespace {
|
||||
|
||||
@@ -805,7 +939,7 @@ RenderLocationIndicatorLayer::RenderLocationIndicatorLayer(Immutable<style::Loca
|
||||
}
|
||||
|
||||
RenderLocationIndicatorLayer::~RenderLocationIndicatorLayer() {
|
||||
if (!contextDestroyed) MBGL_CHECK_ERROR(renderImpl->release());
|
||||
if (!contextDestroyed) renderImpl->release();
|
||||
}
|
||||
|
||||
void RenderLocationIndicatorLayer::transition(const TransitionParameters& parameters) {
|
||||
@@ -876,6 +1010,11 @@ void RenderLocationIndicatorLayer::prepare(const LayerPrepareParameters& p) {
|
||||
renderImpl->updatePuckGeometry(renderImpl->parameters);
|
||||
}
|
||||
|
||||
void RenderLocationIndicatorLayer::populateDynamicRenderFeatureIndex(DynamicFeatureIndex& index) const {
|
||||
renderImpl->updateFeature();
|
||||
if (!renderImpl->featureEnvelope->empty()) index.insert(renderImpl->feature, renderImpl->featureEnvelope);
|
||||
}
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) {
|
||||
auto& glContext = static_cast<gl::Context&>(paintParameters.context);
|
||||
@@ -894,12 +1033,265 @@ void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) {
|
||||
paintParameters.backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
|
||||
glContext.setDirtyState();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
|
||||
void RenderLocationIndicatorLayer::update(gfx::ShaderRegistry& shaders,
|
||||
gfx::Context& context,
|
||||
const TransformState&,
|
||||
const std::shared_ptr<UpdateParameters>&,
|
||||
const RenderTree&,
|
||||
UniqueChangeRequestVec& changes) {
|
||||
const auto drawPasses = RenderPass::Translucent;
|
||||
|
||||
// If the result is transparent or missing, just remove any existing drawables and stop
|
||||
if (drawPasses == RenderPass::None) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!quadShader) {
|
||||
quadShader = context.getGenericShader(shaders, "CommonTexturedShader");
|
||||
}
|
||||
|
||||
if (!quadShader) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!circleShader) {
|
||||
circleShader = context.getGenericShader(shaders, "CommonShader");
|
||||
}
|
||||
|
||||
if (!circleShader) {
|
||||
removeAllDrawables();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layerGroup) {
|
||||
if (auto layerGroup_ = context.createLayerGroup(layerIndex, /*initialCapacity=*/4, getID())) {
|
||||
setLayerGroup(std::move(layerGroup_), changes);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!layerTweaker) {
|
||||
layerTweaker = std::make_shared<LocationIndicatorLayerTweaker>(
|
||||
getID(), evaluatedProperties, renderImpl->getProjectionCircle(), renderImpl->getProjectionPuck());
|
||||
layerGroup->addLayerTweaker(layerTweaker);
|
||||
}
|
||||
|
||||
auto* localLayerGroup = static_cast<LayerGroup*>(layerGroup.get());
|
||||
|
||||
if (localLayerGroup->getDrawableCount() == 0) {
|
||||
// create empty drawable using a builder
|
||||
const gfx::UniqueDrawableBuilder& builder = context.createDrawableBuilder(getID());
|
||||
|
||||
const auto createQuadGeometry = [&](gfx::Drawable& drawable, const auto& geometry) {
|
||||
auto vertexAttrs = context.createVertexAttributeArray();
|
||||
|
||||
if (const auto& attr = vertexAttrs->set(
|
||||
shaders::idCommonTexVertexAttribute, 0, gfx::AttributeDataType::Float2)) {
|
||||
const std::array<RenderLocationIndicatorImpl::vec2, 4> texCoords = {
|
||||
{{0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}}};
|
||||
|
||||
auto geoDataPtr = reinterpret_cast<const uint8_t*>(texCoords.data());
|
||||
auto geoDataSize = texCoords.size() * sizeof(RenderLocationIndicatorImpl::vec2);
|
||||
|
||||
std::vector<uint8_t> rawData;
|
||||
std::copy(geoDataPtr, geoDataPtr + geoDataSize, std::back_inserter(rawData));
|
||||
attr->setRawData(std::move(rawData));
|
||||
}
|
||||
|
||||
drawable.setVertexAttributes(vertexAttrs);
|
||||
|
||||
gfx::IndexVector<gfx::Triangles> indices;
|
||||
indices.emplace_back(0, 1, 2);
|
||||
indices.emplace_back(0, 2, 3);
|
||||
|
||||
std::vector<gfx::Drawable::UniqueDrawSegment> drawSegments;
|
||||
drawSegments.emplace_back(
|
||||
builder->createSegment(gfx::Triangles(), SegmentBase(0, 0, geometry.size(), indices.elements())));
|
||||
drawable.setIndexData(indices.vector(), std::move(drawSegments));
|
||||
};
|
||||
|
||||
const auto createQuadDrawable = [&](RenderLocationIndicatorImpl::QuadDrawableInfo& drawableInfo,
|
||||
std::string&& name,
|
||||
LocationIndicatorComponentType type) {
|
||||
auto& drawable = builder->getCurrentDrawable(true);
|
||||
drawable->setType(static_cast<uint8_t>(type));
|
||||
|
||||
drawable->setName(name);
|
||||
drawable->setRenderPass(drawPasses);
|
||||
drawable->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
drawable->setColorMode(drawPasses == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
|
||||
drawable->setShader(quadShader);
|
||||
|
||||
createQuadGeometry(*drawable, drawableInfo.geometry);
|
||||
|
||||
drawableInfo.drawable.emplace(*drawable);
|
||||
|
||||
// add drawable to layer group
|
||||
localLayerGroup->addDrawable(std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
};
|
||||
|
||||
// create circle drawable
|
||||
const auto getCircleDrawable = [&](const auto& name, auto& vertexAttrib) -> gfx::UniqueDrawable& {
|
||||
auto& drawable = builder->getCurrentDrawable(true);
|
||||
|
||||
drawable->setName(name);
|
||||
drawable->setRenderPass(drawPasses);
|
||||
drawable->setDepthType(gfx::DepthMaskType::ReadWrite);
|
||||
drawable->setColorMode(drawPasses == RenderPass::Translucent ? gfx::ColorMode::alphaBlended()
|
||||
: gfx::ColorMode::unblended());
|
||||
|
||||
drawable->setShader(circleShader);
|
||||
drawable->setVertexAttributes(vertexAttrib);
|
||||
|
||||
return drawable;
|
||||
};
|
||||
|
||||
const auto createCircleDrawable = [&]() {
|
||||
// circle[0] is the center
|
||||
const auto& geometry = renderImpl->circleDrawableInfo.geometry;
|
||||
const uint16_t vertexCount = static_cast<uint16_t>(geometry.size());
|
||||
auto vertexAttrib = context.createVertexAttributeArray();
|
||||
|
||||
{
|
||||
auto& drawable = getCircleDrawable("locationAccuracyCircle", vertexAttrib);
|
||||
drawable->setType(static_cast<uint8_t>(LocationIndicatorComponentType::Circle));
|
||||
|
||||
std::vector<gfx::Drawable::UniqueDrawSegment> drawSegments;
|
||||
std::vector<uint16_t> indices;
|
||||
|
||||
for (uint16_t i = 1; i < vertexCount - 1; ++i) {
|
||||
indices.insert(indices.end(), {0, i, static_cast<uint16_t>(i + 1)});
|
||||
}
|
||||
indices.insert(indices.end(), {0, static_cast<uint16_t>(vertexCount - 1), 1});
|
||||
|
||||
SegmentBase segment(0, 0, vertexCount, indices.size());
|
||||
drawSegments.emplace_back(builder->createSegment(gfx::Triangles(), std::move(segment)));
|
||||
drawable->setIndexData(indices, std::move(drawSegments));
|
||||
|
||||
renderImpl->circleDrawableInfo.drawable.emplace(*drawable);
|
||||
|
||||
localLayerGroup->addDrawable(std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
|
||||
{
|
||||
auto& drawable = getCircleDrawable("locationAccuracyCircleOutline", vertexAttrib);
|
||||
drawable->setType(static_cast<uint8_t>(LocationIndicatorComponentType::CircleOutline));
|
||||
|
||||
std::vector<gfx::Drawable::UniqueDrawSegment> drawSegments;
|
||||
std::vector<uint16_t> indices;
|
||||
|
||||
for (uint16_t i = 1; i < vertexCount; ++i) {
|
||||
indices.push_back(i);
|
||||
}
|
||||
|
||||
SegmentBase segment(0, 0, vertexCount, indices.size());
|
||||
drawSegments.emplace_back(builder->createSegment(gfx::LineStrip(1.0f), std::move(segment)));
|
||||
drawable->setIndexData(indices, std::move(drawSegments));
|
||||
|
||||
renderImpl->circleDrawableInfo.outlineDrawable.emplace(*drawable);
|
||||
|
||||
localLayerGroup->addDrawable(std::move(drawable));
|
||||
++stats.drawablesAdded;
|
||||
}
|
||||
};
|
||||
|
||||
createCircleDrawable();
|
||||
createQuadDrawable(
|
||||
renderImpl->shadowDrawableInfo, "locationShadow", LocationIndicatorComponentType::PuckShadow);
|
||||
createQuadDrawable(renderImpl->puckDrawableInfo, "locationPuck", LocationIndicatorComponentType::Puck);
|
||||
createQuadDrawable(renderImpl->hatDrawableInfo, "locationPuckHat", LocationIndicatorComponentType::PuckHat);
|
||||
};
|
||||
|
||||
const auto updateCircleDrawable = [&]() {
|
||||
auto& circleDrawable = renderImpl->circleDrawableInfo.drawable.value().get();
|
||||
auto& circleOutlineDrawable = renderImpl->circleDrawableInfo.outlineDrawable.value().get();
|
||||
|
||||
if (!(renderImpl->parameters.errorRadiusMeters > 0.0) ||
|
||||
(renderImpl->parameters.errorRadiusColor.a == 0.0 &&
|
||||
renderImpl->parameters.errorRadiusBorderColor.a == 0.0)) {
|
||||
circleDrawable.setEnabled(false);
|
||||
circleOutlineDrawable.setEnabled(false);
|
||||
return;
|
||||
} else {
|
||||
circleDrawable.setEnabled(true);
|
||||
circleOutlineDrawable.setEnabled(true);
|
||||
}
|
||||
|
||||
// update attributes
|
||||
if (renderImpl->circleDrawableInfo.dirty) {
|
||||
// vertex attribute data is shared between the 2 circle drawables
|
||||
const auto& geometry = renderImpl->circleDrawableInfo.geometry;
|
||||
|
||||
using VertexVector = gfx::VertexVector<RenderLocationIndicatorImpl::vec2>;
|
||||
std::shared_ptr<VertexVector> verts = std::make_shared<VertexVector>();
|
||||
for (const auto& elem : geometry) {
|
||||
verts->emplace_back(elem);
|
||||
}
|
||||
|
||||
auto& circleVertexAttrs = circleDrawable.getVertexAttributes();
|
||||
if (const auto& attr = circleVertexAttrs->set(shaders::idCommonPosVertexAttribute)) {
|
||||
attr->setSharedRawData(
|
||||
verts, 0, 0, sizeof(RenderLocationIndicatorImpl::vec2), gfx::AttributeDataType::Float2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto updateQuadDrawable = [&](RenderLocationIndicatorImpl::QuadDrawableInfo& info) {
|
||||
auto& drawable = info.getDrawable();
|
||||
|
||||
if (info.dirty) {
|
||||
auto vertexAttrs = drawable.getVertexAttributes();
|
||||
|
||||
if (const auto& attr = vertexAttrs->set(
|
||||
shaders::idCommonPosVertexAttribute, 0, gfx::AttributeDataType::Float2)) {
|
||||
auto geoDataPtr = reinterpret_cast<const uint8_t*>(info.geometry.data());
|
||||
auto geoDataSize = info.geometry.size() * sizeof(RenderLocationIndicatorImpl::vec2);
|
||||
|
||||
std::vector<uint8_t> rawData;
|
||||
std::copy(geoDataPtr, geoDataPtr + geoDataSize, std::back_inserter(rawData));
|
||||
attr->setRawData(std::move(rawData));
|
||||
}
|
||||
|
||||
info.dirty = false;
|
||||
}
|
||||
|
||||
if (info.textureInfo.dirty) {
|
||||
if (info.textureInfo.image) {
|
||||
if (!info.textureInfo.texture) {
|
||||
info.textureInfo.texture = context.createTexture2D();
|
||||
info.textureInfo.texture->setSamplerConfiguration({gfx::TextureFilterType::Linear,
|
||||
gfx::TextureWrapType::Clamp,
|
||||
gfx::TextureWrapType::Clamp,
|
||||
16,
|
||||
true});
|
||||
}
|
||||
|
||||
info.textureInfo.texture->upload(info.textureInfo.image->get()->image);
|
||||
info.textureInfo.image.reset();
|
||||
}
|
||||
|
||||
drawable.setTexture(info.textureInfo.texture, shaders::idCommonTexture);
|
||||
info.textureInfo.dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
updateCircleDrawable();
|
||||
updateQuadDrawable(renderImpl->shadowDrawableInfo);
|
||||
updateQuadDrawable(renderImpl->puckDrawableInfo);
|
||||
updateQuadDrawable(renderImpl->hatDrawableInfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RenderLocationIndicatorLayer::populateDynamicRenderFeatureIndex(DynamicFeatureIndex& index) const {
|
||||
renderImpl->updateFeature();
|
||||
if (!renderImpl->featureEnvelope->empty()) index.insert(renderImpl->feature, renderImpl->featureEnvelope);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -9,9 +9,27 @@ namespace mbgl {
|
||||
class RenderLocationIndicatorImpl;
|
||||
class RenderLocationIndicatorLayer final : public RenderLayer {
|
||||
public:
|
||||
enum class LocationIndicatorComponentType : uint8_t {
|
||||
Circle,
|
||||
CircleOutline,
|
||||
PuckShadow,
|
||||
Puck,
|
||||
PuckHat,
|
||||
Undefined = 255
|
||||
};
|
||||
|
||||
explicit RenderLocationIndicatorLayer(Immutable<style::LocationIndicatorLayer::Impl>);
|
||||
~RenderLocationIndicatorLayer() override;
|
||||
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
void update(gfx::ShaderRegistry &,
|
||||
gfx::Context &,
|
||||
const TransformState &,
|
||||
const std::shared_ptr<UpdateParameters> &,
|
||||
const RenderTree &,
|
||||
UniqueChangeRequestVec &) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void transition(const TransitionParameters &) override;
|
||||
void evaluate(const PropertyEvaluationParameters &) override;
|
||||
@@ -26,9 +44,16 @@ private:
|
||||
|
||||
void populateDynamicRenderFeatureIndex(DynamicFeatureIndex &) const override;
|
||||
|
||||
private:
|
||||
bool contextDestroyed = false;
|
||||
std::unique_ptr<RenderLocationIndicatorImpl> renderImpl;
|
||||
style::LocationIndicatorPaintProperties::Unevaluated unevaluated;
|
||||
|
||||
#if !MLN_RENDER_BACKEND_OPENGL
|
||||
// Drawable shaders
|
||||
gfx::ShaderProgramBasePtr quadShader;
|
||||
gfx::ShaderProgramBasePtr circleShader;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -525,10 +525,10 @@ void Renderer::Impl::render(const RenderTree& renderTree,
|
||||
parameters.renderPass.reset();
|
||||
|
||||
const auto startRendering = util::MonotonicTimer::now().count();
|
||||
// present submits render commands
|
||||
parameters.encoder->present(parameters.backend.getDefaultRenderable());
|
||||
const auto renderingTime = util::MonotonicTimer::now().count() - startRendering;
|
||||
|
||||
// CommandEncoder destructor submits render commands.
|
||||
parameters.encoder.reset();
|
||||
context.endFrame();
|
||||
|
||||
|
||||
28
src/mbgl/shaders/vulkan/common.cpp
Normal file
28
src/mbgl/shaders/vulkan/common.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <mbgl/shaders/vulkan/common.hpp>
|
||||
#include <mbgl/shaders/common_ubo.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
const std::array<UniformBlockInfo, 1> ShaderSource<BuiltIn::CommonShader, gfx::Backend::Type::Vulkan>::uniforms = {
|
||||
UniformBlockInfo{true, true, sizeof(CommonUBO), idCommonUBO},
|
||||
};
|
||||
const std::array<AttributeInfo, 1> ShaderSource<BuiltIn::CommonShader, gfx::Backend::Type::Vulkan>::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Float2, idCommonPosVertexAttribute},
|
||||
};
|
||||
|
||||
const std::array<UniformBlockInfo, 1>
|
||||
ShaderSource<BuiltIn::CommonTexturedShader, gfx::Backend::Type::Vulkan>::uniforms = {
|
||||
UniformBlockInfo{true, true, sizeof(CommonUBO), idCommonUBO},
|
||||
};
|
||||
const std::array<AttributeInfo, 2> ShaderSource<BuiltIn::CommonTexturedShader, gfx::Backend::Type::Vulkan>::attributes =
|
||||
{
|
||||
AttributeInfo{0, gfx::AttributeDataType::Float2, idCommonPosVertexAttribute},
|
||||
AttributeInfo{1, gfx::AttributeDataType::Float2, idCommonTexVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::CommonTexturedShader, gfx::Backend::Type::Vulkan>::textures = {
|
||||
TextureInfo{0, idCommonTexture},
|
||||
};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -164,9 +164,5 @@ std::size_t BufferResource::getVulkanBufferOffset() const noexcept {
|
||||
return context.getCurrentFrameResourceIndex() * bufferWindowSize;
|
||||
}
|
||||
|
||||
std::size_t BufferResource::getVulkanBufferSize() const noexcept {
|
||||
return bufferWindowSize > 0 ? bufferWindowSize : size;
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -425,7 +425,7 @@ bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept {
|
||||
const auto& bufferResource = uniformBufferImpl.getBufferResource();
|
||||
descriptorBufferInfo.setBuffer(bufferResource.getVulkanBuffer())
|
||||
.setOffset(bufferResource.getVulkanBufferOffset())
|
||||
.setRange(bufferResource.getVulkanBufferSize());
|
||||
.setRange(bufferResource.getSizeInBytes());
|
||||
} else if (fillGaps) {
|
||||
descriptorBufferInfo.setBuffer(context.getDummyUniformBuffer()->getVulkanBuffer())
|
||||
.setOffset(0)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <mbgl/shaders/vulkan/circle.hpp>
|
||||
#include <mbgl/shaders/vulkan/clipping_mask.hpp>
|
||||
#include <mbgl/shaders/vulkan/collision.hpp>
|
||||
#include <mbgl/shaders/vulkan/common.hpp>
|
||||
#include <mbgl/shaders/vulkan/debug.hpp>
|
||||
#include <mbgl/shaders/vulkan/fill.hpp>
|
||||
#include <mbgl/shaders/vulkan/heatmap.hpp>
|
||||
@@ -195,7 +196,8 @@ void RendererBackend::initFrameCapture() {
|
||||
void RendererBackend::startFrameCapture() {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
if (g_rdoc_api) {
|
||||
g_rdoc_api->StartFrameCapture(nullptr, nullptr);
|
||||
RENDERDOC_DevicePointer devicePtr = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(instance->operator VkInstance_T*());
|
||||
g_rdoc_api->StartFrameCapture(devicePtr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -203,7 +205,8 @@ void RendererBackend::startFrameCapture() {
|
||||
void RendererBackend::endFrameCapture() {
|
||||
#ifdef ENABLE_RENDERDOC_FRAME_CAPTURE
|
||||
if (g_rdoc_api) {
|
||||
g_rdoc_api->EndFrameCapture(nullptr, nullptr);
|
||||
RENDERDOC_DevicePointer devicePtr = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(instance->operator VkInstance_T*());
|
||||
g_rdoc_api->EndFrameCapture(devicePtr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -525,10 +528,16 @@ void RendererBackend::initDevice() {
|
||||
// physicalDeviceProperties.limits.lineWidthRange;
|
||||
// physicalDeviceProperties.limits.lineWidthGranularity;
|
||||
} else {
|
||||
mbgl::Log::Error(mbgl::Event::Render, "Wide line support not available");
|
||||
mbgl::Log::Error(mbgl::Event::Render, "Feature not available: wideLines");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (supportedDeviceFeatures.samplerAnisotropy) {
|
||||
physicalDeviceFeatures.setSamplerAnisotropy(true);
|
||||
} else {
|
||||
mbgl::Log::Error(mbgl::Event::Render, "Feature not available: samplerAnisotropy");
|
||||
}
|
||||
|
||||
auto createInfo = vk::DeviceCreateInfo()
|
||||
.setQueueCreateInfos(queueCreateInfos)
|
||||
.setEnabledExtensionCount(static_cast<uint32_t>(extensions.size()))
|
||||
@@ -612,6 +621,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
|
||||
shaders::BuiltIn::ClippingMaskProgram,
|
||||
shaders::BuiltIn::CollisionBoxShader,
|
||||
shaders::BuiltIn::CollisionCircleShader,
|
||||
shaders::BuiltIn::CommonShader,
|
||||
shaders::BuiltIn::CommonTexturedShader,
|
||||
shaders::BuiltIn::CustomSymbolIconShader,
|
||||
shaders::BuiltIn::DebugShader,
|
||||
shaders::BuiltIn::FillShader,
|
||||
|
||||
@@ -190,7 +190,11 @@ void Texture2D::uploadSubRegion(const void* pixelData,
|
||||
|
||||
buffer->copyBufferToImage(bufferAllocation->buffer, imageAllocation->image, imageLayout, region);
|
||||
|
||||
transitionToShaderReadLayout(buffer);
|
||||
if (samplerState.mipmapped && textureUsage == Texture2DUsage::ShaderInput) {
|
||||
generateMips(buffer);
|
||||
} else {
|
||||
transitionToShaderReadLayout(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
enqueueCommands(commandBuffer);
|
||||
@@ -269,6 +273,10 @@ void Texture2D::createTexture() {
|
||||
imageUsage = vk::ImageUsageFlags() | vk::ImageUsageFlagBits::eTransferDst |
|
||||
vk::ImageUsageFlagBits::eSampled;
|
||||
imageTiling = vk::ImageTiling::eOptimal;
|
||||
|
||||
if (samplerState.mipmapped) {
|
||||
imageUsage |= vk::ImageUsageFlagBits::eTransferSrc;
|
||||
}
|
||||
break;
|
||||
|
||||
case Texture2DUsage::Attachment:
|
||||
@@ -287,7 +295,7 @@ void Texture2D::createTexture() {
|
||||
.setImageType(vk::ImageType::e2D)
|
||||
.setFormat(format)
|
||||
.setExtent({size.width, size.height, 1})
|
||||
.setMipLevels(1)
|
||||
.setMipLevels(getMipLevels())
|
||||
.setArrayLayers(1)
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setTiling(imageTiling)
|
||||
@@ -331,7 +339,7 @@ void Texture2D::createTexture() {
|
||||
.setFormat(format)
|
||||
.setComponents(imageSwizzle)
|
||||
.setSubresourceRange(
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
{vk::ImageAspectFlagBits::eColor, 0, imageCreateInfo.mipLevels, 0, 1});
|
||||
|
||||
imageAllocation->imageView = backend.getDevice()->createImageViewUnique(imageViewCreateInfo);
|
||||
}
|
||||
@@ -357,16 +365,22 @@ void Texture2D::createSampler() {
|
||||
const auto addressModeU = vulkanAddressMode(samplerState.wrapU);
|
||||
const auto addressModeV = vulkanAddressMode(samplerState.wrapV);
|
||||
|
||||
const auto samplerCreateInfo = vk::SamplerCreateInfo()
|
||||
.setMinFilter(filter)
|
||||
.setMagFilter(filter)
|
||||
.setMipmapMode(vk::SamplerMipmapMode::eNearest)
|
||||
.setMinLod(-VK_LOD_CLAMP_NONE)
|
||||
.setMaxLod(VK_LOD_CLAMP_NONE)
|
||||
.setAddressModeU(addressModeU)
|
||||
.setAddressModeV(addressModeV)
|
||||
.setAddressModeW(vk::SamplerAddressMode::eRepeat)
|
||||
.setAnisotropyEnable(false);
|
||||
auto samplerCreateInfo = vk::SamplerCreateInfo()
|
||||
.setMinFilter(filter)
|
||||
.setMagFilter(filter)
|
||||
.setMinLod(-VK_LOD_CLAMP_NONE)
|
||||
.setMaxLod(VK_LOD_CLAMP_NONE)
|
||||
.setAddressModeU(addressModeU)
|
||||
.setAddressModeV(addressModeV)
|
||||
.setAddressModeW(vk::SamplerAddressMode::eRepeat);
|
||||
|
||||
if (samplerState.mipmapped) {
|
||||
samplerCreateInfo.setMipmapMode(vk::SamplerMipmapMode::eLinear);
|
||||
}
|
||||
|
||||
if (samplerState.maxAnisotropy != 1 && context.getBackend().getDeviceFeatures().samplerAnisotropy) {
|
||||
samplerCreateInfo.setAnisotropyEnable(true).setMaxAnisotropy(samplerState.maxAnisotropy);
|
||||
}
|
||||
|
||||
sampler = context.getBackend().getDevice()->createSampler(samplerCreateInfo);
|
||||
|
||||
@@ -400,8 +414,7 @@ void Texture2D::transitionToTransferLayout(const vk::UniqueCommandBuffer& buffer
|
||||
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
|
||||
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setSubresourceRange(
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, getMipLevels(), 0, 1});
|
||||
|
||||
buffer->pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, barrier);
|
||||
@@ -418,8 +431,7 @@ void Texture2D::transitionToShaderReadLayout(const vk::UniqueCommandBuffer& buff
|
||||
.setDstAccessMask(vk::AccessFlagBits::eShaderRead)
|
||||
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setSubresourceRange(
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
|
||||
buffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::PipelineStageFlagBits::eFragmentShader,
|
||||
@@ -440,8 +452,7 @@ void Texture2D::transitionToGeneralLayout(const vk::UniqueCommandBuffer& buffer)
|
||||
.setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
|
||||
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setSubresourceRange(
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
|
||||
buffer->pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, barrier);
|
||||
@@ -507,5 +518,88 @@ std::shared_ptr<PremultipliedImage> Texture2D::readImage() {
|
||||
return imageData;
|
||||
}
|
||||
|
||||
uint32_t Texture2D::getMipLevels() const {
|
||||
if (samplerState.mipmapped && size.width > 0 && size.height > 0) {
|
||||
return static_cast<uint32_t>(std::floor(std::log2(std::max(size.width, size.height))) + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Texture2D::generateMips(const vk::UniqueCommandBuffer& buffer) {
|
||||
const uint32_t mipLevels = getMipLevels();
|
||||
|
||||
if (mipLevels <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t mipWidth = size.width;
|
||||
int32_t mipHeight = size.height;
|
||||
|
||||
auto barrier = vk::ImageMemoryBarrier()
|
||||
.setImage(imageAllocation->image)
|
||||
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
|
||||
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
|
||||
for (uint32_t i = 1; i < mipLevels; ++i) {
|
||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||
|
||||
// flip transfer direction
|
||||
barrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal)
|
||||
.setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
|
||||
.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
|
||||
.setDstAccessMask(vk::AccessFlagBits::eTransferRead);
|
||||
|
||||
buffer->pipelineBarrier(
|
||||
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, barrier);
|
||||
|
||||
const auto blit = vk::ImageBlit()
|
||||
.setSrcOffsets({vk::Offset3D{0, 0, 0}, {mipWidth, mipHeight, 1}})
|
||||
.setDstOffsets({vk::Offset3D{0, 0, 0}, {mipWidth / 2, mipHeight / 2, 1}})
|
||||
.setSrcSubresource({vk::ImageAspectFlagBits::eColor, i - 1, 0, 1})
|
||||
.setDstSubresource({vk::ImageAspectFlagBits::eColor, i, 0, 1});
|
||||
|
||||
buffer->blitImage(imageAllocation->image,
|
||||
barrier.newLayout,
|
||||
imageAllocation->image,
|
||||
barrier.oldLayout,
|
||||
blit,
|
||||
vk::Filter::eLinear);
|
||||
|
||||
barrier.setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
|
||||
.setNewLayout(vk::ImageLayout::eShaderReadOnlyOptimal)
|
||||
.setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
|
||||
.setDstAccessMask(vk::AccessFlagBits::eShaderRead);
|
||||
|
||||
buffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::PipelineStageFlagBits::eFragmentShader,
|
||||
{},
|
||||
nullptr,
|
||||
nullptr,
|
||||
barrier);
|
||||
|
||||
mipWidth = std::max(1, mipWidth / 2);
|
||||
mipHeight = std::max(1, mipHeight / 2);
|
||||
}
|
||||
|
||||
// transition the last mip
|
||||
barrier.subresourceRange.baseMipLevel = mipLevels - 1;
|
||||
|
||||
barrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal)
|
||||
.setNewLayout(vk::ImageLayout::eShaderReadOnlyOptimal)
|
||||
.setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
|
||||
.setDstAccessMask(vk::AccessFlagBits::eShaderRead);
|
||||
|
||||
buffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::PipelineStageFlagBits::eFragmentShader,
|
||||
{},
|
||||
nullptr,
|
||||
nullptr,
|
||||
barrier);
|
||||
|
||||
imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user