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

Commit 7a4ecc95 authored by Jason Sams's avatar Jason Sams Committed by Android (Google) Code Review
Browse files

Merge "Balls perf update"

parents d838ca6b fe02fc43
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;