convert this: peculiarities of cross-platform mobile game development at vizor

21

Upload: devgamm-conference

Post on 09-Jan-2017

49 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Convert this: peculiarities of cross-platform mobile game development at Vizor
Page 2: Convert this: peculiarities of cross-platform mobile game development at Vizor
Page 3: Convert this: peculiarities of cross-platform mobile game development at Vizor

Who am I ?

Previously at:«Unity3D глазами программиста графики»DevGamm! Минск, осень 2014.

Роман Чеховский• Архитектор мобильного движка Vizor Games.• 4+ лет опыта работы с графикой, мобильными играми, и движками.• Работал с Unity3D, UE, Cocos2D, libgdx, Urho3D, Ogre3D, Adobe flash, Irrlicht, проприетарными технологиями.

Page 4: Convert this: peculiarities of cross-platform mobile game development at Vizor

• Развивался в процессе разработки проекта.• Кроссплатформенный: Windows, OS X, Linux – JDK.

Android 4.0+, iOS – Native (conversion).

• Первый релиз – “Зомби Инфо” – Апрель 2013.• Множество структурных и функциональных

оптимизаций для мобильных устройств.• Data-driven насколько это возможно.• Смычка с API устройств через бриджи на С+

+.• 95% кода написано на Java.

Cобственный мобильный движок

Page 5: Convert this: peculiarities of cross-platform mobile game development at Vizor

–• Много runtime-проверок.• Отсутствие значимых

типов,• Отсутствие делегатов.• Отсутствие обобщенных

типов во время выполнения.

• Издержки на сборку мусора.

• Нет среды выполнения на iOS.

Java как язык разработки+

• Типобезопасность.• Отсутствие pointer

arithmetic.• Большая стандартная

библиотека.• Средства

выразительности.• Автоматическая сборка

мусора.• Приемлемая

производительность.jMonkeyEngine1 http://jmonkeyengine.org - jMonkeyEngine official site2 https://libgdx.badlogicgames.com - ligGDX official site

Page 6: Convert this: peculiarities of cross-platform mobile game development at Vizor

Коллекции

! Error(x, y): java: generic array creation

1. Не могут содержать примитивы

решение: Не изобретать своих коллекций для ссылочных типов.

решение: IntArrayList, FloatArrayList, IntIntHashMap, etc, не реализующие iterator().

3. Присутствует type erasure и издержки на приведение типов в run-timeрешение: Насколько это возможно, ускорить cast и instanceof на

runtime-уровне.

2. Нельзя инстанциировать generic arraypublic class ArrayList0<T> extends ...{ private T[] objects;

public ArrayList0(int capacity) { objects = new T[capacity]; }

// и так далее}

public class ArrayList1<T> extends ...{ private T[] elements;

public ArrayList1(Class<T> klass, int capacity) { elements = java.lang.reflect.Array.newInstance( klass, capacity ); }

// и так далее}

Page 7: Convert this: peculiarities of cross-platform mobile game development at Vizor

Значимые типы1. Их нет :(

List<Vertex3D> vs = new ArrayList<>();

for (int i = 0; i < ...; ++i) vs.add(new Vertex3D());

context.setStreamSource(vs);

• Колоссальные расходы на инстанциирование

• Footprint объектов

2. …но с этим можно жить :)public class Vertex3DModel extends VertexModel { VertexElem position = VertexElem.POSITION3F; VertexElem rotation = VertexElem.ROTATION4F; VertexElem scale = VertexElem.SCALE3F;}

• Невыровненная память

Vertex3DModel m = new Vertex3DModel();VertexArray vs = new VertexArray(m);

for (int i = 0; i < ...; ++i) vs.add(...);

context.setStreamSource(vs);

• Данные хранятся в виде float[]• Инты кладем используя floatToRawIntBits()

• Байты упаковыаем в int’ы• Значительный overhead для GC

Проблемы: Факты:

• Double-precision пока без необходим

public class Vertex3D extends Vertex{ Vector3 position = new Vector3(); Quaternion rotation = new Quaternion(); Vector3 scale = new Vector3();}

Page 8: Convert this: peculiarities of cross-platform mobile game development at Vizor

Performance Apple iOS

Java - проблемы

JNI-бриджинг AOT-компиляцияКонверсия кода

J2ObjC RoboVM

3 https://github.com/google/j2objc - j2ObjC github repo4 https://github.com/robovm/robovm - RoboVM github repo

j2cpp2 Java DesktopNative plug-ins

Page 9: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер - требования

•Конверсия исходного кода на java в С++ 11.•Совместимость с java 1.8 (lambdas, method references).•Высокая скорость конверсии на многоядерном железе.•Читаемость и отлаживаемость сгенерированного кода.

Page 10: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: AST*.jav

aCompilation

unitConcurrencypackage com.vizor.data;

class A<T> extends ... implements ... { private T[] field;

public A(T[] data) {

field = data; }

/** Выводит на экран i’й аргумент * @param i индекс */ public void foo(int arg) { System.out.println(field[arg]); }}

5

Lexer

Parser+

5 https://github.com/javaparser/javaparser - javaparser library github repo

Class Declaration

MethodsExtension

Class Name

Class NameMethod Declaration

Method Name CommentMethod Body

Assignment Invocation

ValueTarget Target Methodname

Page 11: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: CST

Compilation

unitFP

VisitorSP

VisitorTP

VisitorCST

project

Concurrency

Write Atomicity

@Overrideprotected int foo() { String msg = “Hello” + “world”; int n = 0;

for (int i = 0; i < msg.length(); ++i) { if (msg.charAt(i) == ‘o’) n++; }

return n;}

Method: com.vizor.B.foo():int overrides com.vizor.A.foo():int

Class: java.lang.String

Method: java.lang.String.length():int

Method: java.lang.String.charAt(int):char

Method: java.lang.String.append(S):S

В AST указания типа - строки

Page 12: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: Visitors 1. FP Visitor – Объявления классов, интерфейсов, перечислений.2. SP Visitor – Конструкторы, поля, методы, константы

перечислений.3. TP Visitor – Циклы, блоки кода, операторы, вызовы методов и

приведения типов.

• СST Project – база знаний о связях в AST.• Информация о типах собирается в bulk type cache.• Помечаются ссылки на использованные типы,

переопределенные методы, etc.• Помечаются ссылки на вызываемые методы и использованные

поля.• На следующем этапе код обрабатывается процессорами.

Page 13: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: Процессоры 1.Var Args remover2.Generics remover3.Anonymous class remover4.Inner class remover5.Nested class remover6.For Each remover7.Auto boxing remover8.Enum remover9.Conflicting names renamer10.Method return type fixer11.Method redeclaration

fixer12.String finalizer13.Explicit constructor call

adder

class ShapeBuilder { public Shape build() { ....}

class CircleBuilder extends ShapeBuilder { @Override public Circle build() { ....}

CircleBuilder cb = new CircleBuilder();Circle c = cb.build();

Method redeclaration fixer:

class CircleBuilder extends ShapeBuilder { @Override public Shape build() { ....}

CircleBuilder cb = new CircleBuilder();Circle c = (Circle)cb.build();

Page 14: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: Печать CST

project

HPP Printer

CPP Printer

method prototypesclass declarations

class definitionusing types

fields

method bodies#include files

statics init

A.hpp A.cpp

HPP Printer

CPP Printer

B.hpp B.cpp

HPP Printer

CPP Printer

C.hpp C.cpp

A B C … Z

A (class) B (class) C (class)

Thread Pool

Page 15: Convert this: peculiarities of cross-platform mobile game development at Vizor

Конвертер: Showcasepublic static void unique(List<? extends Item> list){ Iterator<? extends Item> it = list.iterator(); int count = 0;

while (it.hasNext()) { Item object = it.next();

for (int i = 0; i < count; i++) { Item o = list.get(i); if (o.id.equals(object.id)) { it.remove(); count--; break; } }

count++; }}

jvmtypes::jvoid Item::unique(List* list){ Iterator* it = list->iterator(); jvmtypes::jint count = 0;

while (it->hasNext()) { Item* object = (jCAST<Item>(it->next()));

for (jvmtypes::jint i = 0; i < count; i++) { Item* o = (jCAST<Item>(list->get(i))); if (o->id->equals(object->id)) { it->remove(); count--; break; } }

count++; }}

Page 16: Convert this: peculiarities of cross-platform mobile game development at Vizor

List<GameObject> l = new ArrayList<>(42);// ...GameObject o = l.get(0);

List l = new ArrayList(42);// ...GameObject o = (GameObject) l.get(0);

NEW java/util/ArrayListDUPINVOKESPECIAL java/util/ArrayList.<init> ()VASTORE 1ALOAD 1ICONST_0INVOKEINTERFACE java/util/List.get (I)Ljava/lang/ObjectCHECKCAST com/vizor/mobile/engine/GameObjectASTORE 2

List* vectors = ArrayList::$alloc()->$ctor_ArrayList(42);// ...GameObject* v = static_cast<GameObject*>(vectors->get(0));

Type erasure

Такого простого приведения типа очевидно недостаточно. Почему?

Page 17: Convert this: peculiarities of cross-platform mobile game development at Vizor

public class GameObject extends ? implements ?

class GameObject : public Entity, public Serializable, public virtual Object

java.lang.Object

com.vizor.Entityjava.lang.Serializable

com.vizor.GameObject<<implements>> <<extends>>

virtual inheritancevirtual inheritance

Virtual inheritance

static_cast - статическое преобразование c проверкой в compile time.

! Cannot cast ‘Base *' to ‘Derived *' via virtual base ‘Base'

reinterpret_cast - смена представления указателя или ссылки без каких бы то ни было проверок или гарантий ни в compile time, ни в runtime.

Page 18: Convert this: peculiarities of cross-platform mobile game development at Vizor

Type traits

dynamic_cast – динамическое преобразование указателя или ссылки с проверкой в runtime.

Медленный, требует опцию -frtti

Object* o = ->ctor_GameObject(...);

ADDRESSADDRESS + THUNK

GameObject::$alloc()

“INVOKESPECIAL”

Таким образом суть каста сводится к убиранию этого adjusment’a c с проверкой достижимости.

java.lang.Object

java.lang.Serializable

com.vizor.Entity

com.vizor.GameObject

6 http://www.programering.com/a/MDOxgTNwATM.html - memory layout for dynamic objects

Object* o = new GameObject();GameObject* go = dynamic_cast<GameObject>(o);

std::cout << (uintptr_t)o; // 0x10000010std::cout << (uintptr_t)go; // 0x10000000

o != go

Page 19: Convert this: peculiarities of cross-platform mobile game development at Vizor

jCASTGameObject* o = jCAST<GameObject>(o); -> return (GameObject*)o->$cast_to(GameObject::CLASS_ID);

void* $getPointer(){ return this; }

void* $castTo(const int to){ switch (to) { case GameObject::CLASS_ID: return GameObject::$getPointer() case Serializable::CLASS_ID: return Serializable::$getPointer(); case Entity::CLASS_ID: return Entity::$getPointer(); case Object::CLASS_ID: return Object::$getPointer(); default: return 0; }}

7 http://www.drdobbs.com/cpp/multiple-inheritance-considered-useful - dynamic_cast trough vtable

0

10000000

20000000

30000000

40000000

50000000

60000000

dynamic_cast jCAST

5-10X speed-up on real hardware

Page 20: Convert this: peculiarities of cross-platform mobile game development at Vizor

1. Java, на самом деле, подходит как язык для написания движка, с принятием во внимание её особенностей.

Выводы:

2. Любая проблема может быть достойно решена на архитектурном уровне.

3. Индустрия показывает, что конверсия кода – перспективное решение, к которому разработчики прибегают всё чаще.

Page 21: Convert this: peculiarities of cross-platform mobile game development at Vizor

Спасибо за внимание!Вопросы…?