Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 818a1d70 authored by Jason Sams's avatar Jason Sams Committed by Android Git Automerger
Browse files

am 7a4ecc95: Merge "Balls perf update"

# Via Android (Google) Code Review (1) and Jason Sams (1)
* commit '7a4ecc95':
  Balls perf update
parents 40fce329 7a4ecc95
Loading
Loading
Loading
Loading
+28 −20
Original line number Diff line number Diff line
@@ -20,8 +20,9 @@ import android.content.res.Resources;
import android.renderscript.*;
import android.util.Log;


public class BallsRS {
    public static final int PART_COUNT = 900;
    public static final int PART_COUNT = 4000;

    public BallsRS() {
    }
@@ -30,11 +31,12 @@ public class BallsRS {
    private RenderScriptGL mRS;
    private ScriptC_balls mScript;
    private ScriptC_ball_physics mPhysicsScript;
    private ProgramFragment mPFLines;
    private ProgramFragment mPFPoints;
    private ProgramVertex mPV;
    private ScriptField_Point mPoints;
    private ScriptField_VpConsts mVpConsts;
    private ScriptField_BallGrid mGrid;
    private ScriptField_Ball mBalls;
    private Allocation mGridCache;

    void updateProjectionMatrices() {
        mVpConsts = new ScriptField_VpConsts(mRS, 1,
@@ -56,8 +58,8 @@ public class BallsRS {
                    "  vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
                    "  pos.xy = ATTRIB_position;\n" +
                    "  gl_Position = UNI_MVP * pos;\n" +
                    "  varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
                    "  gl_PointSize = ATTRIB_size;\n" +
                    "  varColor = ATTRIB_color;\n" +
                    "  gl_PointSize = 12.0;\n" +
                    "}\n";
        sb.setShader(t);
        sb.addConstant(mVpConsts.getType());
@@ -84,22 +86,21 @@ public class BallsRS {
        return builder.create();
    }

    public void init(RenderScriptGL rs, Resources res, int width, int height) {
        mRS = rs;
        mRes = res;

        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
    private void createPF(int width, int height) {
        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(mRS);
        pfb.setPointSpriteTexCoordinateReplacement(true);
        pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
        pfb.setVaryingColor(true);
        mPFPoints = pfb.create();
    }

        pfb = new ProgramFragmentFixedFunction.Builder(rs);
        pfb.setVaryingColor(true);
        mPFLines = pfb.create();
    public void init(RenderScriptGL rs, Resources res, int width, int height) {
        mRS = rs;
        mRes = res;

        createPF(width, height);

        android.util.Log.e("rs", "Load texture");
        mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0);

        mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);
@@ -109,16 +110,22 @@ public class BallsRS {
        smb.addIndexSetType(Mesh.Primitive.POINT);
        Mesh smP = smb.create();

        mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics);
        mGrid = ScriptField_BallGrid.create2D(mRS, (width + 99) / 100, (height + 99) / 100);
        mGridCache = Allocation.createSized(mRS, Element.F32_2(mRS), PART_COUNT);
        mBalls = new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);

        mPhysicsScript = new ScriptC_ball_physics(mRS);
        mPhysicsScript.set_gGridCache(mGridCache);
        mPhysicsScript.set_gBalls(mBalls.getAllocation());

        mScript = new ScriptC_balls(mRS, mRes, R.raw.balls);
        mScript = new ScriptC_balls(mRS);
        mScript.set_partMesh(smP);
        mScript.set_physics_script(mPhysicsScript);
        mScript.bind_point(mPoints);
        mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));
        mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));
        mScript.bind_balls(mBalls);
        mScript.set_gGrid(mGrid.getAllocation());
        mScript.bind_gGridCache(mGridCache);

        mScript.set_gPFLines(mPFLines);
        mScript.set_gPFPoints(mPFPoints);
        createProgramVertex();

