diff --git a/.github/workflows/android-device-test.yml b/.github/workflows/android-device-test.yml index 9d1c2efbe52..263c4c76ae3 100644 --- a/.github/workflows/android-device-test.yml +++ b/.github/workflows/android-device-test.yml @@ -144,9 +144,6 @@ jobs: export testPackageType=INSTRUMENTATION_TEST_PACKAGE export testType=INSTRUMENTATION export testFilter="${{ matrix.test.testFilter }}" - export AWS_ACCESS_KEY_ID="${{ secrets.AWS_ACCESS_KEY_ID }}" - export AWS_SECRET_ACCESS_KEY="${{ secrets.AWS_SECRET_ACCESS_KEY }}" - export AWS_ROLE_TO_ASSUME="${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}" export AWS_DEVICE_FARM_PROJECT_ARN="${{ vars.AWS_DEVICE_FARM_PROJECT_ARN }}" export AWS_DEVICE_FARM_DEVICE_POOL_ARN="${{ matrix.test.devicePool }}" export testSpecArn="${{ matrix.test.testSpecArn }}" diff --git a/.github/workflows/ios-device-test.yml b/.github/workflows/ios-device-test.yml index 5ea5666f28e..fc8bde6698c 100644 --- a/.github/workflows/ios-device-test.yml +++ b/.github/workflows/ios-device-test.yml @@ -58,9 +58,6 @@ jobs: export testFile="${{ matrix.test.xcTestFile }}" export testPackageType=XCTEST_TEST_PACKAGE export testType=XCTEST - export AWS_ACCESS_KEY_ID="${{ secrets.AWS_ACCESS_KEY_ID }}" - export AWS_SECRET_ACCESS_KEY="${{ secrets.AWS_SECRET_ACCESS_KEY }}" - export AWS_ROLE_TO_ASSUME="${{ vars.OIDC_AWS_ROLE_TO_ASSUME }}" export AWS_DEVICE_FARM_PROJECT_ARN="${{ vars.AWS_DEVICE_FARM_PROJECT_ARN }}" export AWS_DEVICE_FARM_DEVICE_POOL_ARN="${{ vars.AWS_DEVICE_FARM_IPHONE_DEVICE_POOL_ARN }}" export wait_for_completion=true diff --git a/benchmark/android/gradle/wrapper/gradle-wrapper.properties b/benchmark/android/gradle/wrapper/gradle-wrapper.properties index 66cd5a0e49b..7cf748e7430 100644 --- a/benchmark/android/gradle/wrapper/gradle-wrapper.properties +++ b/benchmark/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/include/mbgl/util/instrumentation.hpp b/include/mbgl/util/instrumentation.hpp index 852871442e8..e3882a31fa5 100644 --- a/include/mbgl/util/instrumentation.hpp +++ b/include/mbgl/util/instrumentation.hpp @@ -20,9 +20,10 @@ const void* castGpuIdToTracyPtr(GpuId id) { return reinterpret_cast(static_cast(id)); } -#ifndef MLN_RENDER_BACKEND_OPENGL +#if !defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MLN_RENDER_BACKEND_VULKAN) #error \ - "MLN_RENDER_BACKEND_OPENGL is not defined. MLN_RENDER_BACKEND_OPENGL is expected to be defined in CMake and Bazel" + "MLN_RENDER_BACKEND_OPENGL/MLN_RENDER_BACKEND_VULKAN is not defined. \ + MLN_RENDER_BACKEND_OPENGL/MLN_RENDER_BACKEND_VULKAN is expected to be defined in CMake and Bazel" #endif #define MLN_TRACE_FUNC() ZoneScoped @@ -88,14 +89,21 @@ constexpr const char* tracyConstMemoryLabel = "Constant Buffer Memory"; #undef glGetQueryObjectui64v #undef GLint -#else // MLN_RENDER_BACKEND_OPENGL +#elif MLN_RENDER_BACKEND_VULKAN + +#define MLN_END_FRAME() \ + do { \ + FrameMark; \ + } while (0); + +#else #define MLN_TRACE_GL_CONTEXT() ((void)0) #define MLN_TRACE_GL_ZONE(label) ((void)0) #define MLN_TRACE_FUNC_GL() ((void)0) #define MLN_END_FRAME() FrameMark -#endif // MLN_RENDER_BACKEND_OPENGL +#endif #else // MLN_TRACY_ENABLE diff --git a/include/mbgl/vulkan/descriptor_set.hpp b/include/mbgl/vulkan/descriptor_set.hpp index a4f3fb3c1bb..fff737a7d91 100644 --- a/include/mbgl/vulkan/descriptor_set.hpp +++ b/include/mbgl/vulkan/descriptor_set.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { namespace vulkan { @@ -21,6 +22,7 @@ struct DescriptorPoolGrowable { struct PoolInfo { vk::UniqueDescriptorPool pool; uint32_t remainingSets{0}; + std::queue> unusedSets; PoolInfo(vk::UniqueDescriptorPool&& pool_, uint32_t remainingSets_) : pool(std::move(pool_)), diff --git a/include/mbgl/vulkan/texture2d.hpp b/include/mbgl/vulkan/texture2d.hpp index 7d88e3e87c0..b0aaef237f9 100644 --- a/include/mbgl/vulkan/texture2d.hpp +++ b/include/mbgl/vulkan/texture2d.hpp @@ -59,6 +59,8 @@ class Texture2D : public gfx::Texture2D { size_t getPixelStride() const noexcept override; size_t numChannels() const noexcept override; + bool isDirty() const { return samplerStateDirty || textureDirty; } + void create() noexcept override; void upload() noexcept override; diff --git a/metrics/expectations/platform-android-vulkan/render-tests/icon-text-fit/textFit-grid-long/expected.png b/metrics/expectations/platform-android-vulkan/render-tests/icon-text-fit/textFit-grid-long/expected.png index 060dce66232..5b2fabc6c8c 100644 Binary files a/metrics/expectations/platform-android-vulkan/render-tests/icon-text-fit/textFit-grid-long/expected.png and b/metrics/expectations/platform-android-vulkan/render-tests/icon-text-fit/textFit-grid-long/expected.png differ diff --git a/metrics/ignores/linux-vulkan.json b/metrics/ignores/linux-vulkan.json index e49d79329c9..a0d601b4203 100644 --- a/metrics/ignores/linux-vulkan.json +++ b/metrics/ignores/linux-vulkan.json @@ -1,4 +1,5 @@ { "render-tests/fill-extrusion-color/function": "Layer Z Fighting: https://github.com/maplibre/maplibre-native/issues/1847", - "render-tests/tilejson-bounds/default": "flaky on CI" + "render-tests/tilejson-bounds/default": "flaky on CI", + "render-tests/icon-text-fit/textFit-grid-long": "Needs to be investigated" } \ No newline at end of file diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index 9355b415575..94113f200e6 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/render-test/android/gradle/wrapper/gradle-wrapper.properties b/render-test/android/gradle/wrapper/gradle-wrapper.properties index 66cd5a0e49b..7cf748e7430 100644 --- a/render-test/android/gradle/wrapper/gradle-wrapper.properties +++ b/render-test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/scripts/aws-device-farm/aws-device-farm-run.sh b/scripts/aws-device-farm/aws-device-farm-run.sh index 31b58db2fd1..9b76bb0f844 100755 --- a/scripts/aws-device-farm/aws-device-farm-run.sh +++ b/scripts/aws-device-farm/aws-device-farm-run.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + # List of required environment variables required_vars=( "AWS_DEVICE_FARM_PROJECT_ARN" diff --git a/src/mbgl/vulkan/buffer_resource.cpp b/src/mbgl/vulkan/buffer_resource.cpp index 0289149dad4..ddcc505900e 100644 --- a/src/mbgl/vulkan/buffer_resource.cpp +++ b/src/mbgl/vulkan/buffer_resource.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -48,6 +49,8 @@ BufferResource::BufferResource( size(size_), usage(usage_), persistent(persistent_) { + MLN_TRACE_FUNC(); + const auto& allocator = context.getBackend().getAllocator(); std::size_t totalSize = size; @@ -141,6 +144,8 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept { } void BufferResource::update(const void* newData, std::size_t updateSize, std::size_t offset) noexcept { + MLN_TRACE_FUNC(); + assert(updateSize + offset <= size); updateSize = std::min(updateSize, size - offset); if (updateSize <= 0) { diff --git a/src/mbgl/vulkan/context.cpp b/src/mbgl/vulkan/context.cpp index 1d812d82683..5a6e9863438 100644 --- a/src/mbgl/vulkan/context.cpp +++ b/src/mbgl/vulkan/context.cpp @@ -144,6 +144,8 @@ void Context::enqueueDeletion(std::function&& function) { } void Context::submitOneTimeCommand(const std::function& function) const { + MLN_TRACE_FUNC(); + const vk::CommandBufferAllocateInfo allocateInfo( backend.getCommandPool().get(), vk::CommandBufferLevel::ePrimary, 1); @@ -170,6 +172,7 @@ void Context::submitOneTimeCommand(const std::function::max(); @@ -180,6 +183,8 @@ void Context::waitFrame() const { } } void Context::beginFrame() { + MLN_TRACE_FUNC(); + const auto& device = backend.getDevice(); auto& renderableResource = backend.getDefaultRenderable().getResource(); const auto& platformSurface = renderableResource.getPlatformSurface(); @@ -208,6 +213,7 @@ void Context::beginFrame() { frame.runDeletionQueue(*this); if (platformSurface) { + MLN_TRACE_ZONE(acquireNextImageKHR); try { const vk::ResultValue acquireImageResult = device->acquireNextImageKHR( renderableResource.getSwapchain().get(), timeout, frame.surfaceSemaphore.get(), nullptr); @@ -245,6 +251,7 @@ void Context::endFrame() { } void Context::submitFrame() { + MLN_TRACE_FUNC(); const auto& frame = frameResources[frameResourceIndex]; frame.commandBuffer->end(); @@ -626,6 +633,8 @@ const vk::UniquePipelineLayout& Context::getPushConstantPipelineLayout() { } void Context::FrameResources::runDeletionQueue(Context& context) { + MLN_TRACE_FUNC(); + for (const auto& function : deletionQueue) function(context); deletionQueue.clear(); diff --git a/src/mbgl/vulkan/descriptor_set.cpp b/src/mbgl/vulkan/descriptor_set.cpp index 79d2a86a8fa..d8d6866e5e7 100644 --- a/src/mbgl/vulkan/descriptor_set.cpp +++ b/src/mbgl/vulkan/descriptor_set.cpp @@ -4,10 +4,13 @@ #include #include #include +#include #include #include +#define USE_DESCRIPTOR_POOL_RESET + namespace mbgl { namespace vulkan { @@ -19,8 +22,12 @@ DescriptorSet::~DescriptorSet() { context.enqueueDeletion( [type_ = type, poolIndex = descriptorPoolIndex, sets = std::move(descriptorSets)](auto& context_) mutable { auto& poolInfo = context_.getDescriptorPool(type_).pools[poolIndex]; +#ifdef USE_DESCRIPTOR_POOL_RESET + poolInfo.unusedSets.push(std::move(sets)); +#else context_.getBackend().getDevice()->freeDescriptorSets(poolInfo.pool.get(), sets); poolInfo.remainingSets += sets.size(); +#endif }); } @@ -34,15 +41,21 @@ void DescriptorSet::createDescriptorPool(DescriptorPoolGrowable& growablePool) { : vk::DescriptorType::eCombinedImageSampler, maxSets * growablePool.descriptorsPerSet}; - const auto descriptorPoolInfo = vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet) - .setPoolSizes(size) - .setMaxSets(maxSets); +#ifdef USE_DESCRIPTOR_POOL_RESET + const auto poolFlags = vk::DescriptorPoolCreateFlags(); +#else + const auto poolFlags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet; +#endif + + const auto descriptorPoolInfo = vk::DescriptorPoolCreateInfo(poolFlags).setPoolSizes(size).setMaxSets(maxSets); growablePool.pools.emplace_back(device->createDescriptorPoolUnique(descriptorPoolInfo), maxSets); growablePool.currentPoolIndex = growablePool.pools.size() - 1; }; void DescriptorSet::allocate() { + MLN_TRACE_FUNC(); + if (!descriptorSets.empty()) { return; } @@ -52,31 +65,55 @@ void DescriptorSet::allocate() { auto& growablePool = context.getDescriptorPool(type); const std::vector layouts(context.getBackend().getMaxFrames(), descriptorSetLayout); - if (growablePool.currentPoolIndex == -1 || growablePool.current().remainingSets < layouts.size()) { - const auto& poolIt = std::find_if(growablePool.pools.begin(), growablePool.pools.end(), [&](const auto& p) { - return p.remainingSets >= layouts.size(); - }); - - if (poolIt != growablePool.pools.end()) { - growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), poolIt); - } else { - createDescriptorPool(growablePool); + if (growablePool.currentPoolIndex == -1 || + (growablePool.current().unusedSets.empty() && growablePool.current().remainingSets < layouts.size())) { +#ifdef USE_DESCRIPTOR_POOL_RESET + // find a pool that has unused allocated descriptor sets + const auto& unusedPoolIt = std::find_if( + growablePool.pools.begin(), growablePool.pools.end(), [&](const auto& p) { return !p.unusedSets.empty(); }); + + if (unusedPoolIt != growablePool.pools.end()) { + growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), unusedPoolIt); + } else +#endif + { + // find a pool that has available memory to allocate more descriptor sets + const auto& freePoolIt = std::find_if(growablePool.pools.begin(), + growablePool.pools.end(), + [&](const auto& p) { return p.remainingSets >= layouts.size(); }); + + if (freePoolIt != growablePool.pools.end()) { + growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), freePoolIt); + } else { + createDescriptorPool(growablePool); + } } } descriptorPoolIndex = growablePool.currentPoolIndex; - descriptorSets = device->allocateDescriptorSets( - vk::DescriptorSetAllocateInfo().setDescriptorPool(growablePool.current().pool.get()).setSetLayouts(layouts)); - growablePool.current().remainingSets -= descriptorSets.size(); - markDirty(true); +#ifdef USE_DESCRIPTOR_POOL_RESET + if (!growablePool.current().unusedSets.empty()) { + descriptorSets = growablePool.current().unusedSets.front(); + growablePool.current().unusedSets.pop(); + } else +#endif + { + descriptorSets = device->allocateDescriptorSets(vk::DescriptorSetAllocateInfo() + .setDescriptorPool(growablePool.current().pool.get()) + .setSetLayouts(layouts)); + growablePool.current().remainingSets -= descriptorSets.size(); + } + + dirty = std::vector(descriptorSets.size(), true); } void DescriptorSet::markDirty(bool value) { - dirty = std::vector(descriptorSets.size(), value); + std::fill(dirty.begin(), dirty.end(), value); } void DescriptorSet::bind(CommandEncoder& encoder) { + MLN_TRACE_FUNC(); auto& commandBuffer = encoder.getCommandBuffer(); const uint8_t index = context.getCurrentFrameResourceIndex(); @@ -94,6 +131,8 @@ UniformDescriptorSet::UniformDescriptorSet(Context& context_, DescriptorSetType void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms, uint32_t uniformStartIndex, uint32_t descriptorBindingCount) { + MLN_TRACE_FUNC(); + allocate(); const uint8_t frameIndex = context.getCurrentFrameResourceIndex(); @@ -127,12 +166,15 @@ void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms, device->updateDescriptorSets(writeDescriptorSet, nullptr); } + + dirty[frameIndex] = false; } ImageDescriptorSet::ImageDescriptorSet(Context& context_) : DescriptorSet(context_, DescriptorSetType::DrawableImage) {} void ImageDescriptorSet::update(const std::array& textures) { + MLN_TRACE_FUNC(); allocate(); const uint8_t frameIndex = context.getCurrentFrameResourceIndex(); @@ -160,6 +202,8 @@ void ImageDescriptorSet::update(const std::arrayupdateDescriptorSets(writeDescriptorSet, nullptr); } + + dirty[frameIndex] = false; } } // namespace vulkan diff --git a/src/mbgl/vulkan/drawable.cpp b/src/mbgl/vulkan/drawable.cpp index a8c65f8251a..64dcf681ac0 100644 --- a/src/mbgl/vulkan/drawable.cpp +++ b/src/mbgl/vulkan/drawable.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #if !defined(NDEBUG) @@ -129,6 +130,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices, } void Drawable::upload(gfx::UploadPass& uploadPass_) { + MLN_TRACE_FUNC(); + if (isCustom) { return; } @@ -234,6 +237,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) { } void Drawable::draw(PaintParameters& parameters) const { + MLN_TRACE_FUNC(); + if (isCustom) { return; } @@ -334,6 +339,8 @@ gfx::UniformBufferArray& Drawable::mutableUniformBuffers() { } void Drawable::buildVulkanInputBindings() noexcept { + MLN_TRACE_FUNC(); + impl->vulkanVertexBuffers.clear(); impl->vulkanVertexOffsets.clear(); @@ -386,6 +393,8 @@ void Drawable::buildVulkanInputBindings() noexcept { } bool Drawable::bindAttributes(CommandEncoder& encoder) const noexcept { + MLN_TRACE_FUNC(); + if (impl->vulkanVertexBuffers.empty()) return false; const auto& commandBuffer = encoder.getCommandBuffer(); @@ -403,6 +412,8 @@ bool Drawable::bindAttributes(CommandEncoder& encoder) const noexcept { } bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept { + MLN_TRACE_FUNC(); + if (!shader) return false; // bind uniforms @@ -415,6 +426,15 @@ bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept { impl->imageDescriptorSet = std::make_unique(encoder.getContext()); } + for (const auto& texture : textures) { + if (!texture) continue; + const auto textureImpl = static_cast(texture.get()); + if (textureImpl->isDirty()) { + impl->imageDescriptorSet->markDirty(true); + break; + } + } + impl->imageDescriptorSet->update(textures); impl->imageDescriptorSet->bind(encoder); } @@ -423,6 +443,7 @@ bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept { } void Drawable::uploadTextures(UploadPass&) const noexcept { + MLN_TRACE_FUNC(); for (const auto& texture : textures) { if (texture) { texture->upload(); diff --git a/src/mbgl/vulkan/texture2d.cpp b/src/mbgl/vulkan/texture2d.cpp index d461f68b9cc..7c31f5330d8 100644 --- a/src/mbgl/vulkan/texture2d.cpp +++ b/src/mbgl/vulkan/texture2d.cpp @@ -50,6 +50,11 @@ Texture2D::~Texture2D() { } gfx::Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_) noexcept { + if (samplerState.filter == samplerState_.filter && samplerState.wrapU == samplerState_.wrapU && + samplerState.wrapV == samplerState_.wrapV) { + return *this; + } + samplerState = samplerState_; samplerStateDirty = true; return *this; diff --git a/src/mbgl/vulkan/uniform_buffer.cpp b/src/mbgl/vulkan/uniform_buffer.cpp index 9f5364f2d78..b01e0facc90 100644 --- a/src/mbgl/vulkan/uniform_buffer.cpp +++ b/src/mbgl/vulkan/uniform_buffer.cpp @@ -41,11 +41,20 @@ void UniformBuffer::update(const void* data, std::size_t size_) { const std::shared_ptr& UniformBufferArray::set(const size_t id, std::shared_ptr uniformBuffer) { + if (id >= uniformBufferVector.size()) { + return nullref; + } + + if (uniformBufferVector[id] == uniformBuffer) { + return uniformBufferVector[id]; + } + if (descriptorSet) { descriptorSet->markDirty(); } - return gfx::UniformBufferArray::set(id, uniformBuffer); + uniformBufferVector[id] = std::move(uniformBuffer); + return uniformBufferVector[id]; } void UniformBufferArray::createOrUpdate( diff --git a/test/android/gradle/wrapper/gradle-wrapper.properties b/test/android/gradle/wrapper/gradle-wrapper.properties index 66cd5a0e49b..7cf748e7430 100644 --- a/test/android/gradle/wrapper/gradle-wrapper.properties +++ b/test/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME