Fix Metal frame glitch on older devices (#2379)

This commit is contained in:
Stefan Karschti
2024-05-15 15:30:28 +03:00
committed by GitHub
parent 8e479eea96
commit aff5693fb9
6 changed files with 57 additions and 4 deletions

View File

@@ -62,7 +62,8 @@ public:
MTLRenderPipelineStatePtr getRenderPipelineState(const gfx::Renderable&,
const MTLVertexDescriptorPtr&,
const gfx::ColorMode& colorMode) const;
const gfx::ColorMode& colorMode,
const std::optional<std::size_t> reuseHash) const;
std::optional<size_t> getSamplerLocation(const size_t id) const override;
@@ -87,6 +88,8 @@ protected:
VertexAttributeArray vertexAttributes;
VertexAttributeArray instanceAttributes;
std::array<std::optional<size_t>, shaders::maxTextureCountPerShader> textureBindings;
mutable mbgl::unordered_map<std::size_t, MTLRenderPipelineStatePtr> renderPipelineStateCache;
};
} // namespace mtl

View File

@@ -3,6 +3,7 @@
#include <mbgl/gfx/types.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/hash.hpp>
namespace mbgl {
namespace gfx {
@@ -58,6 +59,18 @@ public:
static ColorMode additive() {
return {Add{ColorBlendFactorType::One, ColorBlendFactorType::One}, {}, {true, true, true, true}};
}
std::size_t hash() const {
return mbgl::util::hash(blendFunction.which(),
blendColor.r,
blendColor.g,
blendColor.b,
blendColor.a,
mask.r,
mask.g,
mask.b,
mask.a);
}
};
constexpr bool operator!=(const ColorMode::Mask& a, const ColorMode::Mask& b) {

View File

@@ -23,6 +23,7 @@
#include <mbgl/util/std.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/thread_pool.hpp>
#include <mbgl/util/hash.hpp>
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
@@ -361,7 +362,14 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
// Create a render pipeline state, telling Metal how to render the primitives
const auto& renderPassDescriptor = mtlRenderPass.getDescriptor();
if (auto state = mtlShader.getRenderPipelineState(renderable, vertDesc, colorMode)) {
const std::size_t hash = mbgl::util::hash(ShaderClass::attributes[0].index,
0,
MTL::VertexFormatShort2,
vertexSize,
MTL::VertexStepFunctionPerVertex,
1);
if (auto state = mtlShader.getRenderPipelineState(
renderable, vertDesc, colorMode, mbgl::util::hash(colorMode.hash(), hash))) {
clipMaskPipelineState = std::move(state);
}
}

View File

@@ -18,6 +18,7 @@
#include <mbgl/shaders/mtl/shader_program.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/util/hash.hpp>
#include <Metal/Metal.hpp>
@@ -210,7 +211,11 @@ void Drawable::draw(PaintParameters& parameters) const {
encoder->setFrontFacingWinding(mapWindingMode(cullMode.winding));
if (!impl->pipelineState) {
impl->pipelineState = shaderMTL.getRenderPipelineState(renderable, impl->vertexDesc, getColorMode());
impl->pipelineState = shaderMTL.getRenderPipelineState(
renderable,
impl->vertexDesc,
getColorMode(),
mbgl::util::hash(getColorMode().hash(), impl->vertexDescHash));
}
if (impl->pipelineState) {
encoder->setRenderPipelineState(impl->pipelineState.get());
@@ -563,6 +568,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
if (impl->attributeBindings != attributeBindings_) {
impl->attributeBindings = std::move(attributeBindings_);
// hash
std::size_t hash{0};
// Create a layout descriptor for each attribute
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
@@ -595,10 +603,18 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
vertDesc->attributes()->setObject(attribDesc.get(), index);
vertDesc->layouts()->setObject(layoutDesc.get(), index);
mbgl::util::hash_combine(hash,
mbgl::util::hash(index,
binding->attribute.offset,
binding->attribute.dataType,
binding->vertexStride,
static_cast<bool>(binding->vertexBufferResource)));
index += 1;
}
impl->vertexDesc = std::move(vertDesc);
impl->vertexDescHash = hash;
impl->pipelineState.reset();
}
}

View File

@@ -36,6 +36,7 @@ public:
std::vector<UniqueDrawSegment> segments;
MTLVertexDescriptorPtr vertexDesc;
std::size_t vertexDescHash{0};
/*
std::vector<TextureID> textures;

View File

@@ -83,7 +83,14 @@ ShaderProgram::~ShaderProgram() noexcept = default;
MTLRenderPipelineStatePtr ShaderProgram::getRenderPipelineState(const gfx::Renderable& renderable,
const MTLVertexDescriptorPtr& vertexDescriptor,
const gfx::ColorMode& colorMode) const {
const gfx::ColorMode& colorMode,
const std::optional<std::size_t> reuseHash) const {
if (reuseHash.has_value()) {
// we'd like to reuse a previous value
if (auto it = renderPipelineStateCache.find(reuseHash.value()); it != renderPipelineStateCache.end())
return it->second;
}
auto pool = NS::TransferPtr(NS::AutoreleasePool::alloc()->init());
const auto& renderableResource = renderable.getResource<RenderableResource>();
@@ -165,6 +172,11 @@ MTLRenderPipelineStatePtr ShaderProgram::getRenderPipelineState(const gfx::Rende
assert(false);
}
if (reuseHash.has_value()) {
// store the value for future reuse
renderPipelineStateCache[reuseHash.value()] = rps;
}
return rps;
}