@@ -126,6 +133,7 @@ public class BallsRS {

        mPhysicsScript.set_gMinPos(new Float2(5, 5));
        mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
        mPhysicsScript.set_gGrid(mGrid.getAllocation());

        mScript.invoke_initParts(width, height);

@@ -133,7 +141,7 @@ public class BallsRS {
    }

    public void newTouchPosition(float x, float y, float pressure, int id) {
        mPhysicsScript.invoke_touch(x, y, pressure, id);
        mPhysicsScript.invoke_touch(x, y, pressure * mRS.getWidth() / 1280, id);
    }

    public void setAccel(float x, float y) {
+92 −83
Original line number Diff line number Diff line
@@ -10,6 +10,13 @@ float2 gMaxPos = {1280.f, 700.f};

static float2 touchPos[10];
static float touchPressure[10];
static const float gDT = 1.f / 30.f;

rs_allocation gGrid;
rs_allocation gGridCache;
rs_allocation gBalls;

float gScale = 1.f;

void touch(float x, float y, float pressure, int id) {
    if (id >= 10) {
@@ -21,126 +28,128 @@ void touch(float x, float y, float pressure, int id) {
    touchPressure[id] = pressure;
}

void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) {
    float2 fv = {0, 0};
    float2 pos = ballIn->position;

    int arcID = -1;
    float arcInvStr = 100000;
void root(Ball_t *ball, uint32_t x) {
    float2 fv = 0;
    float pressure = 0;
    float2 pos = ball->position;
    int2 gridPos[9];

    gridPos[0] = convert_int2((ball->position / 100.f) /*- 0.4999f*/);
    gridPos[1] = (int2){gridPos[0].x - 1, gridPos[0].y - 1};
    gridPos[2] = (int2){gridPos[0].x + 0, gridPos[0].y - 1};
    gridPos[3] = (int2){gridPos[0].x + 1, gridPos[0].y - 1};
    gridPos[4] = (int2){gridPos[0].x - 1, gridPos[0].y};
    gridPos[5] = (int2){gridPos[0].x + 1, gridPos[0].y};
    gridPos[6] = (int2){gridPos[0].x - 1, gridPos[0].y + 1};
    gridPos[7] = (int2){gridPos[0].x + 0, gridPos[0].y + 1};
    gridPos[8] = (int2){gridPos[0].x + 1, gridPos[0].y + 1};

    for (int gct=0; gct < 9; gct++) {
        if ((gridPos[gct].x >= rsAllocationGetDimX(gGrid)) ||
            (gridPos[gct].x < 0) ||
            (gridPos[gct].y >= rsAllocationGetDimY(gGrid)) ||
            (gridPos[gct].y < 0)) {
            continue;
        }
        //rsDebug("grid ", gridPos[gct]);
        const BallGrid_t *bg = (const BallGrid_t *)rsGetElementAt(gGrid, gridPos[gct].x, gridPos[gct].y);

    const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0);
    for (uint32_t xin = 0; xin < ctl->dimX; xin++) {
        float2 vec = bPtr[xin].position - pos;
        for (int cidx = 0; cidx < bg->count; cidx++) {
            float2 bcptr = rsGetElementAt_float2(gGridCache, bg->cacheIdx + cidx);
            float2 vec = bcptr - pos;
            float2 vec2 = vec * vec;
            float len2 = vec2.x + vec2.y;

        if (len2 < 10000) {
            //float minDist = ballIn->size + bPtr[xin].size;
            float forceScale = ballIn->size * bPtr[xin].size;
            forceScale *= forceScale;

            if (len2 > 16 /* (minDist*minDist)*/)  {
                // Repulsion
                float len = sqrt(len2);
                fv -= (vec / (len * len * len)) * 20000.f * forceScale;
            } else {
                if (len2 < 1) {
                    if (xin == x) {
                        continue;
                    }
                    ballOut->delta = 0.f;
                    ballOut->position = ballIn->position;
                    if (xin > x) {
                        ballOut->position.x += 1.f;
                    } else {
                        ballOut->position.x -= 1.f;
                    }
                    //ballOut->color.rgb = 1.f;
                    //ballOut->arcID = -1;
                    //ballOut->arcStr = 0;
                    continue;
                }
                // Collision
                float2 axis = normalize(vec);
                float e1 = dot(axis, ballIn->delta);
                float e2 = dot(axis, bPtr[xin].delta);
                float e = (e1 - e2) * 0.45f;
                if (e1 > 0) {
                    fv -= axis * e;
                } else {
                    fv += axis * e;
                }
            if ((len2 < 10000.f) && (len2 > 0.f)) {
                float t = native_powr(len2, 1.5f) + 16.0f;
                float2 pfv = (vec / t) * 16000.f;
                pressure += length(pfv);
                fv -= pfv;
            }
        }
    }

    fv /= ballIn->size * ballIn->size * ballIn->size;
    fv -= gGravityVector * 4.f;
    fv *= ctl->dt;
    //fv /= ball->size * ball->size * ball->size;
    fv -= gGravityVector * 4.f * gScale;
    fv *= gDT;

    for (int i=0; i < 10; i++) {
        if (touchPressure[i] > 0.1f) {
            float2 vec = touchPos[i] - ballIn->position;
            float2 vec = touchPos[i] - ball->position;
            float2 vec2 = vec * vec;
            float len2 = max(2.f, vec2.x + vec2.y);
            fv -= (vec / len2) * touchPressure[i] * 300.f;
            float2 pfv = (vec / len2) * touchPressure[i] * 500.f * gScale;
            pressure += length(pfv);
            fv -= pfv;
        }
    }

    ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv;
    ballOut->position = ballIn->position + (ballOut->delta * ctl->dt);
    ball->delta = (ball->delta * (1.f - 0.008f)) + fv;
    ball->position = ball->position + (ball->delta * gDT);

    const float wallForce = 400.f;
    if (ballOut->position.x > (gMaxPos.x - 20.f)) {
        float d = gMaxPos.x - ballOut->position.x;
    const float wallForce = 400.f * gScale;
    if (ball->position.x > (gMaxPos.x - 20.f)) {
        float d = gMaxPos.x - ball->position.x;
        if (d < 0.f) {
            if (ballOut->delta.x > 0) {
                ballOut->delta.x *= -0.7f;
            if (ball->delta.x > 0) {
                ball->delta.x *= -0.7f;
            }
            ballOut->position.x = gMaxPos.x;
            ball->position.x = gMaxPos.x - 1.f;
        } else {
            ballOut->delta.x -= min(wallForce / (d * d), 10.f);
            ball->delta.x -= min(wallForce / (d * d), 10.f);
        }
    }

    if (ballOut->position.x < (gMinPos.x + 20.f)) {
        float d = ballOut->position.x - gMinPos.x;
    if (ball->position.x < (gMinPos.x + 20.f)) {
        float d = ball->position.x - gMinPos.x;
        if (d < 0.f) {
            if (ballOut->delta.x < 0) {
                ballOut->delta.x *= -0.7f;
            if (ball->delta.x < 0) {
                ball->delta.x *= -0.7f;
            }
            ballOut->position.x = gMinPos.x + 1.f;
            ball->position.x = gMinPos.x + 1.f;
        } else {
            ballOut->delta.x += min(wallForce / (d * d), 10.f);
            ball->delta.x += min(wallForce / (d * d), 10.f);
        }
    }

    if (ballOut->position.y > (gMaxPos.y - 20.f)) {
        float d = gMaxPos.y - ballOut->position.y;
    if (ball->position.y > (gMaxPos.y - 20.f)) {
        float d = gMaxPos.y - ball->position.y;
        if (d < 0.f) {
            if (ballOut->delta.y > 0) {
                ballOut->delta.y *= -0.7f;
            if (ball->delta.y > 0) {
                ball->delta.y *= -0.7f;
            }
            ballOut->position.y = gMaxPos.y;
            ball->position.y = gMaxPos.y - 1.f;
        } else {
            ballOut->delta.y -= min(wallForce / (d * d), 10.f);
            ball->delta.y -= min(wallForce / (d * d), 10.f);
        }
    }

    if (ballOut->position.y < (gMinPos.y + 20.f)) {
        float d = ballOut->position.y - gMinPos.y;
    if (ball->position.y < (gMinPos.y + 20.f)) {
        float d = ball->position.y - gMinPos.y;
        if (d < 0.f) {
            if (ballOut->delta.y < 0) {
                ballOut->delta.y *= -0.7f;
            if (ball->delta.y < 0) {
                ball->delta.y *= -0.7f;
            }
            ballOut->position.y = gMinPos.y + 1.f;
            ball->position.y = gMinPos.y + 1.f;
        } else {
            ballOut->delta.y += min(wallForce / (d * d * d), 10.f);
            ball->delta.y += min(wallForce / (d * d * d), 10.f);
        }
    }

    ballOut->size = ballIn->size;
    // low pressure ~500, high ~2500
    pressure = max(pressure - 400.f, 0.f);
    ball->pressure = pressure;

    //rsDebug("p ", pressure);

    float4 color = 1.f;
    color.r = pow(pressure, 0.25f) / 12.f;
    color.b = 1.f - color.r;
    color.g = sin(pressure / 1500.f * 3.14f);
    color.rgb = max(color.rgb, (float3)0);
    color.rgb = normalize(color.rgb);
    ball->color = rsPackColorTo8888(color);

    //rsDebug("physics pos out", ballOut->position);
    //rsDebug("physics pos out", ball->position);
}
+60 −37
Original line number Diff line number Diff line
@@ -8,12 +8,15 @@
#pragma stateStore(parent)

rs_program_fragment gPFPoints;
rs_program_fragment gPFLines;
rs_mesh partMesh;

rs_allocation gGrid;
BallGrid_t *unused1;
float2 *gGridCache;

typedef struct __attribute__((packed, aligned(4))) Point {
    float2 position;
    float size;
    uchar4 color;
} Point_t;
Point_t *point;

@@ -24,58 +27,78 @@ VpConsts_t *vpConstants;

rs_script physics_script;

Ball_t *balls1;
Ball_t *balls2;

static int frame = 0;

void initParts(int w, int h)
{
    uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1));
    uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls));

    for (uint32_t ct=0; ct < dimX; ct++) {
        balls1[ct].position.x = rsRand(0.f, (float)w);
        balls1[ct].position.y = rsRand(0.f, (float)h);
        balls1[ct].delta.x = 0.f;
        balls1[ct].delta.y = 0.f;
        balls1[ct].size = 1.f;

        float r = rsRand(100.f);
        if (r > 90.f) {
            balls1[ct].size += pow(10.f, rsRand(0.f, 2.f)) * 0.07f;
        }
        balls[ct].position.x = rsRand(0.f, (float)w);
        balls[ct].position.y = rsRand(0.f, (float)h);
        balls[ct].delta.x = 0.f;
        balls[ct].delta.y = 0.f;
    }
}



int root() {
    rsgClearColor(0.f, 0.f, 0.f, 1.f);

    BallControl_t bc;
    Ball_t *bout;

    if (frame & 1) {
        bc.ain = rsGetAllocation(balls2);
        bc.aout = rsGetAllocation(balls1);
        bout = balls1;
    } else {
        bc.ain = rsGetAllocation(balls1);
        bc.aout = rsGetAllocation(balls2);
        bout = balls2;
    int2 gridDims = (int2){ rsAllocationGetDimX(gGrid),
                            rsAllocationGetDimY(gGrid) };

    rs_allocation ain = rsGetAllocation(balls);
    int32_t dimX = rsAllocationGetDimX(ain);

    // Binning
    // Clear the particle list
    for (uint32_t ct=0; ct < dimX; ct++) {
        balls[ct].next = -1;
    }

    bc.dimX = rsAllocationGetDimX(bc.ain);
    bc.dt = 1.f / 30.f;
    // Clear the grid
    for (uint32_t y=0; y < gridDims.y; y++) {
        for (uint32_t x=0; x < gridDims.x; x++) {
            BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, x, y);
            bg->count = 0;
            bg->idx = -1;
        }
    }

    rsForEach(physics_script, bc.ain, bc.aout, &bc, sizeof(bc));
    // Create the particle list per grid
    for (uint32_t ct=0; ct < dimX; ct++) {
        int2 p = convert_int2(balls[ct].position / 100.f);
        p.x = rsClamp(p.x, 0, (int)(gridDims.x-1));
        p.y = rsClamp(p.y, 0, (int)(gridDims.y-1));
        BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, p.x, p.y);
        bg->count ++;
        balls[ct].next = bg->idx;
        bg->idx = ct;
    }

    for (uint32_t ct=0; ct < bc.dimX; ct++) {
        point[ct].position = bout[ct].position;
        point[ct].size = 6.f /*+ bout[ct].color.g * 6.f*/ * bout[ct].size;
    // Create the sorted grid cache
    uint32_t gridIdx = 0;
    for (uint32_t y=0; y < gridDims.y; y++) {
        for (uint32_t x=0; x < gridDims.x; x++) {
            BallGrid_t *bg = (BallGrid_t *)rsGetElementAt(gGrid, x, y);
            bg->cacheIdx = gridIdx;

            int idx = bg->idx;
            while (idx >= 0) {
                const Ball_t * bPtr = &balls[idx];
                gGridCache[gridIdx++] = bPtr->position;
                idx = bPtr->next;
            }
        }
    }


    rsForEach(physics_script, ain, ain);

    for (uint32_t ct=0; ct < dimX; ct++) {
        point[ct].position = balls[ct].position;
        point[ct].color = balls[ct].color;
    }

    frame++;
    rsgBindProgramFragment(gPFPoints);
    rsgDrawMesh(partMesh);
    return 1;
+9 −8
Original line number Diff line number Diff line
@@ -2,17 +2,18 @@
typedef struct __attribute__((packed, aligned(4))) Ball {
    float2 delta;
    float2 position;
    //float3 color;
    float size;
    uchar4 color;
    float pressure;
    //float size;
    int32_t next;
    //int arcID;
    //float arcStr;
} Ball_t;
Ball_t *balls;


typedef struct BallControl {
    uint32_t dimX;
    rs_allocation ain;
    rs_allocation aout;
    float dt;
} BallControl_t;
typedef struct BallGrid {
    int32_t idx;
    int32_t count;
    int32_t cacheIdx;
} BallGrid_t;