Fix Metal frame glitch on older devices (#2379)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
std::vector<UniqueDrawSegment> segments;
|
||||
|
||||
MTLVertexDescriptorPtr vertexDesc;
|
||||
std::size_t vertexDescHash{0};
|
||||
|
||||
/*
|
||||
std::vector<TextureID> textures;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user