Metal stats (#1781)
This commit is contained in:
@@ -1216,6 +1216,7 @@ if(MBGL_WITH_METAL)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_impl.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_builder.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/index_buffer_resource.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/layer_group.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/mtl.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/offscreen_texture.cpp
|
||||
@@ -1227,6 +1228,7 @@ if(MBGL_WITH_METAL)
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/uniform_buffer.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/upload_pass.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_attribute.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_buffer_resource.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program.cpp
|
||||
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background.cpp
|
||||
${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/background_pattern.cpp
|
||||
|
||||
@@ -895,7 +895,7 @@ MLN_OPENGL_HEADERS = [
|
||||
"include/mbgl/gl/renderable_resource.hpp",
|
||||
"include/mbgl/gl/renderer_backend.hpp",
|
||||
"include/mbgl/layermanager/location_indicator_layer_factory.hpp",
|
||||
"include/mbgl/platform/gl_functions.hpp"
|
||||
"include/mbgl/platform/gl_functions.hpp",
|
||||
]
|
||||
|
||||
MLN_DRAWABLES_SOURCE = [
|
||||
@@ -1009,7 +1009,7 @@ MLN_DRAWABLES_GL_HEADERS = [
|
||||
"include/mbgl/gl/vertex_attribute_gl.hpp",
|
||||
"include/mbgl/gl/texture2d.hpp",
|
||||
"include/mbgl/shaders/gl/shader_program_gl.hpp",
|
||||
"include/mbgl/shaders/gl/shader_group_gl.hpp"
|
||||
"include/mbgl/shaders/gl/shader_group_gl.hpp",
|
||||
]
|
||||
|
||||
MLN_DRAWABLES_MTL_SOURCE = [
|
||||
@@ -1019,6 +1019,7 @@ MLN_DRAWABLES_MTL_SOURCE = [
|
||||
"src/mbgl/mtl/drawable.cpp",
|
||||
"src/mbgl/mtl/drawable_impl.hpp",
|
||||
"src/mbgl/mtl/drawable_builder.cpp",
|
||||
"src/mbgl/mtl/index_buffer_resource.cpp",
|
||||
"src/mbgl/mtl/layer_group.cpp",
|
||||
"src/mbgl/mtl/mtl.cpp",
|
||||
"src/mbgl/mtl/offscreen_texture.cpp",
|
||||
@@ -1030,6 +1031,7 @@ MLN_DRAWABLES_MTL_SOURCE = [
|
||||
"src/mbgl/mtl/uniform_buffer.cpp",
|
||||
"src/mbgl/mtl/upload_pass.cpp",
|
||||
"src/mbgl/mtl/vertex_attribute.cpp",
|
||||
"src/mbgl/mtl/vertex_buffer_resource.cpp",
|
||||
"src/mbgl/shaders/mtl/shader_program.cpp",
|
||||
"src/mbgl/shaders/mtl/background.cpp",
|
||||
"src/mbgl/shaders/mtl/background_pattern.cpp",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
@@ -7,38 +10,44 @@ struct RenderingStats {
|
||||
RenderingStats() = default;
|
||||
bool isZero() const;
|
||||
|
||||
int numDrawCalls;
|
||||
int numActiveTextures;
|
||||
int numCreatedTextures;
|
||||
int numBuffers;
|
||||
int numFrameBuffers;
|
||||
int numFrames = 0;
|
||||
int numDrawCalls = 0;
|
||||
int totalDrawCalls = 0;
|
||||
|
||||
int memTextures;
|
||||
int memIndexBuffers;
|
||||
int memVertexBuffers;
|
||||
int numCreatedTextures = 0;
|
||||
int numActiveTextures = 0;
|
||||
int numTextureBindings = 0;
|
||||
int numTextureUpdates = 0;
|
||||
std::size_t textureUpdateBytes = 0;
|
||||
|
||||
int numBuffers = 0;
|
||||
int numFrameBuffers = 0;
|
||||
|
||||
int numIndexBuffers = 0;
|
||||
std::size_t indexUpdateBytes = 0;
|
||||
|
||||
int numVertexBuffers = 0;
|
||||
std::size_t vertexUpdateBytes = 0;
|
||||
|
||||
int numUniformBuffers = 0;
|
||||
int numUniformUpdates = 0;
|
||||
std::size_t uniformUpdateBytes = 0;
|
||||
|
||||
int memTextures = 0;
|
||||
int memBuffers = 0;
|
||||
int memIndexBuffers = 0;
|
||||
int memVertexBuffers = 0;
|
||||
int memUniformBuffers = 0;
|
||||
|
||||
int stencilClears = 0;
|
||||
int stencilUpdates = 0;
|
||||
|
||||
RenderingStats& operator+=(const RenderingStats& right);
|
||||
RenderingStats& operator+=(const RenderingStats&);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
std::string toString(std::string_view separator) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline RenderingStats& RenderingStats::operator+=(const RenderingStats& r) {
|
||||
numDrawCalls += r.numDrawCalls;
|
||||
numActiveTextures += r.numActiveTextures;
|
||||
numCreatedTextures += r.numCreatedTextures;
|
||||
numBuffers += r.numBuffers;
|
||||
numFrameBuffers += r.numFrameBuffers;
|
||||
|
||||
memTextures += r.memTextures;
|
||||
memIndexBuffers += r.memIndexBuffers;
|
||||
memVertexBuffers += r.memVertexBuffers;
|
||||
|
||||
stencilClears += r.stencilClears;
|
||||
stencilUpdates += r.stencilUpdates;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -22,7 +22,8 @@ class UniformBuffer {
|
||||
protected:
|
||||
UniformBuffer(std::size_t size_)
|
||||
: size(size_) {}
|
||||
UniformBuffer(const UniformBuffer&) = default;
|
||||
UniformBuffer(const UniformBuffer& other)
|
||||
: size(other.size) {}
|
||||
UniformBuffer(UniformBuffer&& other)
|
||||
: size(other.size) {}
|
||||
|
||||
@@ -32,8 +33,9 @@ public:
|
||||
|
||||
std::size_t getSize() const { return size; }
|
||||
|
||||
UniformBuffer& operator=(const UniformBuffer&) = delete;
|
||||
|
||||
protected:
|
||||
UniformBuffer& operator=(const UniformBuffer&) = default;
|
||||
UniformBuffer& operator=(UniformBuffer&& other) {
|
||||
size = other.size;
|
||||
return *this;
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace mbgl {
|
||||
namespace gl {
|
||||
|
||||
class UniformBufferGL final : public gfx::UniformBuffer {
|
||||
UniformBufferGL(const UniformBufferGL&);
|
||||
|
||||
public:
|
||||
UniformBufferGL(const void* data, std::size_t size_);
|
||||
UniformBufferGL(const UniformBufferGL& other)
|
||||
: UniformBuffer(other) {}
|
||||
UniformBufferGL(UniformBufferGL&& other)
|
||||
: UniformBuffer(std::move(other)) {}
|
||||
~UniformBufferGL() override;
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
BufferID getID() const { return id; }
|
||||
void update(const void* data, std::size_t size_) override;
|
||||
|
||||
UniformBufferGL clone() const { return {*this}; }
|
||||
|
||||
protected:
|
||||
BufferID id = 0;
|
||||
uint32_t hash;
|
||||
@@ -42,7 +44,7 @@ public:
|
||||
|
||||
private:
|
||||
std::unique_ptr<gfx::UniformBuffer> copy(const gfx::UniformBuffer& uniformBuffers) override {
|
||||
return std::make_unique<UniformBufferGL>(static_cast<const UniformBufferGL&>(uniformBuffers));
|
||||
return std::make_unique<UniformBufferGL>(static_cast<const UniformBufferGL&>(uniformBuffers).clone());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,32 +10,40 @@
|
||||
namespace mbgl {
|
||||
namespace mtl {
|
||||
|
||||
class Context;
|
||||
|
||||
class BufferResource {
|
||||
public:
|
||||
BufferResource() = default;
|
||||
BufferResource() = delete;
|
||||
/** @brief Create a new Metal buffer
|
||||
@param device The Metal device on which to create the buffer.
|
||||
@param raw Data to use for the contents of the new buffer. May be null.
|
||||
@param size The minimum size of the new buffer. Must be non-zero.
|
||||
@param usage A `MTL::ResourceOptions` value. Currently, only `ResourceStorageModeShared` is supported.
|
||||
*/
|
||||
BufferResource(MTLDevicePtr device, const void* raw, std::size_t size, MTL::ResourceOptions usage);
|
||||
BufferResource(const BufferResource&);
|
||||
BufferResource(Context& context_, const void* raw, std::size_t size, MTL::ResourceOptions usage);
|
||||
BufferResource(BufferResource&&);
|
||||
virtual ~BufferResource();
|
||||
|
||||
BufferResource& operator=(BufferResource&&);
|
||||
|
||||
BufferResource clone() const;
|
||||
|
||||
void update(const void* data, std::size_t size, std::size_t offset);
|
||||
|
||||
std::size_t getSizeInBytes() const { return buffer ? buffer->length() : 0; }
|
||||
void* contents() const { return buffer ? buffer->contents() : nullptr; }
|
||||
|
||||
Context& getContext() const { return context; }
|
||||
const MTLBufferPtr& getMetalBuffer() const { return buffer; }
|
||||
|
||||
operator bool() const { return buffer.operator bool(); }
|
||||
bool operator!() const { return !buffer.operator bool(); }
|
||||
|
||||
protected:
|
||||
MTLDevicePtr device;
|
||||
Context& context;
|
||||
MTLBufferPtr buffer;
|
||||
NS::UInteger size;
|
||||
NS::UInteger usage;
|
||||
};
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ public:
|
||||
|
||||
std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;
|
||||
|
||||
gfx::RenderingStats& renderingStats() { return stats; }
|
||||
const gfx::RenderingStats& renderingStats() const override { return stats; }
|
||||
|
||||
BufferResource createBuffer(const void* data, std::size_t size, gfx::BufferUsageType) const;
|
||||
|
||||
UniqueShaderProgram createProgram(std::string name,
|
||||
@@ -59,6 +56,8 @@ public:
|
||||
MTLTexturePtr createMetalTexture(MTLTextureDescriptorPtr textureDescriptor) const;
|
||||
MTLSamplerStatePtr createMetalSamplerState(MTLSamplerDescriptorPtr samplerDescriptor) const;
|
||||
|
||||
void clear();
|
||||
|
||||
// Actually remove the objects we marked as abandoned with the above methods.
|
||||
void performCleanup() override;
|
||||
|
||||
@@ -119,6 +118,9 @@ public:
|
||||
/// Get a reusable buffer containing the standard fixed tile indexes
|
||||
const BufferResource& getTileIndexBuffer();
|
||||
|
||||
/// Get a buffer to be bound to unused vertex buffers
|
||||
const gfx::UniqueVertexBufferResource& getEmptyVertexBuffer();
|
||||
|
||||
bool renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
RenderStaticData& staticData,
|
||||
const std::vector<shaders::ClipUBO>& tileUBOs);
|
||||
@@ -130,14 +132,14 @@ private:
|
||||
std::optional<BufferResource> tileVertexBuffer;
|
||||
std::optional<BufferResource> tileIndexBuffer;
|
||||
|
||||
gfx::UniqueVertexBufferResource emptyVertexBuffer;
|
||||
|
||||
gfx::ShaderProgramBasePtr clipMaskShader;
|
||||
MTLDepthStencilStatePtr clipMaskDepthStencilState;
|
||||
MTLRenderPipelineStatePtr clipMaskPipelineState;
|
||||
BufferResource clipMaskUniformsBuffer;
|
||||
std::optional<BufferResource> clipMaskUniformsBuffer;
|
||||
bool clipMaskUniformsBufferUsed = false;
|
||||
const gfx::Renderable* stencilStateRenderable = nullptr;
|
||||
|
||||
gfx::RenderingStats stats;
|
||||
};
|
||||
|
||||
} // namespace mtl
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/index_buffer.hpp>
|
||||
#include <mbgl/mtl/buffer_resource.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -8,10 +9,10 @@ namespace mtl {
|
||||
class IndexBufferResource : public gfx::IndexBufferResource {
|
||||
public:
|
||||
IndexBufferResource() = default;
|
||||
IndexBufferResource(BufferResource&& ptr)
|
||||
: buffer(std::move(ptr)) {}
|
||||
IndexBufferResource(BufferResource&&);
|
||||
IndexBufferResource(IndexBufferResource&& other)
|
||||
: buffer(std::move(other.buffer)) {}
|
||||
~IndexBufferResource() override;
|
||||
|
||||
std::size_t getSizeInBytes() const { return buffer.getSizeInBytes(); }
|
||||
void* contents() const { return buffer.contents(); }
|
||||
|
||||
@@ -9,12 +9,14 @@ namespace mtl {
|
||||
class UniformBuffer final : public gfx::UniformBuffer {
|
||||
public:
|
||||
UniformBuffer(BufferResource&&);
|
||||
UniformBuffer(const UniformBuffer&) = default;
|
||||
UniformBuffer(const UniformBuffer&) = delete;
|
||||
UniformBuffer(UniformBuffer&&);
|
||||
~UniformBuffer() override = default;
|
||||
~UniformBuffer() override;
|
||||
|
||||
const BufferResource& getBufferResource() const { return buffer; }
|
||||
|
||||
UniformBuffer clone() const { return {buffer.clone()}; }
|
||||
|
||||
void update(const void* data, std::size_t size_) override;
|
||||
|
||||
protected:
|
||||
@@ -40,7 +42,7 @@ public:
|
||||
|
||||
private:
|
||||
gfx::UniqueUniformBuffer copy(const gfx::UniformBuffer& buffer) override {
|
||||
return std::make_unique<UniformBuffer>(static_cast<const UniformBuffer&>(buffer));
|
||||
return std::make_unique<UniformBuffer>(static_cast<const UniformBuffer&>(buffer).clone());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace mtl {
|
||||
class VertexBufferResource : public gfx::VertexBufferResource {
|
||||
public:
|
||||
VertexBufferResource() = default;
|
||||
VertexBufferResource(BufferResource&& ptr)
|
||||
: buffer(std::move(ptr)) {}
|
||||
VertexBufferResource(BufferResource&&);
|
||||
VertexBufferResource(VertexBufferResource&& other)
|
||||
: buffer(std::move(other.buffer)) {}
|
||||
~VertexBufferResource() override;
|
||||
|
||||
std::size_t getSizeInBytes() const { return buffer.getSizeInBytes(); }
|
||||
void* contents() const { return buffer.contents(); }
|
||||
|
||||
@@ -103,7 +103,8 @@ protected:
|
||||
public:
|
||||
virtual std::unique_ptr<CommandEncoder> createCommandEncoder() = 0;
|
||||
|
||||
virtual const RenderingStats& renderingStats() const = 0;
|
||||
gfx::RenderingStats& renderingStats() { return stats; }
|
||||
const gfx::RenderingStats& renderingStats() const { return stats; }
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
public:
|
||||
@@ -156,6 +157,9 @@ public:
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
gfx::RenderingStats stats;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -1,12 +1,74 @@
|
||||
#include <mbgl/gfx/rendering_stats.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <sstream>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
bool RenderingStats::isZero() const {
|
||||
return numActiveTextures == 0 && numCreatedTextures == 0 && numBuffers == 0 && numFrameBuffers == 0 &&
|
||||
memTextures == 0 && memIndexBuffers == 0 && memVertexBuffers == 0;
|
||||
const auto expectedZeros = {numActiveTextures,
|
||||
numTextureBindings,
|
||||
numBuffers,
|
||||
numVertexBuffers,
|
||||
numIndexBuffers,
|
||||
numUniformBuffers,
|
||||
numFrameBuffers,
|
||||
memTextures,
|
||||
memBuffers,
|
||||
memIndexBuffers,
|
||||
memVertexBuffers,
|
||||
memUniformBuffers};
|
||||
return std::all_of(expectedZeros.begin(), expectedZeros.end(), [](auto x) { return x == 0; });
|
||||
}
|
||||
|
||||
RenderingStats& RenderingStats::operator+=(const RenderingStats& r) {
|
||||
numFrames += r.numFrames;
|
||||
numDrawCalls += r.numDrawCalls;
|
||||
totalDrawCalls += r.totalDrawCalls;
|
||||
numCreatedTextures += r.numCreatedTextures;
|
||||
numActiveTextures += r.numActiveTextures;
|
||||
numTextureBindings += r.numTextureBindings;
|
||||
numTextureUpdates += r.numTextureUpdates;
|
||||
textureUpdateBytes += r.textureUpdateBytes;
|
||||
numBuffers += r.numBuffers;
|
||||
numFrameBuffers += r.numFrameBuffers;
|
||||
numIndexBuffers += r.numIndexBuffers;
|
||||
indexUpdateBytes += r.indexUpdateBytes;
|
||||
numVertexBuffers += r.numVertexBuffers;
|
||||
vertexUpdateBytes += r.vertexUpdateBytes;
|
||||
numUniformBuffers += r.numUniformBuffers;
|
||||
numUniformUpdates += r.numUniformUpdates;
|
||||
uniformUpdateBytes += r.uniformUpdateBytes;
|
||||
memTextures += r.memTextures;
|
||||
memBuffers += r.memBuffers;
|
||||
memIndexBuffers += r.memIndexBuffers;
|
||||
memVertexBuffers += r.memVertexBuffers;
|
||||
memUniformBuffers += r.memUniformBuffers;
|
||||
stencilClears += r.stencilClears;
|
||||
stencilUpdates += r.stencilUpdates;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
std::string RenderingStats::toString(std::string_view sep) const {
|
||||
std::stringstream ss;
|
||||
ss << "numFrames = " << numFrames << sep << "numDrawCalls = " << numDrawCalls << sep
|
||||
<< "totalDrawCalls = " << totalDrawCalls << sep << "numCreatedTextures = " << numCreatedTextures << sep
|
||||
<< "numActiveTextures = " << numActiveTextures << sep << "numTextureBindings = " << numTextureBindings << sep
|
||||
<< "numTextureUpdates = " << numTextureUpdates << sep << "textureUpdateBytes = " << textureUpdateBytes << sep
|
||||
<< "numBuffers = " << numBuffers << sep << "numFrameBuffers = " << numFrameBuffers << sep
|
||||
<< "numIndexBuffers = " << numIndexBuffers << sep << "indexUpdateBytes = " << indexUpdateBytes << sep
|
||||
<< "numVertexBuffers = " << numVertexBuffers << sep << "vertexUpdateBytes = " << vertexUpdateBytes << sep
|
||||
<< "numUniformBuffers = " << numUniformBuffers << sep << "numUniformUpdates = " << numUniformUpdates << sep
|
||||
<< "uniformUpdateBytes = " << uniformUpdateBytes << sep << "memTextures = " << memTextures << sep
|
||||
<< "memBuffers = " << memBuffers << sep << "memIndexBuffers = " << memIndexBuffers << sep
|
||||
<< "memVertexBuffers = " << memVertexBuffers << sep << "memUniformBuffers = " << memUniformBuffers << sep
|
||||
<< "stencilClears = " << stencilClears << sep << "stencilUpdates = " << stencilUpdates << sep;
|
||||
return ss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -63,14 +63,17 @@ static_assert(underlying_type(UniformDataType::FloatMat4) == GL_FLOAT_MAT4, "Ope
|
||||
static_assert(underlying_type(UniformDataType::Sampler2D) == GL_SAMPLER_2D, "OpenGL type mismatch");
|
||||
static_assert(underlying_type(UniformDataType::SamplerCube) == GL_SAMPLER_CUBE, "OpenGL type mismatch");
|
||||
|
||||
namespace {
|
||||
GLint getMaxVertexAttribs() {
|
||||
GLint value = 0;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
|
||||
return value;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Context::Context(RendererBackend& backend_)
|
||||
: gfx::Context([] {
|
||||
GLint value;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
|
||||
return value;
|
||||
}()),
|
||||
backend(backend_),
|
||||
stats() {}
|
||||
: gfx::Context(/*maximumVertexBindingCount=*/getMaxVertexAttribs()),
|
||||
backend(backend_) {}
|
||||
|
||||
Context::~Context() noexcept {
|
||||
if (cleanupOnDestruction) {
|
||||
@@ -616,14 +619,6 @@ std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
|
||||
return std::make_unique<gl::CommandEncoder>(*this);
|
||||
}
|
||||
|
||||
gfx::RenderingStats& Context::renderingStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
const gfx::RenderingStats& Context::renderingStats() const {
|
||||
return stats;
|
||||
}
|
||||
|
||||
void Context::finish() {
|
||||
MBGL_CHECK_ERROR(glFinish());
|
||||
}
|
||||
|
||||
@@ -44,9 +44,6 @@ public:
|
||||
|
||||
std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;
|
||||
|
||||
gfx::RenderingStats& renderingStats();
|
||||
const gfx::RenderingStats& renderingStats() const override;
|
||||
|
||||
void initializeExtensions(const std::function<gl::ProcAddress(const char*)>&);
|
||||
|
||||
void enableDebugging();
|
||||
@@ -131,7 +128,6 @@ private:
|
||||
RendererBackend& backend;
|
||||
bool cleanupOnDestruction = true;
|
||||
|
||||
gfx::RenderingStats stats;
|
||||
std::unique_ptr<extension::Debugging> debugging;
|
||||
|
||||
public:
|
||||
|
||||
@@ -20,6 +20,16 @@ UniformBufferGL::UniformBufferGL(const void* data_, std::size_t size_)
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0));
|
||||
}
|
||||
|
||||
UniformBufferGL::UniformBufferGL(const UniformBufferGL& other)
|
||||
: UniformBuffer(other),
|
||||
hash(other.hash) {
|
||||
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
|
||||
MBGL_CHECK_ERROR(glCopyBufferSubData(other.id, id, 0, 0, size));
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_COPY_READ_BUFFER, other.id));
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_COPY_WRITE_BUFFER, id));
|
||||
MBGL_CHECK_ERROR(glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, size));
|
||||
}
|
||||
|
||||
UniformBufferGL::~UniformBufferGL() {
|
||||
if (id) {
|
||||
MBGL_CHECK_ERROR(glDeleteBuffers(1, &id));
|
||||
|
||||
@@ -1,37 +1,52 @@
|
||||
#include <mbgl/mtl/buffer_resource.hpp>
|
||||
|
||||
#include <mbgl/mtl/context.hpp>
|
||||
#include <mbgl/mtl/renderer_backend.hpp>
|
||||
|
||||
#include <Metal/MTLDevice.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace mbgl {
|
||||
namespace mtl {
|
||||
|
||||
BufferResource::BufferResource(MTLDevicePtr device_, const void* data, std::size_t size, MTL::ResourceOptions usage_)
|
||||
: device(std::move(device_)),
|
||||
BufferResource::BufferResource(Context& context_, const void* data, std::size_t size_, MTL::ResourceOptions usage_)
|
||||
: context(context_),
|
||||
size(static_cast<NS::UInteger>(size_)),
|
||||
usage(usage_) {
|
||||
if (data && size) {
|
||||
buffer = NS::TransferPtr(device->newBuffer(data, static_cast<NS::UInteger>(size), usage));
|
||||
} else {
|
||||
buffer = NS::TransferPtr(device->newBuffer(static_cast<NS::UInteger>(size), usage));
|
||||
}
|
||||
}
|
||||
|
||||
BufferResource::BufferResource(const BufferResource& other)
|
||||
: device(other.device),
|
||||
usage(other.usage) {
|
||||
if (other.buffer) {
|
||||
buffer = NS::TransferPtr(device->newBuffer(other.buffer->contents(), other.buffer->length(), other.usage));
|
||||
auto& device = context.getBackend().getDevice();
|
||||
buffer = NS::TransferPtr((data && size) ? device->newBuffer(data, size, usage) : device->newBuffer(size, usage));
|
||||
if (buffer) {
|
||||
context.renderingStats().numBuffers++;
|
||||
context.renderingStats().memBuffers += size;
|
||||
}
|
||||
}
|
||||
|
||||
BufferResource::BufferResource(BufferResource&& other)
|
||||
: device(std::move(other.device)),
|
||||
: context(other.context),
|
||||
buffer(std::move(other.buffer)),
|
||||
size(other.size),
|
||||
usage(other.usage) {}
|
||||
|
||||
BufferResource::~BufferResource() {
|
||||
if (buffer) {
|
||||
context.renderingStats().numBuffers--;
|
||||
context.renderingStats().memBuffers -= size;
|
||||
}
|
||||
}
|
||||
|
||||
BufferResource BufferResource::clone() const {
|
||||
return {context, buffer->contents(), size, usage};
|
||||
}
|
||||
|
||||
BufferResource& BufferResource::operator=(BufferResource&& other) {
|
||||
device = std::move(other.device);
|
||||
assert(&context == &other.context);
|
||||
if (buffer) {
|
||||
context.renderingStats().numBuffers--;
|
||||
context.renderingStats().memBuffers -= size;
|
||||
}
|
||||
buffer = std::move(other.buffer);
|
||||
size = other.size;
|
||||
usage = other.usage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <mbgl/mtl/render_pass.hpp>
|
||||
#include <mbgl/mtl/uniform_buffer.hpp>
|
||||
#include <mbgl/mtl/upload_pass.hpp>
|
||||
#include <mbgl/mtl/vertex_buffer_resource.hpp>
|
||||
#include <mbgl/programs/program_parameters.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
@@ -37,12 +38,24 @@ constexpr uint32_t maximumVertexBindingCount = 31;
|
||||
|
||||
Context::Context(RendererBackend& backend_)
|
||||
: gfx::Context(mtl::maximumVertexBindingCount),
|
||||
backend(backend_),
|
||||
stats() {}
|
||||
backend(backend_) {}
|
||||
|
||||
Context::~Context() noexcept {
|
||||
if (cleanupOnDestruction) {
|
||||
performCleanup();
|
||||
|
||||
emptyVertexBuffer.reset();
|
||||
tileVertexBuffer.reset();
|
||||
tileIndexBuffer.reset();
|
||||
clipMaskShader.reset();
|
||||
clipMaskDepthStencilState.reset();
|
||||
clipMaskPipelineState.reset();
|
||||
clipMaskUniformsBuffer.reset();
|
||||
stencilStateRenderable = nullptr;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
Log::Debug(Event::General, "Rendering Stats:\n" + stats.toString("\n"));
|
||||
#endif
|
||||
assert(stats.isZero());
|
||||
}
|
||||
}
|
||||
@@ -52,7 +65,7 @@ std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
|
||||
}
|
||||
|
||||
BufferResource Context::createBuffer(const void* data, std::size_t size, gfx::BufferUsageType) const {
|
||||
return {backend.getDevice(), data, size, MTL::ResourceStorageModeShared};
|
||||
return {const_cast<Context&>(*this), data, size, MTL::ResourceStorageModeShared};
|
||||
}
|
||||
|
||||
UniqueShaderProgram Context::createProgram(std::string name,
|
||||
@@ -144,6 +157,11 @@ MTLSamplerStatePtr Context::createMetalSamplerState(MTLSamplerDescriptorPtr samp
|
||||
return NS::TransferPtr(backend.getDevice()->newSamplerState(samplerDescriptor.get()));
|
||||
}
|
||||
|
||||
void Context::clear() {
|
||||
stats.numDrawCalls = 0;
|
||||
stats.numFrames++;
|
||||
}
|
||||
|
||||
void Context::performCleanup() {
|
||||
clipMaskUniformsBufferUsed = false;
|
||||
}
|
||||
@@ -207,6 +225,20 @@ const BufferResource& Context::getTileIndexBuffer() {
|
||||
return *tileIndexBuffer;
|
||||
}
|
||||
|
||||
const gfx::UniqueVertexBufferResource& Context::getEmptyVertexBuffer() {
|
||||
if (!emptyVertexBuffer) {
|
||||
// This buffer is bound to vertex attribtue indexes when the uniforms are used instead and
|
||||
// shaders are expected not to access the attribute values, but Metal requires a binding.
|
||||
// This buffer could also hold a single default value applied for all vertices, in which case
|
||||
// it could not be shared (See `MTL::VertexStepFunctionConstant` in the vertex attribute
|
||||
// descriptors, but that isn't currently being used.
|
||||
constexpr std::size_t size = 32;
|
||||
constexpr auto usage = gfx::BufferUsageType::StaticDraw;
|
||||
emptyVertexBuffer = std::make_unique<VertexBufferResource>(createBuffer(nullptr, size, usage));
|
||||
}
|
||||
return emptyVertexBuffer;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const auto clipMaskStencilMode = gfx::StencilMode{
|
||||
/*.test=*/gfx::StencilMode::Always(),
|
||||
@@ -316,16 +348,16 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
constexpr auto uboSize = sizeof(shaders::ClipUBO);
|
||||
const auto bufferSize = tileUBOs.size() * uboSize;
|
||||
|
||||
BufferResource tempBuffer;
|
||||
std::optional<BufferResource> tempBuffer;
|
||||
auto& uboBuffer = clipMaskUniformsBufferUsed ? tempBuffer : clipMaskUniformsBuffer;
|
||||
clipMaskUniformsBufferUsed = true;
|
||||
if (!uboBuffer || uboBuffer.getSizeInBytes() < bufferSize) {
|
||||
if (!uboBuffer || !*uboBuffer || uboBuffer->getSizeInBytes() < bufferSize) {
|
||||
uboBuffer = createBuffer(tileUBOs.data(), bufferSize, gfx::BufferUsageType::StaticDraw);
|
||||
if (!uboBuffer) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
uboBuffer.update(tileUBOs.data(), bufferSize, /*offset=*/0);
|
||||
uboBuffer->update(tileUBOs.data(), bufferSize, /*offset=*/0);
|
||||
}
|
||||
|
||||
encoder->setCullMode(MTL::CullModeNone);
|
||||
@@ -350,7 +382,7 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
for (std::size_t ii = 0; ii < tileUBOs.size(); ++ii) {
|
||||
encoder->setStencilReferenceValue(tileUBOs[ii].stencil_ref);
|
||||
encoder->setVertexBuffer(
|
||||
uboBuffer.getMetalBuffer().get(), /*offset=*/ii * uboSize, ShaderClass::uniforms[0].index);
|
||||
uboBuffer->getMetalBuffer().get(), /*offset=*/ii * uboSize, ShaderClass::uniforms[0].index);
|
||||
encoder->drawIndexedPrimitives(MTL::PrimitiveType::PrimitiveTypeTriangle,
|
||||
indexCount,
|
||||
MTL::IndexType::IndexTypeUInt16,
|
||||
@@ -362,6 +394,8 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
}
|
||||
#endif
|
||||
|
||||
stats.numDrawCalls++;
|
||||
stats.totalDrawCalls++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& context = static_cast<Context&>(parameters.context);
|
||||
auto& context = static_cast<Context&>(parameters.context);
|
||||
const auto& renderPass = static_cast<RenderPass&>(*parameters.renderPass);
|
||||
const auto& encoder = renderPass.getMetalEncoder();
|
||||
if (!encoder) {
|
||||
@@ -289,8 +289,8 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
if (binding) {
|
||||
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
|
||||
assert((maxIndex + mlSegment.vertexOffset) * binding->vertexStride <= buffer->length());
|
||||
} else if (const auto buffer = getMetalBuffer(impl->noBindingBuffer.get())) {
|
||||
assert(binding->vertexStride <= buffer->length());
|
||||
} else if (impl->noBindingBuffer) {
|
||||
assert(binding->vertexStride <= impl->noBindingBuffer->length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,6 +304,7 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
instanceCount,
|
||||
baseVertex,
|
||||
baseInstance);
|
||||
context.renderingStats().numDrawCalls++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,8 +372,8 @@ void Drawable::bindAttributes(const RenderPass& renderPass) const {
|
||||
if (const auto buffer = getMetalBuffer(binding ? binding->vertexBufferResource : nullptr)) {
|
||||
assert(binding->vertexStride * impl->vertexCount <= getBufferSize(binding->vertexBufferResource));
|
||||
encoder->setVertexBuffer(buffer, /*offset=*/0, attributeIndex);
|
||||
} else if (const auto buffer = getMetalBuffer(impl->noBindingBuffer.get())) {
|
||||
encoder->setVertexBuffer(buffer, /*offset=*/0, attributeIndex);
|
||||
} else if (impl->noBindingBuffer) {
|
||||
encoder->setVertexBuffer(impl->noBindingBuffer, /*offset=*/0, attributeIndex);
|
||||
}
|
||||
attributeIndex += 1;
|
||||
}
|
||||
@@ -593,8 +594,9 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
|
||||
}
|
||||
|
||||
if (!binding->vertexBufferResource && !impl->noBindingBuffer) {
|
||||
impl->noBindingBuffer = uploadPass.createVertexBufferResource(
|
||||
nullptr, 64, gfx::BufferUsageType::StaticDraw);
|
||||
if (const auto& buf = context.getEmptyVertexBuffer()) {
|
||||
impl->noBindingBuffer = getMetalBuffer(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
auto attribDesc = NS::TransferPtr(MTL::VertexAttributeDescriptor::alloc()->init());
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
// GLfloat pointSize = 0.0f;
|
||||
StringIdentity idVertexAttrName = stringIndexer().get("a_pos");
|
||||
|
||||
gfx::UniqueVertexBufferResource noBindingBuffer;
|
||||
MTL::Buffer* noBindingBuffer = nullptr;
|
||||
|
||||
gfx::AttributeBindingArray attributeBindings;
|
||||
|
||||
|
||||
24
src/mbgl/mtl/index_buffer_resource.cpp
Normal file
24
src/mbgl/mtl/index_buffer_resource.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <mbgl/mtl/index_buffer_resource.hpp>
|
||||
|
||||
#include <mbgl/mtl/context.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace mtl {
|
||||
|
||||
IndexBufferResource::IndexBufferResource(BufferResource&& ptr)
|
||||
: buffer(std::move(ptr)) {
|
||||
if (buffer) {
|
||||
buffer.getContext().renderingStats().numIndexBuffers++;
|
||||
buffer.getContext().renderingStats().memIndexBuffers += buffer.getSizeInBytes();
|
||||
}
|
||||
}
|
||||
|
||||
IndexBufferResource::~IndexBufferResource() {
|
||||
if (buffer) {
|
||||
buffer.getContext().renderingStats().numIndexBuffers--;
|
||||
buffer.getContext().renderingStats().memIndexBuffers -= buffer.getSizeInBytes();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mtl
|
||||
} // namespace mbgl
|
||||
@@ -44,9 +44,10 @@ public:
|
||||
static_cast<Texture2D*>(stencilTexture.get())
|
||||
->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget);
|
||||
}
|
||||
context.renderingStats().numFrameBuffers++;
|
||||
}
|
||||
|
||||
~OffscreenTextureResource() noexcept override = default;
|
||||
~OffscreenTextureResource() noexcept override { context.renderingStats().numFrameBuffers--; }
|
||||
|
||||
void bind() override {
|
||||
assert(context.getBackend().getCommandQueue());
|
||||
|
||||
@@ -47,6 +47,8 @@ RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const
|
||||
|
||||
// Let the encoder pass along any groups pushed to it after this
|
||||
commandEncoder.trackRenderPass(this);
|
||||
|
||||
commandEncoder.context.clear();
|
||||
}
|
||||
|
||||
RenderPass::~RenderPass() {
|
||||
|
||||
@@ -13,7 +13,12 @@ namespace mtl {
|
||||
Texture2D::Texture2D(Context& context_)
|
||||
: context(context_) {}
|
||||
|
||||
Texture2D::~Texture2D() {}
|
||||
Texture2D::~Texture2D() {
|
||||
if (metalTexture) {
|
||||
context.renderingStats().numActiveTextures--;
|
||||
context.renderingStats().memTextures -= getDataSize();
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_) noexcept {
|
||||
samplerState = samplerState_;
|
||||
@@ -138,6 +143,8 @@ void Texture2D::createMetalTexture() noexcept {
|
||||
|
||||
if (metalTexture) {
|
||||
textureDirty = false;
|
||||
context.renderingStats().numCreatedTextures++;
|
||||
context.renderingStats().numActiveTextures++;
|
||||
context.renderingStats().memTextures += getDataSize();
|
||||
}
|
||||
}
|
||||
@@ -190,12 +197,16 @@ void Texture2D::bind(const RenderPass& renderPass, int32_t location) noexcept {
|
||||
|
||||
encoder->setFragmentTexture(metalTexture.get(), location);
|
||||
encoder->setFragmentSamplerState(metalSamplerState.get(), location);
|
||||
|
||||
context.renderingStats().numTextureBindings++;
|
||||
}
|
||||
|
||||
void Texture2D::unbind(const RenderPass& renderPass, int32_t location) noexcept {
|
||||
const auto& encoder = renderPass.getMetalEncoder();
|
||||
encoder->setFragmentTexture(nullptr, location);
|
||||
encoder->setFragmentSamplerState(nullptr, location);
|
||||
|
||||
context.renderingStats().numTextureBindings--;
|
||||
}
|
||||
|
||||
void Texture2D::upload(const void* pixelData, const Size& size_) noexcept {
|
||||
@@ -215,9 +226,11 @@ void Texture2D::uploadSubRegion(const void* pixelData, const Size& size_, uint16
|
||||
assert(metalTexture.get());
|
||||
assert(!textureDirty);
|
||||
|
||||
MTL::Region region = MTL::Region::Make2D(xOffset, yOffset, size_.width, size_.height);
|
||||
NS::UInteger bytesPerRow = size_.width * getPixelStride();
|
||||
const MTL::Region region = MTL::Region::Make2D(xOffset, yOffset, size_.width, size_.height);
|
||||
const NS::UInteger bytesPerRow = size_.width * getPixelStride();
|
||||
metalTexture->replaceRegion(region, 0, pixelData, bytesPerRow);
|
||||
context.renderingStats().numTextureUpdates++;
|
||||
context.renderingStats().textureUpdateBytes += bytesPerRow * size_.height;
|
||||
}
|
||||
|
||||
void Texture2D::upload() noexcept {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/mtl/uniform_buffer.hpp>
|
||||
|
||||
#include <mbgl/mtl/context.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <cassert>
|
||||
@@ -9,11 +10,20 @@ namespace mtl {
|
||||
|
||||
UniformBuffer::UniformBuffer(BufferResource&& buffer_)
|
||||
: gfx::UniformBuffer(buffer_.getSizeInBytes()),
|
||||
buffer(std::move(buffer_)) {}
|
||||
buffer(std::move(buffer_)) {
|
||||
buffer.getContext().renderingStats().numUniformBuffers++;
|
||||
buffer.getContext().renderingStats().memUniformBuffers += size;
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer(UniformBuffer&& other)
|
||||
: gfx::UniformBuffer(std::move(other)),
|
||||
buffer(std::move(other.buffer)) {}
|
||||
|
||||
UniformBuffer::~UniformBuffer() {
|
||||
buffer.getContext().renderingStats().numUniformBuffers--;
|
||||
buffer.getContext().renderingStats().memUniformBuffers -= size;
|
||||
}
|
||||
|
||||
void UniformBuffer::update(const void* data, std::size_t size_) {
|
||||
assert(size == size_);
|
||||
if (size != size_ || size != buffer.getSizeInBytes()) {
|
||||
@@ -23,6 +33,8 @@ void UniformBuffer::update(const void* data, std::size_t size_) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.getContext().renderingStats().numUniformUpdates++;
|
||||
buffer.getContext().renderingStats().uniformUpdateBytes += size_;
|
||||
buffer.update(data, size, /*offset=*/0);
|
||||
}
|
||||
|
||||
|
||||
24
src/mbgl/mtl/vertex_buffer_resource.cpp
Normal file
24
src/mbgl/mtl/vertex_buffer_resource.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <mbgl/mtl/vertex_buffer_resource.hpp>
|
||||
|
||||
#include <mbgl/mtl/context.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace mtl {
|
||||
|
||||
VertexBufferResource::VertexBufferResource(BufferResource&& ptr)
|
||||
: buffer(std::move(ptr)) {
|
||||
if (buffer) {
|
||||
buffer.getContext().renderingStats().numVertexBuffers++;
|
||||
buffer.getContext().renderingStats().memVertexBuffers += buffer.getSizeInBytes();
|
||||
}
|
||||
}
|
||||
|
||||
VertexBufferResource::~VertexBufferResource() {
|
||||
if (buffer) {
|
||||
buffer.getContext().renderingStats().numVertexBuffers--;
|
||||
buffer.getContext().renderingStats().memVertexBuffers -= buffer.getSizeInBytes();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mtl
|
||||
} // namespace mbgl
|
||||
@@ -158,6 +158,7 @@ void PaintParameters::clearStencil() {
|
||||
0,
|
||||
0}};
|
||||
mtlContext.renderTileClippingMasks(*renderPass, staticData, tileUBO);
|
||||
context.renderingStats().stencilClears++;
|
||||
#else // !MLN_RENDER_BACKEND_METAL
|
||||
context.clearStencilBuffer(0b00000000);
|
||||
#endif
|
||||
@@ -231,6 +232,8 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun
|
||||
|
||||
auto& mtlContext = static_cast<mtl::Context&>(context);
|
||||
mtlContext.renderTileClippingMasks(*renderPass, staticData, tileUBOs);
|
||||
|
||||
mtlContext.renderingStats().stencilUpdates++;
|
||||
}
|
||||
|
||||
#else // !MLN_RENDER_BACKEND_METAL
|
||||
|
||||
@@ -136,7 +136,7 @@ RenderOrchestrator::~RenderOrchestrator() {
|
||||
layer.markContextDestroyed();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void RenderOrchestrator::setObserver(RendererObserver* observer_) {
|
||||
observer = observer_ ? observer_ : &nullObserver();
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <atomic>
|
||||
@@ -1607,6 +1608,7 @@ TEST(Map, StencilOverflow) {
|
||||
|
||||
const auto& backend = test.frontend.getBackend();
|
||||
gfx::BackendScope scope{*backend};
|
||||
const auto& context = backend->getContext();
|
||||
|
||||
auto& style = test.map.getStyle();
|
||||
style.loadJSON("{}");
|
||||
@@ -1628,13 +1630,15 @@ TEST(Map, StencilOverflow) {
|
||||
test.frontend.render(test.map);
|
||||
|
||||
// In drawable builds, no drawables are built because no bucket/tiledata is available.
|
||||
#if !MLN_DRAWABLE_RENDERER
|
||||
// TODO: Collect stats on Metal context
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
const auto& context = static_cast<const gl::Context&>(backend->getContext());
|
||||
#if MLN_DRAWABLE_RENDERER
|
||||
ASSERT_LE(0, context.renderingStats().stencilUpdates);
|
||||
#else
|
||||
ASSERT_LT(0, context.renderingStats().stencilClears);
|
||||
#endif // MLN_RENDER_BACKEND_OPENGL
|
||||
#endif // !MLN_DRAWABLE_RENDERER
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
Log::Info(Event::General, context.renderingStats().toString("\n"));
|
||||
#endif // !defined(NDEBUG)
|
||||
|
||||
// TODO: confirm that the stencil masking actually worked
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user