diff --git a/CMakeLists.txt b/CMakeLists.txt index e0920c886..4a415e68b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -530,6 +530,8 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/circle_layer_tweaker.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_layer_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/fill_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/render_background_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -946,6 +948,7 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_outline_pattern.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_fill_pattern.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/drawable_raster.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/background_pattern.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/circle.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/clipping_mask.hpp diff --git a/include/mbgl/gl/drawable_gl.hpp b/include/mbgl/gl/drawable_gl.hpp index aa0a610ea..d1e60ac9e 100644 --- a/include/mbgl/gl/drawable_gl.hpp +++ b/include/mbgl/gl/drawable_gl.hpp @@ -60,6 +60,8 @@ protected: DrawableGL(std::unique_ptr); private: + void uploadTextures() const; + void bindUniformBuffers() const; void unbindUniformBuffers() const; diff --git a/include/mbgl/shaders/gl/drawable_raster.hpp b/include/mbgl/shaders/gl/drawable_raster.hpp new file mode 100644 index 000000000..88aeea88d --- /dev/null +++ b/include/mbgl/shaders/gl/drawable_raster.hpp @@ -0,0 +1,107 @@ +// Generated code, do not modify this file! +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "RasterShader"; + static constexpr const char* vertex = R"(layout (std140) uniform RasterDrawableUBO { + highp mat4 u_matrix; + highp vec3 u_spin_weights; + highp vec2 u_tl_parent; + highp float u_scale_parent; + highp float u_buffer_scale; + highp float u_fade_t; + highp float u_opacity; + highp float u_brightness_low; + highp float u_brightness_high; + highp float u_saturation_factor; + highp float u_contrast_factor; + highp float pad1; + highp float pad2; +}; + +layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec2 a_texture_pos; + +out vec2 v_pos0; +out vec2 v_pos1; + +void main() { + gl_Position = u_matrix * vec4(a_pos, 0, 1); + // We are using Int16 for texture position coordinates to give us enough precision for + // fractional coordinates. We use 8192 to scale the texture coordinates in the buffer + // as an arbitrarily high number to preserve adequate precision when rendering. + // This is also the same value as the EXTENT we are using for our tile buffer pos coordinates, + // so math for modifying either is consistent. + v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5; + v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent; +} +)"; + static constexpr const char* fragment = R"(layout (std140) uniform RasterDrawableUBO { + highp mat4 u_matrix; + highp vec3 u_spin_weights; + highp vec2 u_tl_parent; + highp float u_scale_parent; + highp float u_buffer_scale; + highp float u_fade_t; + highp float u_opacity; + highp float u_brightness_low; + highp float u_brightness_high; + highp float u_saturation_factor; + highp float u_contrast_factor; + highp float pad1; + highp float pad2; +}; +uniform sampler2D u_image0; +uniform sampler2D u_image1; + +in vec2 v_pos0; +in vec2 v_pos1; + +void main() { + + // read and cross-fade colors from the main and parent tiles + vec4 color0 = texture(u_image0, v_pos0); + vec4 color1 = texture(u_image1, v_pos1); + if (color0.a > 0.0) { + color0.rgb = color0.rgb / color0.a; + } + if (color1.a > 0.0) { + color1.rgb = color1.rgb / color1.a; + } + vec4 color = mix(color0, color1, u_fade_t); + color.a *= u_opacity; + vec3 rgb = color.rgb; + + // spin + rgb = vec3( + dot(rgb, u_spin_weights.xyz), + dot(rgb, u_spin_weights.zxy), + dot(rgb, u_spin_weights.yzx)); + + // saturation + float average = (color.r + color.g + color.b) / 3.0; + rgb += (average - rgb) * u_saturation_factor; + + // contrast + rgb = (rgb - 0.5) * u_contrast_factor + 0.5; + + // brightness + vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low); + vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high); + + fragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a); + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/shader_program_gl.hpp b/include/mbgl/shaders/gl/shader_program_gl.hpp index 80f9b1fd9..e64426e89 100644 --- a/include/mbgl/shaders/gl/shader_program_gl.hpp +++ b/include/mbgl/shaders/gl/shader_program_gl.hpp @@ -28,6 +28,8 @@ public: const std::string& fragmentSource, const std::string& additionalDefines = "") noexcept(false); + std::optional getSamplerLocation(const std::string& name) const override; + const gfx::UniformBlockArray& getUniformBlocks() const override { return uniformBlocks; } const gfx::VertexAttributeArray& getVertexAttributes() const override { return vertexAttributes; } diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index 4c125fbb5..963c68931 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/include/mbgl/shaders/shader_program_base.hpp b/include/mbgl/shaders/shader_program_base.hpp index dccc41605..5fc04fc6c 100644 --- a/include/mbgl/shaders/shader_program_base.hpp +++ b/include/mbgl/shaders/shader_program_base.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace mbgl { namespace gfx { @@ -29,6 +30,10 @@ protected: public: const util::SimpleIdentity& getID() const { return shaderProgramID; } + /// @brief Gets the sampler location + /// @param name uniform name + virtual std::optional getSamplerLocation(const std::string& name) const = 0; + /// Get the available uniform blocks attached to this shader virtual const gfx::UniformBlockArray& getUniformBlocks() const = 0; diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index 079ffde18..25738b8ef 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -16,6 +16,7 @@ enum class BuiltIn { FillOutlineShader, FillPatternShader, FillOutlinePatternShader, + RasterShader, Prelude, BackgroundProgram, BackgroundPatternProgram, diff --git a/shaders/drawable.raster.fragment.glsl b/shaders/drawable.raster.fragment.glsl new file mode 100644 index 000000000..bc16dfd27 --- /dev/null +++ b/shaders/drawable.raster.fragment.glsl @@ -0,0 +1,59 @@ +layout (std140) uniform RasterDrawableUBO { + highp mat4 u_matrix; + highp vec3 u_spin_weights; + highp vec2 u_tl_parent; + highp float u_scale_parent; + highp float u_buffer_scale; + highp float u_fade_t; + highp float u_opacity; + highp float u_brightness_low; + highp float u_brightness_high; + highp float u_saturation_factor; + highp float u_contrast_factor; + highp float pad1; + highp float pad2; +}; +uniform sampler2D u_image0; +uniform sampler2D u_image1; + +in vec2 v_pos0; +in vec2 v_pos1; + +void main() { + + // read and cross-fade colors from the main and parent tiles + vec4 color0 = texture(u_image0, v_pos0); + vec4 color1 = texture(u_image1, v_pos1); + if (color0.a > 0.0) { + color0.rgb = color0.rgb / color0.a; + } + if (color1.a > 0.0) { + color1.rgb = color1.rgb / color1.a; + } + vec4 color = mix(color0, color1, u_fade_t); + color.a *= u_opacity; + vec3 rgb = color.rgb; + + // spin + rgb = vec3( + dot(rgb, u_spin_weights.xyz), + dot(rgb, u_spin_weights.zxy), + dot(rgb, u_spin_weights.yzx)); + + // saturation + float average = (color.r + color.g + color.b) / 3.0; + rgb += (average - rgb) * u_saturation_factor; + + // contrast + rgb = (rgb - 0.5) * u_contrast_factor + 0.5; + + // brightness + vec3 u_high_vec = vec3(u_brightness_low, u_brightness_low, u_brightness_low); + vec3 u_low_vec = vec3(u_brightness_high, u_brightness_high, u_brightness_high); + + fragColor = vec4(mix(u_high_vec, u_low_vec, rgb) * color.a, color.a); + +#ifdef OVERDRAW_INSPECTOR + fragColor = vec4(1.0); +#endif +} diff --git a/shaders/drawable.raster.vertex.glsl b/shaders/drawable.raster.vertex.glsl new file mode 100644 index 000000000..9cb2fce74 --- /dev/null +++ b/shaders/drawable.raster.vertex.glsl @@ -0,0 +1,32 @@ +layout (std140) uniform RasterDrawableUBO { + highp mat4 u_matrix; + highp vec3 u_spin_weights; + highp vec2 u_tl_parent; + highp float u_scale_parent; + highp float u_buffer_scale; + highp float u_fade_t; + highp float u_opacity; + highp float u_brightness_low; + highp float u_brightness_high; + highp float u_saturation_factor; + highp float u_contrast_factor; + highp float pad1; + highp float pad2; +}; + +layout (location = 0) in vec2 a_pos; +layout (location = 1) in vec2 a_texture_pos; + +out vec2 v_pos0; +out vec2 v_pos1; + +void main() { + gl_Position = u_matrix * vec4(a_pos, 0, 1); + // We are using Int16 for texture position coordinates to give us enough precision for + // fractional coordinates. We use 8192 to scale the texture coordinates in the buffer + // as an arbitrarily high number to preserve adequate precision when rendering. + // This is also the same value as the EXTENT we are using for our tile buffer pos coordinates, + // so math for modifying either is consistent. + v_pos0 = (((a_texture_pos / 8192.0) - 0.5) / u_buffer_scale ) + 0.5; + v_pos1 = (v_pos0 * u_scale_parent) + u_tl_parent; +} diff --git a/shaders/manifest.json b/shaders/manifest.json index bed5d3407..8f885b2bb 100644 --- a/shaders/manifest.json +++ b/shaders/manifest.json @@ -48,6 +48,13 @@ "glsl_frag": "drawable.fill_outline_pattern.fragment.glsl", "uses_ubos": true }, + { + "name": "RasterShader", + "header": "drawable_raster", + "glsl_vert": "drawable.raster.vertex.glsl", + "glsl_frag": "drawable.raster.fragment.glsl", + "uses_ubos": true + }, { "name": "Prelude", diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index 1863ef62d..e926ae2c1 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -178,6 +178,19 @@ void DrawableGL::upload(gfx::UploadPass& uploadPass) { glSeg.setVertexArray(std::move(vertexArray)); }; } + + const bool texturesNeedUpload = std::any_of( + textures.begin(), textures.end(), [](const auto& tex) { return tex.texture->needsUpload(); }); + + if (texturesNeedUpload) { + uploadTextures(); + } +} + +void DrawableGL::uploadTextures() const { + for (const auto& tex : textures) { + std::static_pointer_cast(tex.texture)->upload(); + } } void DrawableGL::bindTextures() const { diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index 1c595f1e1..918493152 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -99,7 +99,8 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::FillShader, shaders::BuiltIn::FillOutlineShader, shaders::BuiltIn::FillOutlinePatternShader, - shaders::BuiltIn::FillPatternShader>(shaders, static_cast(*context), programParameters); + shaders::BuiltIn::FillPatternShader, + shaders::BuiltIn::RasterShader>(shaders, static_cast(*context), programParameters); } } // namespace gl diff --git a/src/mbgl/gl/texture2d.cpp b/src/mbgl/gl/texture2d.cpp index 7aeed519c..4099ffdad 100644 --- a/src/mbgl/gl/texture2d.cpp +++ b/src/mbgl/gl/texture2d.cpp @@ -148,6 +148,7 @@ void Texture2D::bind(int32_t location, int32_t textureUnit) noexcept { // Link the bound texture unit with the requested sampler in the active shader glUniform1i(location, textureUnit); + boundLocation = location; } void Texture2D::unbind() noexcept { diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp new file mode 100644 index 000000000..da3eef0df --- /dev/null +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -0,0 +1,86 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +struct alignas(16) RasterDrawableUBO { + std::array matrix; + std::array spin_weights; + std::array tl_parent; + float scale_parent; + float buffer_scale; + float fade_t; + float opacity; + float brightness_low; + float brightness_high; + float saturation_factor; + float contrast_factor; + float pad1; + float pad2; +}; +static_assert(sizeof(RasterDrawableUBO) == 128); +static_assert(sizeof(RasterDrawableUBO) % 16 == 0); + +void RasterLayerTweaker::execute([[maybe_unused]] LayerGroup& layerGroup, + [[maybe_unused]] const RenderTree& renderTree, + [[maybe_unused]] const PaintParameters& parameters) { + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + + layerGroup.observeDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getTileID()) { + return; + } + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging()); + + auto spinWeights = [](float spin) -> std::array { + spin = util::deg2radf(spin); + float s = std::sin(spin); + float c = std::cos(spin); + std::array spin_weights = { + {(2 * c + 1) / 3, (-std::sqrt(3.0f) * s - c + 1) / 3, (std::sqrt(3.0f) * s - c + 1) / 3, 0}}; + return spin_weights; + }; + auto saturationFactor = [](float saturation) -> float { + if (saturation > 0) { + return 1.f - 1.f / (1.001f - saturation); + } else { + return -saturation; + } + }; + auto contrastFactor = [](float contrast) -> float { + if (contrast > 0) { + return 1 / (1 - contrast); + } else { + return 1 + contrast; + } + }; + + RasterDrawableUBO drawableUBO{/*.matrix = */ util::cast(matrix), + /*.spin_weigths = */ spinWeights(evaluated.get()), + /*.tl_parent = */ {{0.0f, 0.0f}}, + /*.scale_parent = */ 1.0f, + /*.buffer_scale = */ 1.0f, + /*.fade_t = */ 1.0f, + /*.opacity = */ evaluated.get(), + /*.brightness_low = */ evaluated.get(), + /*.brightness_high = */ evaluated.get(), + /*.saturation_factor = */ saturationFactor(evaluated.get()), + /*.contrast_factor = */ contrastFactor(evaluated.get()), + 0, + 0}; + auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("RasterDrawableUBO", drawableUniformBuffer); + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.hpp b/src/mbgl/renderer/layers/raster_layer_tweaker.hpp new file mode 100644 index 000000000..1dae27832 --- /dev/null +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace mbgl { + +namespace gfx { +class UniformBuffer; +using UniformBufferPtr = std::shared_ptr; +} // namespace gfx + +/** + Raster layer tweaker + */ +class RasterLayerTweaker : public LayerTweaker { +public: + RasterLayerTweaker(Immutable properties) + : LayerTweaker(properties){}; + +public: + ~RasterLayerTweaker() override = default; + + void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; + +protected: + gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 5684e13c7..7fc41a4da 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -7,9 +9,12 @@ #include #include #include +#include +#include #include #include #include +#include namespace mbgl { @@ -40,6 +45,10 @@ void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) passes = properties->evaluated.get() > 0 ? RenderPass::Translucent : RenderPass::None; properties->renderPasses = mbgl::underlying_type(passes); evaluatedProperties = std::move(properties); + + if (tileLayerGroup && tileLayerGroup->getLayerTweaker()) { + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + } } bool RenderRasterLayer::hasTransition() const { @@ -197,4 +206,211 @@ void RenderRasterLayer::render(PaintParameters& parameters) { } } +void RenderRasterLayer::layerRemoved(UniqueChangeRequestVec& changes) { + // Remove everything + if (tileLayerGroup) { + changes.emplace_back(std::make_unique(tileLayerGroup->getLayerIndex())); + tileLayerGroup.reset(); + } +} + +void RenderRasterLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { + stats.tileDrawablesRemoved += tileLayerGroup->removeDrawables(renderPass, tileID).size(); +} + +void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, + gfx::Context& context, + const TransformState& /*state*/, + [[maybe_unused]] const RenderTree& renderTree, + [[maybe_unused]] UniqueChangeRequestVec& changes) { + std::unique_lock guard(mutex); + + if ((!renderTiles || renderTiles->empty()) && !imageData) { + if (tileLayerGroup) { + stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount(); + tileLayerGroup->clearDrawables(); + } + return; + } + + // Set up a layer group + if (!tileLayerGroup) { + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64); + if (!tileLayerGroup) { + return; + } + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); + } + + auto renderPass = RenderPass::Translucent; + + if (!rasterShader) { + rasterShader = context.getGenericShader(shaders, "RasterShader"); + } + + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; + RasterProgram::Binders paintAttributeData{evaluated, 0}; + + const gfx::TextureFilterType filter = evaluated.get() == RasterResamplingType::Nearest + ? gfx::TextureFilterType::Nearest + : gfx::TextureFilterType::Linear; + (void)filter; + + if (imageData && !imageData->bucket->needsUpload()) { + // TODO: implement arbitrary image + RasterBucket& bucket = *imageData->bucket; + assert(bucket.texture); + + // size_t i = 0; + for (const auto& matrix_ : imageData->matrices) { + /*draw(matrix_, + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + RasterProgram::TextureBindings{ + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, + }, + std::to_string(i++));*/ + (void)matrix_; + } + } else if (renderTiles) { + tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { + // Has this tile dropped out of the cover set? + if (const auto it = std::find_if(renderTiles->begin(), + renderTiles->end(), + [&drawable](const auto& renderTile) { + return drawable->getTileID() == renderTile.get().getOverscaledTileID(); + }); + it == renderTiles->end()) { + // remove it + drawable.reset(); + ++stats.tileDrawablesRemoved; + } + }); + + for (const RenderTile& tile : *renderTiles) { + const auto& tileID = tile.getOverscaledTileID(); + auto* bucket_ = tile.getBucket(*baseImpl); + if (!bucket_) { + continue; + } + auto& bucket = static_cast(*bucket_); + + if (!bucket.hasData()) continue; + + if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) continue; + + if (bucket.image) { + std::unique_ptr builder{context.createDrawableBuilder("raster")}; + builder->setShader(rasterShader); + builder->setRenderPass(renderPass); + builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); + builder->setSubLayerIndex(0); + builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite + : gfx::DepthMaskType::ReadOnly); + builder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setVertexAttrName("a_pos"); + + // render data + auto buildRenderData = [](const TileMask& mask, + std::vector>& vertices, + std::vector>& attributes, + std::vector& indices, + std::vector>& segments) { + constexpr const uint16_t vertexLength = 4; + + // Create the vertex buffer for the specified tile mask. + for (const auto& id : mask) { + // Create a quad for every masked tile. + const int32_t vertexExtent = util::EXTENT >> id.z; + + const Point tlVertex = {static_cast(id.x * vertexExtent), + static_cast(id.y * vertexExtent)}; + const Point brVertex = {static_cast(tlVertex.x + vertexExtent), + static_cast(tlVertex.y + vertexExtent)}; + + if (segments.empty() || + (segments.back().vertexLength + vertexLength > std::numeric_limits::max())) { + // Move to a new segments because the old one can't hold the geometry. + segments.emplace_back(vertices.size(), indices.size()); + } + + vertices.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); + attributes.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); + + vertices.emplace_back(std::array{{brVertex.x, tlVertex.y}}); + attributes.emplace_back(std::array{{brVertex.x, tlVertex.y}}); + + vertices.emplace_back(std::array{{tlVertex.x, brVertex.y}}); + attributes.emplace_back(std::array{{tlVertex.x, brVertex.y}}); + + vertices.emplace_back(std::array{{brVertex.x, brVertex.y}}); + attributes.emplace_back(std::array{{brVertex.x, brVertex.y}}); + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits::max()); + const auto offset = static_cast(segment.vertexLength); + + // 0, 1, 2 + // 1, 2, 3 + indices.insert(indices.end(), + {offset, static_cast(offset + 1), static_cast(offset + 2u)}); + indices.insert(indices.end(), + {static_cast(offset + 1), + static_cast(offset + 2), + static_cast(offset + 3)}); + + segment.vertexLength += vertexLength; + segment.indexLength += 6; + } + }; + + std::vector> vertices, attributes; + std::vector indices; + std::vector> segments; + buildRenderData(bucket.mask, vertices, attributes, indices, segments); + builder->addVertices(vertices, 0, vertices.size()); + builder->setSegments(gfx::Triangles(), indices, segments); + + // attributes + { + gfx::VertexAttributeArray vertexAttrs; + if (auto& attr = vertexAttrs.getOrAdd("a_texture_pos")) { + std::size_t index{0}; + for (auto& a : attributes) { + attr->set(index++, {a[0], a[1]}); + } + } + builder->setVertexAttributes(std::move(vertexAttrs)); + } + + // textures + // TODO: move texture creation into gfx::Context + std::shared_ptr tex0 = context.createTexture2D(); + tex0->setImage(bucket.image).create(); + auto location0 = rasterShader->getSamplerLocation("u_image0"); + if (location0.has_value()) { + builder->setTexture(tex0, location0.value()); + } + std::shared_ptr tex1 = context.createTexture2D(); + tex1->setImage(bucket.image).create(); + auto location1 = rasterShader->getSamplerLocation("u_image1"); + if (location1.has_value()) { + builder->setTexture(tex1, location1.value()); + } + + // finish + builder->flush(); + for (auto& drawable : builder->clearDrawables()) { + drawable->setTileID(tileID); + tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); + ++stats.tileDrawablesAdded; + } + }; + } + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp index bcde1b730..394b2759c 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.hpp +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -14,6 +14,15 @@ public: explicit RenderRasterLayer(Immutable); ~RenderRasterLayer() override; + void layerRemoved(UniqueChangeRequestVec&) override; + + /// Generate any changes needed by the layer + void update(gfx::ShaderRegistry&, + gfx::Context&, + const TransformState&, + const RenderTree&, + UniqueChangeRequestVec&) override; + private: void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; @@ -22,12 +31,17 @@ private: void prepare(const LayerPrepareParameters&) override; void render(PaintParameters&) override; + /// Remove all drawables for the tile from the layer group + void removeTile(RenderPass, const OverscaledTileID&); + // Paint properties style::RasterPaintProperties::Unevaluated unevaluated; const ImageSourceRenderData* imageData = nullptr; // Programs std::shared_ptr rasterProgram; + + gfx::ShaderProgramBasePtr rasterShader; }; } // namespace mbgl diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 6e69c3e85..b26028b8e 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -111,7 +111,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { }); // Give the layers a chance to do setup - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters); }); + // orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.preRender(orchestrator, parameters); + // }); // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. @@ -320,7 +321,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } #endif - // Give the layers a chance to do cleanup + // Give the layers a chance to do cleanup orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.postRender(orchestrator, parameters); }); // Ends the RenderPass diff --git a/src/mbgl/shaders/gl/shader_program_gl.cpp b/src/mbgl/shaders/gl/shader_program_gl.cpp index 412b9e9f7..0d0ea2454 100644 --- a/src/mbgl/shaders/gl/shader_program_gl.cpp +++ b/src/mbgl/shaders/gl/shader_program_gl.cpp @@ -111,6 +111,11 @@ static void addAttr( } } +std::optional ShaderProgramGL::getSamplerLocation(const std::string& name) const { + GLint sampler_location = MBGL_CHECK_ERROR(glGetUniformLocation(glProgram, name.c_str())); + return (sampler_location == -1) ? std::optional{} : sampler_location; +} + std::shared_ptr ShaderProgramGL::create(Context& context, const ProgramParameters& programParameters, const std::string& /*name*/,