-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
On arm64, sizeof(impeller::Command) == 440. We might benefit from trimming that down since a lot of the the size of Commands are from optional data that is not usually used. Some of them, like Command::scissor and Command::viewport, are only ever used in Playgrounds. The allocation of Commands every frame is the largest allocation of cross-platform objects in Impeller.
A more cache friendly implementation would instead store the data in parallel arrays, similar to the pattern used by ECS.
class Command {
uint64_t ident;
};
class PlaygroundCommand {
std::optional<Viewport> viewport_;
std::optional<IRect> scissor_;
};
class RenderPass {
std::vector<Command> commands_;
std::map<uint64_t, PlaygroundCommand> playground_commands_;
}You could even go further and do the same thing for bindings since most Commands don't have all of the types of bindings.
typedef Command = uint64_t;
class CommandInfo {
PipelineDescriptor pipeline_
}
class PlaygroundCommand {
std::optional<Viewport> viewport_;
std::optional<IRect> scissor_;
};
class RenderPass {
std::map<Command, CommandInfo> commands_;
std::map<Command, PlaygroundCommand> playground_commands_;
std::map<Command, std::map<size_t, ShaderUniformSlot>> vertex_uniforms_;
std::map<Command, std::map<size_t, ShaderUniformSlot>> fragment_uniforms_;
}I'm not certain that would be faster though since the data structure is rebuilt each frame. Using a std::vector<std::pair<Command, T>> will be better than a map since it will always be written to and read from sequentially.