blob: 815650dec57d61073ba86eb439d709a01124b9fe [file] [log] [blame] [edit]
/*
* Copyright 2025 Rive
*/
#pragma once
#include <stdint.h>
#include <algorithm>
#include <cassert>
namespace rive::gpu
{
// Some Mali and PowerVR devices crash when issuing draw commands with a large
// instance count. This class breaks large instance ranges up into chunks that
// can be safely issued on affected GPUs.
class InstanceChunker
{
public:
struct Chunk
{
uint32_t instanceCount;
uint32_t baseInstance;
};
struct Iterator
{
public:
uint32_t currentChunkInstanceCount() const
{
return std::min(endInstance - currentInstance,
maxSupportedInstancesPerDrawCommand);
}
Chunk operator*() const
{
return {currentChunkInstanceCount(), currentInstance};
}
Iterator& operator++()
{
currentInstance += currentChunkInstanceCount();
return *this;
}
bool operator==(const Iterator& other) const
{
assert(endInstance == other.endInstance);
assert(maxSupportedInstancesPerDrawCommand ==
other.maxSupportedInstancesPerDrawCommand);
return currentInstance == other.currentInstance;
}
bool operator!=(const Iterator& other) const
{
return !(*this == other);
}
uint32_t currentInstance;
uint32_t endInstance;
uint32_t maxSupportedInstancesPerDrawCommand;
};
InstanceChunker(uint32_t instanceCount,
uint32_t baseInstance,
uint32_t maxSupportedInstancesPerDrawCommand) :
m_startInstance(baseInstance),
m_endInstance(baseInstance + instanceCount),
m_maxSupportedInstancesPerDrawCommand(
maxSupportedInstancesPerDrawCommand)
{}
Iterator begin() const
{
return {m_startInstance,
m_endInstance,
m_maxSupportedInstancesPerDrawCommand};
}
Iterator end() const
{
return {m_endInstance,
m_endInstance,
m_maxSupportedInstancesPerDrawCommand};
}
private:
uint32_t m_startInstance;
uint32_t m_endInstance;
uint32_t m_maxSupportedInstancesPerDrawCommand;
};
} // namespace rive::gpu