instead of frequently accessing Java from C-side, feed everything beforehand on Java-side

This commit is contained in:
minjaesong
2019-02-08 11:46:30 +09:00
parent 78bbd9c051
commit af619cda79
3 changed files with 45 additions and 92 deletions

View File

@@ -1,15 +1,14 @@
#include <xmmintrin.h>
#include <jni.h>
#include <stddef.h>
#include "net_torvald_terrarum_worlddrawer_LightmapRenderer.h"
/*
compile required headers with:
"C:\Program Files\Java\jdk1.8.0_131\bin\javah.exe" -jni -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terr
arum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.worlddrawer.LightmapRenderer
"C:\Program Files\Java\jdk1.8.0_131\bin\javah.exe" -jni -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terrarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.worlddrawer.LightmapRenderer
get method signatures with:
"C:\Program Files\Java\jdk1.8.0_131\bin\javap.exe" -s -p -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\ter
rarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.gameworld.GameWorld
"C:\Program Files\Java\jdk1.8.0_131\bin\javap.exe" -s -p -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terrarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.gameworld.GameWorld
*/
#define vec4 __m128
@@ -32,58 +31,14 @@ const vec4 oneVec = _mm_set1_ps(1);
const vec4 zeroVec = _mm_set1_ps(0);
const vec4 sqrt2Vec = _mm_set1_ps(1.41421356f);
int LIGHTMAP_WIDTH;
int for_x_start = 0;
int for_y_start = 0;
int for_x_end = 0;
int for_y_end = 0;
int LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT;
int for_x_start;
int for_y_start;
int for_x_end;
int for_y_end;
void getLightsAndShades(JNIEnv *env, jclass cls, jobject obj, int x, int y) {
// get world first
jfieldID fid = (*env)->GetFieldID(env, cls, "world", "Lnet/torvald/terrarum/gameworld/GameWorld;");
jobject worldobj = (*env)->GetObjectField(env, obj, fid);
jclass worldcls = (*env)->GetObjectClass(env, worldobj);
void getLightsAndShades(int x, int y, jfloatArray lightmap, jintArray groundmap, jfloatArray lummap, jfloatArray shademap, jbyteArray fluidtypemap, jfloatArray fluidfillmap, jfloatArray sun) {
// get method IDs
jmethodID getTerrain_mid = (*env)->GetMethodID(env, worldcls, "getTileFromTerrain", "(II)Ljava/lang/Integer;")
jmethodID getFluid_mid = (*env)->GetMethodID(env, worldcls, "getFluid", "(II)Lnet/torvald/terrarum/gameworld/GameWorld$FluidInfo;")
jmethodID getWall_mid = (*env)->GetMethodID(env, worldcls, "getTileFromWall", "(II)Ljava/lang/Integer;")
jmethodID getSun_mid = (*env)->GetMethodID(env, worldcls, "getGlobalLight", "()Lcom/badlogic/gdx/graphics/Color;")
// populate the vars
thisTerrain = (*env)->CallObjectMethod(env, worldobj, getTerrain_mid, x, y);
thisFluid = (*env)->CallObjectMethod(env, worldobj, getFluid_mid, x, y);
thisWall = (*env)->CallObjectMethod(env, worldobj, getWall_mid, x, y);
// set sunlight
jobject sun_gdxcolor = (*env)->CallObjectMethod(env, worldobj, getSun_mid, x, y);
jclass gdxcolor_cls = (*env)->GetObjectClass(env, sun_gdxcolor);
jfieldID sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "r", "F");
float sunr = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT;
sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "g", "F");
float sung = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT;
sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "b", "F");
float sunb = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT;
sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "a", "F");
float suna = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT;
// TODO check rgba argument order (RGBA or ABGR, intel doc is confusing)
sunLight = _mm_set_ps(sunr, sung, sunb, suna);
// get fluid info
jclass fluid_cls = (*env)->GetObjectClass(env, thisFluid);
jfieldID fluidfid = (*env)->GetFieldID(env, fluid_cls, "type", "I");
jint fluidType = GetIntField(env, thisFluid, fluidfid);
fluidfid = (*env)->GetFieldID(env, fluid_cls, "amount", "F");
jfloat fluidFill = GetIntField(env, thisFluid, fluidfid);
lightLevelThis = _mm_set1_ps(0);
if (fluidType != 0) {
fluidAmountToCol = _mm_set1_ps(fluidFill);
thisTileLuminosity =
}
}
@@ -117,7 +72,7 @@ vec4 calculate(int x, int y) {
return lightLevelThis
}
void setLightOf(JNIEnv *env, jclass cls, int x, int y, vec4 colour) {
void setLightOf(jfloatArray lightmap, int x, int y, vec4 colour) {
if (y - for_y_start + overscan_open >= 0 &&
y - for_y_start + overscan_open < LIGHTMAP_HEIGHT &&
@@ -131,21 +86,17 @@ void setLightOf(JNIEnv *env, jclass cls, int x, int y, vec4 colour) {
float[4] vector;
_mm_store_ps(vector *, colour);
// get the array
jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F");
jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null);
// set r/g/b/a values
list[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = vector[0];
list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = vector[1];
list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = vector[2];
list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = vector[3];
lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = vector[0];
lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = vector[1];
lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = vector[2];
lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = vector[3];
//list[4 * ypos * LIGHTMAP_WIDTH + xpos] = colour
}
}
vec4 getLightInternal(JNIEnv *env, jobject obj, int x, int y) {
vec4 getLightInternal(jfloatArray lightmap, int x, int y) {
if (y - for_y_start + overscan_open >= 0 &&
y - for_y_start + overscan_open < LIGHTMAP_HEIGHT &&
@@ -155,35 +106,25 @@ vec4 getLightInternal(JNIEnv *env, jobject obj, int x, int y) {
int ypos = y - for_y_start + overscan_open
int xpos = x - for_x_start + overscan_open
// get the array
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F");
jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null);
float r = list[4 * (ypos * LIGHTMAP_WIDTH + xpos)];
float g = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1];
float b = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2];
float a = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3];
float r = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos)];
float g = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1];
float b = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2];
float a = lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3];
// TODO check rgba argument order (RGBA or ABGR, intel doc is confusing)
return _mm_set_ps(r, g, b, a);
}
}
JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI(JNIEnv *env, jobject object) {
// update (read) variables
jclass cls = (*env)->GetObjectClass(env, object);
jfieldID fid = (*env)->GetFieldID(env, cls, "LIGHTMAP_WIDTH", "I");
LIGHTMAP_WIDTH = (*env)->GetIntField(env, obj, fid);
fid = (*env)->GetFieldID(env, cls, "for_x_start", "I");
for_x_start = (*env)->GetIntField(env, obj, fid);
fid = (*env)->GetFieldID(env, cls, "for_y_start", "I");
for_y_start = (*env)->GetIntField(env, obj, fid);
fid = (*env)->GetFieldID(env, cls, "for_x_end", "I");
for_x_end = (*env)->GetIntField(env, obj, fid);
fid = (*env)->GetFieldID(env, cls, "for_y_end", "I");
for_y_end = (*env)->GetIntField(env, obj, fid);
JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI
(JNIEnv * env, jobject object, jint forxstart, jint forxend, jint forystart, jint foryend, jint lighmapwidth, jint lightmapheight, jfloatArray lightmap, jintArray groundmap, jfloatArray lummap, jfloatArray shademap, jbyteArray fluidtypemap, jfloatArray fluidfillmap, jfloatArray sun) { // update (read) variables
LIGHTMAP_WIDTH = lightmapwidth;
LIGHTMAP_HEIGHT = lightmapheight;
for_x_start = forxstart;
for_x_end = forxend;
for_y_start = forystart;
for_y_end = foryend;
/**
* Updating order:
@@ -200,7 +141,10 @@ JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fi
* But why start from 2? No special reason.
*/
// clear the lightmap
for (size_t i = 0; i < sizeof(lightmap) / sizeof(lightmap[0]); i++) {
lightmap[i] = 0f;
}
return;
}

View File

@@ -82,7 +82,7 @@ object LightmapRenderer {
*/
// it utilises alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light)
//private val lightmap: Array<Array<Color>> = Array(LIGHTMAP_HEIGHT) { Array(LIGHTMAP_WIDTH, { Color(0f,0f,0f,0f) }) } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4.
private val lightmap: Array<Float> = Array(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 4) { 0f } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4.
private val lightmap: FloatArray = FloatArray(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 4) { 0f } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4.
private val lanternMap = HashMap<BlockAddress, Color>((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4)
private lateinit var texturedLightMap: FrameBuffer
@@ -224,7 +224,7 @@ object LightmapRenderer {
* @param colour Color to write
* @param applyFun A function ```foo(old_colour, given_colour)```
*/
private fun setLightOf(list: Array<Float>, x: Int, y: Int, colour: Color) {
private fun setLightOf(list: FloatArray, x: Int, y: Int, colour: Color) {
if (y - for_y_start + overscan_open in 0 until LIGHTMAP_HEIGHT &&
x - for_x_start + overscan_open in 0 until LIGHTMAP_WIDTH) {
@@ -361,7 +361,16 @@ object LightmapRenderer {
}
private external fun fireRecalculateEventJNI()
private external fun fireRecalculateEventJNI(
for_x_start: Int, for_x_end: Int, for_y_start: Int, for_y_end: Int,
lightmapwidth: Int, lightmapheight: Int, lightmap: FloatArray,
groundmap: IntArray, // high 16 bits: ground, low 16 bits: terrain
lummap: FloatArray, // interleaved RGBA
shademap: FloatArray, // interleaved RGBA
fluidtypemap: ByteArray, // 127 different fluids
fluidfillmap: FloatArray,
sun: FloatArray
)

View File

@@ -48,10 +48,10 @@ extern "C" {
/*
* Class: net_torvald_terrarum_worlddrawer_LightmapRenderer
* Method: fireRecalculateEventJNI
* Signature: ()V
* Signature: (IIIIII[F[I[F[F[B[F[F)V
*/
JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI
(JNIEnv *, jobject);
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jfloatArray, jintArray, jfloatArray, jfloatArray, jbyteArray, jfloatArray, jfloatArray);
#ifdef __cplusplus
}