Cache metal pipeline state (#1658)
Co-authored-by: Alex Cristici <alex.cristici@gmail.com>
This commit is contained in:
@@ -68,7 +68,7 @@ public:
|
||||
const gfx::ShaderProgramBasePtr& getShader() const { return shader; }
|
||||
|
||||
/// Set the shader to be used
|
||||
void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); }
|
||||
virtual void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); }
|
||||
|
||||
/// The pass on which we'll be rendered
|
||||
mbgl::RenderPass getRenderPass() const { return renderPass; }
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
const gfx::ColorMode& getColorMode() const;
|
||||
|
||||
/// Set color mode
|
||||
void setColorMode(const gfx::ColorMode&);
|
||||
virtual void setColorMode(const gfx::ColorMode&);
|
||||
|
||||
/// Get the vertex attributes that override default values in the shader program
|
||||
virtual const gfx::VertexAttributeArray& getVertexAttributes() const = 0;
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
|
||||
virtual void wait() {}
|
||||
|
||||
bool operator!=(const Renderable& other) const { return resource.get() != other.resource.get(); }
|
||||
|
||||
protected:
|
||||
Size size;
|
||||
std::unique_ptr<RenderableResource> resource;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <mbgl/gfx/draw_mode.hpp>
|
||||
#include <mbgl/mtl/upload_pass.hpp>
|
||||
#include <mbgl/programs/segment.hpp>
|
||||
#include <mbgl/mtl/mtl_fwd.hpp>
|
||||
#include <mbgl/mtl/render_pass.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -53,6 +55,10 @@ public:
|
||||
|
||||
void upload(gfx::UploadPass&);
|
||||
|
||||
void setColorMode(const gfx::ColorMode&) override;
|
||||
|
||||
void setShader(gfx::ShaderProgramBasePtr) override;
|
||||
|
||||
protected:
|
||||
// For testing only.
|
||||
Drawable(std::unique_ptr<Impl>);
|
||||
@@ -72,6 +78,10 @@ protected:
|
||||
const std::unique_ptr<Impl> impl;
|
||||
|
||||
gfx::AttributeBindingArray attributeBindings;
|
||||
|
||||
mutable MTLRenderPipelineStatePtr pipelineState;
|
||||
|
||||
mutable std::optional<gfx::RenderPassDescriptor> renderPassDescriptor;
|
||||
};
|
||||
|
||||
} // namespace mtl
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace mbgl {
|
||||
namespace bench {
|
||||
|
||||
const std::vector<Location> locations = {
|
||||
{ "boston", -71.07766, 42.36513, 16, 0.0 },
|
||||
{ "paris", 2.3411, 48.8664, 11, 0.0 },
|
||||
{ "paris2", 2.3516, 48.8356, 13, 273.8 },
|
||||
{ "alps", 10.6107, 46.9599, 6, 0.0 },
|
||||
|
||||
@@ -2,20 +2,24 @@
|
||||
|
||||
#include <mbgl/gfx/debug_group.hpp>
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
class Renderable;
|
||||
|
||||
class RenderPassDescriptor {
|
||||
public:
|
||||
Renderable& renderable;
|
||||
std::optional<Color> clearColor;
|
||||
std::optional<float> clearDepth;
|
||||
std::optional<int32_t> clearStencil;
|
||||
|
||||
bool operator!=(const RenderPassDescriptor& other) const {
|
||||
return other.clearColor != clearColor || other.clearDepth != clearDepth || other.clearStencil != clearStencil ||
|
||||
other.renderable != renderable;
|
||||
}
|
||||
};
|
||||
|
||||
class RenderPass {
|
||||
|
||||
@@ -122,6 +122,16 @@ MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) {
|
||||
|
||||
} // namespace
|
||||
|
||||
void Drawable::setColorMode(const gfx::ColorMode& value) {
|
||||
pipelineState.reset();
|
||||
gfx::Drawable::setColorMode(value);
|
||||
}
|
||||
|
||||
void Drawable::setShader(gfx::ShaderProgramBasePtr value) {
|
||||
pipelineState.reset();
|
||||
gfx::Drawable::setShader(value);
|
||||
}
|
||||
|
||||
void Drawable::draw(PaintParameters& parameters) const {
|
||||
if (isCustom) {
|
||||
return;
|
||||
@@ -141,6 +151,14 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
return;
|
||||
}
|
||||
|
||||
if (renderPassDescriptor.has_value() && renderPass.getDescriptor() != renderPassDescriptor.value()) {
|
||||
pipelineState.reset();
|
||||
}
|
||||
renderPassDescriptor.emplace(gfx::RenderPassDescriptor{renderPass.getDescriptor().renderable,
|
||||
renderPass.getDescriptor().clearColor,
|
||||
renderPass.getDescriptor().clearDepth,
|
||||
renderPass.getDescriptor().clearStencil});
|
||||
|
||||
const auto& shaderMTL = static_cast<const ShaderProgram&>(*shader);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
@@ -189,8 +207,11 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
encoder->setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone);
|
||||
encoder->setFrontFacingWinding(mapWindingMode(cullMode.winding));
|
||||
|
||||
if (auto state = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode())) {
|
||||
encoder->setRenderPipelineState(state.get());
|
||||
if (!pipelineState) {
|
||||
pipelineState = shaderMTL.getRenderPipelineState(renderPassDescriptor, impl->vertexDesc, getColorMode());
|
||||
}
|
||||
if (pipelineState) {
|
||||
encoder->setRenderPipelineState(pipelineState.get());
|
||||
} else {
|
||||
assert(!"Failed to create render pipeline state");
|
||||
return;
|
||||
@@ -522,53 +543,58 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
|
||||
|
||||
// Apply drawable values to shader defaults
|
||||
std::vector<std::unique_ptr<gfx::VertexBufferResource>> vertexBuffers;
|
||||
attributeBindings = uploadPass.buildAttributeBindings(impl->vertexCount,
|
||||
impl->vertexType,
|
||||
/*vertexAttributeIndex=*/-1,
|
||||
/*vertexData=*/{},
|
||||
shader->getVertexAttributes(),
|
||||
impl->vertexAttributes,
|
||||
usage,
|
||||
vertexBuffers);
|
||||
auto attributeBindings_ = uploadPass.buildAttributeBindings(impl->vertexCount,
|
||||
impl->vertexType,
|
||||
/*vertexAttributeIndex=*/-1,
|
||||
/*vertexData=*/{},
|
||||
shader->getVertexAttributes(),
|
||||
impl->vertexAttributes,
|
||||
usage,
|
||||
vertexBuffers);
|
||||
impl->attributeBuffers = std::move(vertexBuffers);
|
||||
|
||||
impl->vertexAttributes.visitAttributes(
|
||||
[](const auto&, gfx::VertexAttribute& attrib) { attrib.setDirty(false); });
|
||||
|
||||
// Create a layout descriptor for each attribute
|
||||
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
|
||||
if (attributeBindings != attributeBindings_) {
|
||||
attributeBindings = attributeBindings_;
|
||||
|
||||
NS::UInteger index = 0;
|
||||
for (auto& binding : attributeBindings) {
|
||||
if (!binding) {
|
||||
assert("Missing attribute binding");
|
||||
continue;
|
||||
// Create a layout descriptor for each attribute
|
||||
auto vertDesc = NS::RetainPtr(MTL::VertexDescriptor::vertexDescriptor());
|
||||
|
||||
NS::UInteger index = 0;
|
||||
for (auto& binding : attributeBindings) {
|
||||
if (!binding) {
|
||||
assert("Missing attribute binding");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
|
||||
impl->noBindingBuffer = uploadPass.createVertexBufferResource(
|
||||
nullptr, 64, gfx::BufferUsageType::StaticDraw);
|
||||
}
|
||||
|
||||
auto attribDesc = NS::TransferPtr(MTL::VertexAttributeDescriptor::alloc()->init());
|
||||
attribDesc->setBufferIndex(index);
|
||||
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
|
||||
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
|
||||
assert(binding->vertexStride > 0);
|
||||
|
||||
auto layoutDesc = NS::TransferPtr(MTL::VertexBufferLayoutDescriptor::alloc()->init());
|
||||
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
|
||||
layoutDesc->setStepFunction(binding->vertexBufferResource ? MTL::VertexStepFunctionPerVertex
|
||||
: MTL::VertexStepFunctionConstant);
|
||||
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
|
||||
|
||||
vertDesc->attributes()->setObject(attribDesc.get(), index);
|
||||
vertDesc->layouts()->setObject(layoutDesc.get(), index);
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
|
||||
impl->noBindingBuffer = uploadPass.createVertexBufferResource(
|
||||
nullptr, 64, gfx::BufferUsageType::StaticDraw);
|
||||
}
|
||||
|
||||
auto attribDesc = NS::TransferPtr(MTL::VertexAttributeDescriptor::alloc()->init());
|
||||
attribDesc->setBufferIndex(index);
|
||||
attribDesc->setOffset(static_cast<NS::UInteger>(binding->attribute.offset));
|
||||
attribDesc->setFormat(mtlVertexTypeOf(binding->attribute.dataType));
|
||||
assert(binding->vertexStride > 0);
|
||||
|
||||
auto layoutDesc = NS::TransferPtr(MTL::VertexBufferLayoutDescriptor::alloc()->init());
|
||||
layoutDesc->setStride(static_cast<NS::UInteger>(binding->vertexStride));
|
||||
layoutDesc->setStepFunction(binding->vertexBufferResource ? MTL::VertexStepFunctionPerVertex
|
||||
: MTL::VertexStepFunctionConstant);
|
||||
layoutDesc->setStepRate(binding->vertexBufferResource ? 1 : 0);
|
||||
|
||||
vertDesc->attributes()->setObject(attribDesc.get(), index);
|
||||
vertDesc->layouts()->setObject(layoutDesc.get(), index);
|
||||
|
||||
index += 1;
|
||||
impl->vertexDesc = std::move(vertDesc);
|
||||
pipelineState.reset();
|
||||
}
|
||||
|
||||
impl->vertexDesc = std::move(vertDesc);
|
||||
}
|
||||
|
||||
const bool texturesNeedUpload = std::any_of(
|
||||
|
||||
Reference in New Issue
Block a user