Initial tests of GPU rendering
Successfully rendered to the map via the GPU (well not really, it falls back to an alternative algorithm) Dropping the PXCLib - finally realized that the GPU speed massively increases after the first pass
This commit is contained in:
parent
f029fc22ec
commit
19b9f1fad6
7 changed files with 128 additions and 17 deletions
|
@ -28,6 +28,9 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-g</arg>
|
||||||
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-g</arg> <!-- TODO: Still warns about this -->
|
||||||
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -92,5 +95,10 @@
|
||||||
<artifactId>aparapi</artifactId>
|
<artifactId>aparapi</artifactId>
|
||||||
<version>1.10.0</version>
|
<version>1.10.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.16.16</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
|
@ -68,7 +68,8 @@ public class DirectRenderer implements IRenderer {
|
||||||
if(System.nanoTime()-lastrender<100*1000*1000)
|
if(System.nanoTime()-lastrender<100*1000*1000)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
long p = PluginMain.pxc.updateAndGetMap((int) x, (int) y, (int) width, (int) height, null);
|
//long p = PluginMain.pxc.updateAndGetMap((int) x, (int) y, (int) width, (int) height, null);
|
||||||
|
long p = 0; //TODO: Not used (class)
|
||||||
if (p == 0) return;
|
if (p == 0) return;
|
||||||
byte[] img = new Pointer(p).getByteArray(0, 128 * 128);
|
byte[] img = new Pointer(p).getByteArray(0, 128 * 128);
|
||||||
boolean hascolor=false;
|
boolean hascolor=false;
|
||||||
|
|
76
VirtualComputer/src/sznp/virtualcomputer/GPURenderer.java
Normal file
76
VirtualComputer/src/sznp/virtualcomputer/GPURenderer.java
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
package sznp.virtualcomputer;
|
||||||
|
|
||||||
|
import com.aparapi.Kernel;
|
||||||
|
import com.aparapi.Range;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.minecraft.server.v1_12_R1.WorldMap;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
|
||||||
|
import org.bukkit.craftbukkit.v1_12_R1.map.RenderData;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.map.MapCanvas;
|
||||||
|
import org.bukkit.map.MapRenderer;
|
||||||
|
import org.bukkit.map.MapView;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GPURenderer extends MapRenderer implements IRenderer {
|
||||||
|
private byte[] buffer;
|
||||||
|
private MapView map;
|
||||||
|
private Kernel kernel;
|
||||||
|
@Setter
|
||||||
|
private static int width;
|
||||||
|
private Range range;
|
||||||
|
|
||||||
|
public GPURenderer(short id, World world, int mapx, int mapy) throws Exception {
|
||||||
|
map = IRenderer.prepare(id, world);
|
||||||
|
final Field field = map.getClass().getDeclaredField("renderCache");
|
||||||
|
field.setAccessible(true);
|
||||||
|
@SuppressWarnings("unchecked") final Map<CraftPlayer, RenderData> renderCache = (Map<CraftPlayer, RenderData>) field.get(map);
|
||||||
|
|
||||||
|
RenderData render = renderCache.get(null);
|
||||||
|
|
||||||
|
if (render == null)
|
||||||
|
renderCache.put(null, render = new RenderData());
|
||||||
|
|
||||||
|
this.buffer = render.buffer;
|
||||||
|
|
||||||
|
kernel = new Kernel() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int mx = getGlobalId(0);
|
||||||
|
int my = getGlobalId(1);
|
||||||
|
int imgx = mx + mapx * 128;
|
||||||
|
int imgy = my + mapy * 128;
|
||||||
|
int imgi = imgy * width + imgx;
|
||||||
|
buffer[my * 128 + mx] = matchColor(PluginMain.pixels[imgi]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
range = Range.create2D(128, 128);
|
||||||
|
|
||||||
|
map.addRenderer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MapView map, MapCanvas canvas, Player player) {
|
||||||
|
try {
|
||||||
|
if (width == 0) return; //TODO: Stop rendering after computer is stopped
|
||||||
|
Field field = canvas.getClass().getDeclaredField("buffer");
|
||||||
|
field.setAccessible(true);
|
||||||
|
buffer = (byte[]) field.get(canvas);
|
||||||
|
kernel.put(buffer).put(PluginMain.pixels).execute(range).get(buffer);
|
||||||
|
field = map.getClass().getDeclaredField("worldMap");
|
||||||
|
field.setAccessible(true);
|
||||||
|
WorldMap wmap = (WorldMap) field.get(map);
|
||||||
|
wmap.flagDirty(0, 0);
|
||||||
|
wmap.flagDirty(127, 127); // Send the whole image - TODO: Only send changes
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte matchColor(int bgra) { //TODO
|
||||||
|
return 48;
|
||||||
|
}
|
||||||
|
}
|
|
@ -105,9 +105,11 @@ public class MCFrameBuffer implements IFramebuffer {
|
||||||
holder.value.getTypedWrapped().queryBitmapInfo(ptr, w, h, bpp, bpl, pf);
|
holder.value.getTypedWrapped().queryBitmapInfo(ptr, w, h, bpp, bpl, pf);
|
||||||
System.out.println("Arr0:" + ptr[0]);
|
System.out.println("Arr0:" + ptr[0]);
|
||||||
System.out.println("whbppbplpf: " + w[0] + " " + h[0] + " " + bpp[0] + " " + bpl[0] + " " + pf[0]);
|
System.out.println("whbppbplpf: " + w[0] + " " + h[0] + " " + bpp[0] + " " + bpl[0] + " " + pf[0]);
|
||||||
if(PluginMain.direct)
|
if (PluginMain.direct) {
|
||||||
PluginMain.pxc.setSource(ptr[0], (int)w[0], (int)h[0], PluginMain.MCX, PluginMain.MCY);
|
//PluginMain.pxc.setSource(ptr[0], (int)w[0], (int)h[0], PluginMain.MCX, PluginMain.MCY);
|
||||||
else {
|
PluginMain.pixels = new Pointer(ptr[0]).getByteArray(0L, (int) (w[0] * h[0] * 4));
|
||||||
|
GPURenderer.setWidth((int) w[0]);
|
||||||
|
} else {
|
||||||
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
PluginMain.allpixels = new Pointer(ptr[0]).getByteBuffer(0L, width * height * 4);
|
||||||
if (width * height > 640 * 480)
|
if (width * height > 640 * 480)
|
||||||
PluginMain.allpixels.limit(640 * 480 * 4);
|
PluginMain.allpixels.limit(640 * 480 * 4);
|
||||||
|
|
|
@ -37,8 +37,12 @@ public class PluginMain extends JavaPlugin {
|
||||||
/**
|
/**
|
||||||
* Only used if {@link #direct} is true.
|
* Only used if {@link #direct} is true.
|
||||||
*/
|
*/
|
||||||
public static PXCLib pxc;
|
//public static PXCLib pxc;
|
||||||
public static boolean direct;
|
public static boolean direct;
|
||||||
|
/**
|
||||||
|
* Only used if {@link #direct} is true.
|
||||||
|
*/
|
||||||
|
public static byte[] pixels;
|
||||||
|
|
||||||
// Fired when plugin is first enabled
|
// Fired when plugin is first enabled
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,9 +77,10 @@ public class PluginMain extends JavaPlugin {
|
||||||
ccs.sendMessage("§bLoading Screen...");
|
ccs.sendMessage("§bLoading Screen...");
|
||||||
try {
|
try {
|
||||||
//throw new NoClassDefFoundError("Test error pls ignore");
|
//throw new NoClassDefFoundError("Test error pls ignore");
|
||||||
for (short i = 0; i < 20; i++)
|
for (short i = 0; i < 5; i++)
|
||||||
renderers.add(new DirectRenderer(i, Bukkit.getWorlds().get(0), i * 128 * 128 * 4)); // TODO: The pixels are selected in a horribly wrong way probably
|
for (short j = 0; j < 4; j++)
|
||||||
pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc");
|
renderers.add(new GPURenderer(i, Bukkit.getWorlds().get(0), i, j));
|
||||||
|
//pxc = LibraryLoader.create(PXCLib.class).search(getDataFolder().getAbsolutePath()).load("pxc");
|
||||||
direct=true;
|
direct=true;
|
||||||
ccs.sendMessage("§bUsing Direct Renderer, all good");
|
ccs.sendMessage("§bUsing Direct Renderer, all good");
|
||||||
} catch (NoClassDefFoundError | Exception e) {
|
} catch (NoClassDefFoundError | Exception e) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package sznp.virtualcomputer;
|
||||||
|
|
||||||
import com.aparapi.Kernel;
|
import com.aparapi.Kernel;
|
||||||
import com.aparapi.Range;
|
import com.aparapi.Range;
|
||||||
import com.sun.jna.Native;
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import jnr.ffi.LibraryLoader;
|
import jnr.ffi.LibraryLoader;
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
|
@ -12,9 +11,7 @@ import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.Buffer;
|
import java.nio.Buffer;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.LongStream;
|
|
||||||
|
|
||||||
public class Test {
|
public class Test {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -28,7 +25,6 @@ public class Test {
|
||||||
//final int[] b={10,80,10,3,32,20,56,85,51,968,156,5894,10,60,52};
|
//final int[] b={10,80,10,3,32,20,56,85,51,968,156,5894,10,60,52};
|
||||||
//final int[] a={5,6};
|
//final int[] a={5,6};
|
||||||
//final int[] b={10,80};
|
//final int[] b={10,80};
|
||||||
long t=System.nanoTime();
|
|
||||||
int[] a= IntStream.range(0, 640*480).toArray();
|
int[] a= IntStream.range(0, 640*480).toArray();
|
||||||
final int[] res=new int[a.length];
|
final int[] res=new int[a.length];
|
||||||
Kernel kernel=new Kernel() {
|
Kernel kernel=new Kernel() {
|
||||||
|
@ -37,14 +33,20 @@ public class Test {
|
||||||
int i=getGlobalId();
|
int i=getGlobalId();
|
||||||
//System.out.println(i);
|
//System.out.println(i);
|
||||||
//res[i]=a[i]+b[i];
|
//res[i]=a[i]+b[i];
|
||||||
Color c=Color.fromBGR((int)a[i]);
|
//res[i]= MapPalette.matchColor(a[i] & 0x0000FF, a[i] & 0x00FF00 >> 8, a[i] & 0xFF0000 >> 16);
|
||||||
res[i]= MapPalette.matchColor(c.getRed(), c.getGreen(), c.getBlue());
|
res[i] = a[i];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
kernel.execute(Range.create(res.length));
|
long t = System.nanoTime();
|
||||||
|
kernel.put(a).execute(Range.create(res.length)).get(res);
|
||||||
//System.out.println(Arrays.toString(res));
|
//System.out.println(Arrays.toString(res));
|
||||||
System.out.println(a[10]);
|
System.out.println(a[10]);
|
||||||
System.out.println("OpenCL time: "+(System.nanoTime()-t)/1000000f+"ms");
|
System.out.println("OpenCL time: "+(System.nanoTime()-t)/1000000f+"ms");
|
||||||
|
a[50] = 652; //Massive speedups after the fist pass
|
||||||
|
t = System.nanoTime();
|
||||||
|
kernel.put(a).execute(Range.create(res.length)).get(res);
|
||||||
|
System.out.println(a[10]);
|
||||||
|
System.out.println("Second OpenCL time: " + (System.nanoTime() - t) / 1000000f + "ms");
|
||||||
|
|
||||||
t=System.nanoTime();
|
t=System.nanoTime();
|
||||||
for (int i = 0; i < res.length; i++) {
|
for (int i = 0; i < res.length; i++) {
|
||||||
|
@ -58,15 +60,29 @@ public class Test {
|
||||||
System.out.println("Sys time: "+(System.nanoTime()-t)/1000000f+"ms");
|
System.out.println("Sys time: "+(System.nanoTime()-t)/1000000f+"ms");
|
||||||
|
|
||||||
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
||||||
ByteBuffer bb=ByteBuffer.allocateDirect(640*480);
|
ByteBuffer bb = ByteBuffer.allocateDirect(640 * 480 * 4);
|
||||||
try {
|
try {
|
||||||
Field f=Buffer.class.getDeclaredField("address");
|
Field f=Buffer.class.getDeclaredField("address");
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
long addr= (long) f.get(bb);
|
long addr= (long) f.get(bb);
|
||||||
pxc.setSource(addr, 640, 480, 5, 4);
|
pxc.setSource(addr, 640, 480, 5, 4);
|
||||||
pxc.updateAndGetMap(0, 0, 640, 480, null);
|
t = System.nanoTime();
|
||||||
|
long p = pxc.updateAndGetMap(0, 0, 640, 480, null);
|
||||||
|
if (p == 0) return;
|
||||||
|
byte[] img = new Pointer(p).getByteArray(0, 128 * 128);
|
||||||
|
System.out.println("img[50]: " + img[50]);
|
||||||
|
System.out.println("Native time: " + (System.nanoTime() - t) / 1000000f + "ms");
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kernel = new Kernel() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PXCLib pxc = LibraryLoader.create(PXCLib.class).search(new File("").getAbsolutePath()).load("pxc");
|
||||||
|
pxc.updateAndGetMap(0, 0, 0, 0, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
kernel.execute(Range.create(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue