Notice to GitKraken users: A vulnerability has been found in the SSH key generation of GitKraken versions 7.6.0 to 8.0.0 (https://www.gitkraken.com/blog/weak-ssh-key-fix). If you use GitKraken and have generated a SSH key using one of these versions, please remove it both from your local workstation and from your LRZ GitLab profile.

21.10.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 376f75c4 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

OpenCL bug-fix: memory leaks.

parent 50d9ef0d
......@@ -11,63 +11,64 @@ import org.vadere.state.attributes.scenario.AttributesAgent;
public class CLGaussianCalculator {
private final double scale;
private final int scenarioWidth;
private final int scenarioHeight;
private SimulationModel<DefaultSimulationConfig> model;
private final double scale;
private final int scenarioWidth;
private final int scenarioHeight;
private SimulationModel<DefaultSimulationConfig> model;
private IGaussianFilter filterObstacles;
private IGaussianFilter filterObstacles;
private IGaussianFilter filterPedestrians;
public CLGaussianCalculator(final SimulationModel model,
final double scale,
final double measurementRadius,
final Color color,
final boolean visualisation,
final boolean scenarioBound) {
public CLGaussianCalculator(final SimulationModel model,
final double scale,
final double measurementRadius,
final Color color,
final boolean visualisation,
final boolean scenarioBound) {
this.scenarioWidth = (int) model.getTopographyBound().getWidth();
this.scenarioHeight = (int) model.getTopographyBound().getHeight();
this.scale = scale;
this.model = model;
this.filterObstacles = IGaussianFilter.create(model.getTopography(), scale, model.getTopography().isBounded(),
0.7, IGaussianFilter.Type.OpenCL);
}
this.scenarioWidth = (int) model.getTopographyBound().getWidth();
this.scenarioHeight = (int) model.getTopographyBound().getHeight();
this.scale = scale;
this.model = model;
this.filterObstacles = IGaussianFilter.create(model.getTopography(), scale, model.getTopography().isBounded(),
0.7, IGaussianFilter.Type.OpenCL);
}
public BufferedImage getDensityImage() {
IGaussianFilter filterPedestrians = IGaussianFilter.create(
model.getTopography().getBounds(),
model.getAgents(),
scale,
0.7f,
new AttributesAgent(-1),
(ped) -> 1.0,
IGaussianFilter.Type.OpenCL);
filterPedestrians.filterImage();
filterObstacles.filterImage();
public BufferedImage getDensityImage() {
IGaussianFilter filterPedestrians = IGaussianFilter.create(
model.getTopography().getBounds(),
model.getAgents(),
scale,
0.7f,
new AttributesAgent(-1),
(ped) -> 1.0,
IGaussianFilter.Type.OpenCL);
filterPedestrians.filterImage();
filterObstacles.filterImage();
filterPedestrians.destroy();
return convertFilterToImage(filterPedestrians, filterObstacles);
}
return convertFilterToImage(filterPedestrians, filterObstacles);
}
private BufferedImage convertFilterToImage(final IGaussianFilter filterPedestrians,
final IGaussianFilter filterObstacles) {
int width = Math.max(filterObstacles.getMatrixWidth(), filterPedestrians.getMatrixWidth());
int height = Math.max(filterObstacles.getMatrixHeight(), filterPedestrians.getMatrixHeight());
BufferedImage image = createImage(width, height);
int maxColorValue = 255 * 255 * 255;
ColorHelper colorHelper = new ColorHelper(maxColorValue);
private BufferedImage convertFilterToImage(final IGaussianFilter filterPedestrians,
final IGaussianFilter filterObstacles) {
int width = Math.max(filterObstacles.getMatrixWidth(), filterPedestrians.getMatrixWidth());
int height = Math.max(filterObstacles.getMatrixHeight(), filterPedestrians.getMatrixHeight());
BufferedImage image = createImage(width, height);
int maxColorValue = 255 * 255 * 255;
ColorHelper colorHelper = new ColorHelper(maxColorValue);
// double bound = filter.getMaxFilteredValue();
double max = 1.00;
double factor = maxColorValue / max;
System.out.println(filterPedestrians.getMaxFilteredValue()); // 0.1259
// double max = filter.getMaxFilteredValue();
double max = 1.00;
double factor = maxColorValue / max;
System.out.println(filterPedestrians.getMaxFilteredValue()); // 0.1259
for (int x = 0; x < filterPedestrians.getMatrixWidth(); x++) {
for (int y = 0; y < filterPedestrians.getMatrixHeight(); y++) {
double pedValue = filterPedestrians.getFilteredValue(x, y);
double obsValue = filterObstacles.getFilteredValue(x, y);
double value = pedValue + obsValue;
// value = pedValue;
image.setRGB(x, y, colorHelper.numberToColor(value * factor).getRGB());
for (int x = 0; x < filterPedestrians.getMatrixWidth(); x++) {
for (int y = 0; y < filterPedestrians.getMatrixHeight(); y++) {
double pedValue = filterPedestrians.getFilteredValue(x, y);
double obsValue = filterObstacles.getFilteredValue(x, y);
double value = pedValue + obsValue;
// value = pedValue;
image.setRGB(x, y, colorHelper.numberToColor(value * factor).getRGB());
/*
* if(value <= 0.0) {
* image.setRGB(x, y, Color.WHITE.getRGB());
......@@ -75,20 +76,24 @@ public class CLGaussianCalculator {
* image.setRGB(x, y, colorHelper.numberToColor(value * factor).getRGB());
* }
*/
}
}
return image;
}
}
}
return image;
}
public void destroy() {
this.filterObstacles.destroy();
}
/**
* Helper method which create a new standard BufferedImage with the needed
* configurations.
*
* @return the image which is prepared for additional drawing
*/
private BufferedImage createImage(final int width, final int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
return image;
}
/**
* Helper method which create a new standard BufferedImage with the needed
* configurations.
*
* @return the image which is prepared for additional drawing
*/
private BufferedImage createImage(final int width, final int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
return image;
}
}
......@@ -7,6 +7,7 @@ import java.awt.Stroke;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.stream.Stream;
import org.apache.log4j.LogManager;
......@@ -17,126 +18,133 @@ import org.vadere.gui.components.utils.ColorHelper;
import org.vadere.gui.components.utils.Resources;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VTriangle;
public abstract class SimulationRenderer extends DefaultRenderer {
private static Logger logger = LogManager.getLogger(SimulationRenderer.class);
private static Resources resources = Resources.getInstance("postvisualization");
private static double MAX_POTENTIAL = 1000.0;
private static double CONTOUR_STEP = 2.0;
private static double CONTOUR_THINKNESS = 0.2;
private SimulationModel model;
private BufferedImage obstacleDensity = null;
private BufferedImage potentialFieldImage = null;
private ColorHelper colorHelper;
private Color lastDensityColor = null;
private int topographyId;
public SimulationRenderer(final SimulationModel model) {
super(model);
this.model = model;
this.topographyId = -1;
this.colorHelper = new ColorHelper(40);
}
@Override
protected void renderPreTransformation(Graphics2D graphics2D, int width, int height) {
if (model.isFloorFieldAvailable() && model.config.isShowPotentialField()) {
synchronized (model) {
renderPotentialField(graphics2D,
(int)(Math.min(model.getTopographyBound().width, model.getViewportBound().width) * model.getScaleFactor()),
(int)(Math.min(model.getTopographyBound().height, model.getViewportBound().height) * model.getScaleFactor()));
}
}
super.renderPreTransformation(graphics2D, width, height);
}
@Override
public void renderPostTransformation(final Graphics2D graphics, final int width, final int height) {
graphics.setColor(Color.BLACK);
// if there is no potential field than draw the default background (white)
// otherwise do not overdraw the potential field!!!
if (!model.isFloorFieldAvailable() || !model.config.isShowPotentialField()) {
super.renderPostTransformation(graphics, width, height);
}
if (model.config.isShowDensity()) {
renderDensity(graphics);
}
if (model.config.isShowGrid()) {
renderGrid(graphics);
}
if (model.config.isShowObstacles()) {
renderScenarioElement(model.getTopography().getObstacles(), graphics, model.config.getObstacleColor());
}
if (model.config.isShowStairs()) {
renderScenarioElement(model.getTopography().getStairs(), graphics, model.config.getStairColor());
}
if (model.config.isShowTargets()) {
renderScenarioElement(model.getTopography().getTargets(), graphics, model.config.getTargetColor());
}
if (model.config.isShowSources()) {
renderScenarioElement(model.getTopography().getSources(), graphics, model.config.getSourceColor());
}
if (model.isVoronoiDiagramAvailable() && model.isVoronoiDiagramVisible()) {
renderVoronoiDiagram(graphics, model.getVoronoiDiagram());
}
renderSimulationContent(graphics);
if (model.isElementSelected()) {
renderSelectionBorder(graphics);
}
if (model.isSelectionVisible()) {
renderSelectionShape(graphics);
}
if (hasLogo() && model.config.isShowLogo()) {
renderLogo(graphics, model.getScaleFactor(), height);
}
graphics.dispose();
}
protected void renderTrajectory(final Graphics2D g, final java.util.List<VPoint> points, final Agent pedestrain) {
renderTrajectory(g, points.stream(), pedestrain);
}
protected void renderTrajectory(final Graphics2D g, final Stream<VPoint> points, final Agent pedestrain) {
Color color = g.getColor();
Stroke stroke = g.getStroke();
if (model.isElementSelected() && model.getSelectedElement().equals(pedestrain)) {
g.setColor(Color.MAGENTA);
g.setStroke(new BasicStroke(getLineWidth() / 2.0f));
} else {
g.setStroke(new BasicStroke(getLineWidth() / 4.0f));
}
Path2D.Double path = new Path2D.Double();
path.moveTo(pedestrain.getPosition().getX(), pedestrain.getPosition().getY());
points.forEachOrdered(
p -> path.lineTo(p.getX(), p.getY()));
g.draw(path);
g.setColor(color);
// g.setStroke(stroke);
}
private void renderDensity(final Graphics2D g) {
CLGaussianCalculator densityCalculator = new CLGaussianCalculator(model, model.config.getDensityScale(),
model.config.getDensityMeasurementRadius(),
model.config.getDensityColor(), true, true);
private static Logger logger = LogManager.getLogger(SimulationRenderer.class);
private static Resources resources = Resources.getInstance("postvisualization");
private static double MAX_POTENTIAL = 1000.0;
private static double CONTOUR_STEP = 2.0;
private static double CONTOUR_THINKNESS = 0.2;
private SimulationModel model;
private BufferedImage obstacleDensity = null;
private BufferedImage potentialFieldImage = null;
private ColorHelper colorHelper;
private Color lastDensityColor = null;
private int topographyId;
public SimulationRenderer(final SimulationModel model) {
super(model);
this.model = model;
this.topographyId = -1;
this.colorHelper = new ColorHelper(40);
}
@Override
protected void renderPreTransformation(Graphics2D graphics2D, int width, int height) {
if (model.isFloorFieldAvailable() && model.config.isShowPotentialField()) {
synchronized (model) {
renderPotentialField(graphics2D,
(int)(Math.min(model.getTopographyBound().width, model.getViewportBound().width) * model.getScaleFactor()),
(int)(Math.min(model.getTopographyBound().height, model.getViewportBound().height) * model.getScaleFactor()));
}
}
super.renderPreTransformation(graphics2D, width, height);
}
@Override
public void renderPostTransformation(final Graphics2D graphics, final int width, final int height) {
graphics.setColor(Color.BLACK);
// if there is no potential field than draw the default background (white)
// otherwise do not overdraw the potential field!!!
if (!model.isFloorFieldAvailable() || !model.config.isShowPotentialField()) {
super.renderPostTransformation(graphics, width, height);
}
if (model.config.isShowDensity()) {
renderDensity(graphics);
}
if (model.config.isShowGrid()) {
renderGrid(graphics);
}
if (model.config.isShowObstacles()) {
renderScenarioElement(model.getTopography().getObstacles(), graphics, model.config.getObstacleColor());
}
if (model.config.isShowStairs()) {
renderScenarioElement(model.getTopography().getStairs(), graphics, model.config.getStairColor());
}
if (model.config.isShowTargets()) {
renderScenarioElement(model.getTopography().getTargets(), graphics, model.config.getTargetColor());
}
if (model.config.isShowSources()) {
renderScenarioElement(model.getTopography().getSources(), graphics, model.config.getSourceColor());
}
if (model.isVoronoiDiagramAvailable() && model.isVoronoiDiagramVisible()) {
renderVoronoiDiagram(graphics, model.getVoronoiDiagram());
}
renderSimulationContent(graphics);
if (model.isElementSelected()) {
renderSelectionBorder(graphics);
}
if (model.isSelectionVisible()) {
renderSelectionShape(graphics);
}
if (hasLogo() && model.config.isShowLogo()) {
renderLogo(graphics, model.getScaleFactor(), height);
}
graphics.dispose();
}
protected void renderTrajectory(final Graphics2D g, final java.util.List<VPoint> points, final Agent pedestrain) {
renderTrajectory(g, points.stream(), pedestrain);
}
protected void renderTrajectory(final Graphics2D g, final Stream<VPoint> points, final Agent pedestrain) {
Color color = g.getColor();
Stroke stroke = g.getStroke();
if (model.isElementSelected() && model.getSelectedElement().equals(pedestrain)) {
g.setColor(Color.MAGENTA);
g.setStroke(new BasicStroke(getLineWidth() / 2.0f));
} else {
g.setStroke(new BasicStroke(getLineWidth() / 4.0f));
}
Path2D.Double path = new Path2D.Double();
path.moveTo(pedestrain.getPosition().getX(), pedestrain.getPosition().getY());
points.forEachOrdered(
p -> path.lineTo(p.getX(), p.getY()));
g.draw(path);
g.setColor(color);
// g.setStroke(stroke);
}
protected void renderTriangulation(final Graphics2D g, final Collection<VTriangle> triangleList) {
g.setColor(Color.GRAY);
g.setStroke(new BasicStroke(getGridLineWidth()));
triangleList.stream().forEach(triangle -> g.draw(triangle));
}
private void renderDensity(final Graphics2D g) {
CLGaussianCalculator densityCalculator = new CLGaussianCalculator(model, model.config.getDensityScale(),
model.config.getDensityMeasurementRadius(),
model.config.getDensityColor(), true, true);
/*
* if (obstacleDensity == null || !model.config.getDensityColor().equals(lastDensityColor)
* || model.getTopographyId() != topographyId) {
......@@ -152,44 +160,49 @@ public abstract class SimulationRenderer extends DefaultRenderer {
* model.config.getPedestrianTorso());
*/
BufferedImage densityImage = densityCalculator.getDensityImage();
BufferedImage densityImage = densityCalculator.getDensityImage();
g.scale(1.0 / model.config.getDensityScale(), 1.0 / model.config.getDensityScale());
g.drawImage(densityImage, 0, 0, null);
// g.drawImage(pedestrianDensity, 0, 0, null);
g.scale(model.config.getDensityScale(), model.config.getDensityScale());
}
g.scale(1.0 / model.config.getDensityScale(), 1.0 / model.config.getDensityScale());
g.drawImage(densityImage, 0, 0, null);
// g.drawImage(pedestrianDensity, 0, 0, null);
g.scale(model.config.getDensityScale(), model.config.getDensityScale());
densityCalculator.destroy();
}
private void renderPotentialField(final Graphics2D g, final int width, final int height) {
private void renderPotentialField(final Graphics2D g, final int width, final int height) {
/*
* This calculation we need since the viewport.y = 0 if the user scrolls to the bottom
*/
Rectangle2D.Double viewportBound = model.getViewportBound();
double dy = model.getTopographyBound().getHeight() - viewportBound.getHeight();
int startX = (int) (viewportBound.getX() * model.getScaleFactor());
int startY = (int) (Math.max((dy - viewportBound.getY()), 0) * model.getScaleFactor());
potentialFieldImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < potentialFieldImage.getWidth(); x++) {
for (int y = 0; y < potentialFieldImage.getHeight(); y++) {
Color c;
double potential = model.getPotential(x + startX, y + startY);
if (potential >= MAX_POTENTIAL) {
c = model.config.getObstacleColor();
} else if (potential % CONTOUR_STEP <= CONTOUR_THINKNESS) {
c = Color.BLACK;
} else {
c = colorHelper.numberToColor(potential % 100);
}
potentialFieldImage.setRGB(x, y, c.getRGB());
}
}
g.drawImage(potentialFieldImage, 0, 0, null);
}
protected abstract void renderSimulationContent(final Graphics2D g);
}
Rectangle2D.Double viewportBound = model.getViewportBound();
double dy = model.getTopographyBound().getHeight() - viewportBound.getHeight();
int startX = (int) (viewportBound.getX() * model.getScaleFactor());
int startY = (int) (Math.max((dy - viewportBound.getY()), 0) * model.getScaleFactor());
potentialFieldImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < potentialFieldImage.getWidth(); x++) {
for (int y = 0; y < potentialFieldImage.getHeight(); y++) {
Color c;
double potential = model.getPotential(x + startX, y + startY);
if (potential >= MAX_POTENTIAL) {
c = model.config.getObstacleColor();
} else if (potential % CONTOUR_STEP <= CONTOUR_THINKNESS) {
c = Color.BLACK;
} else {
c = colorHelper.numberToColor(potential % 100);
}
potentialFieldImage.setRGB(x, y, c.getRGB());
}
}
g.drawImage(potentialFieldImage, 0, 0, null);
}
protected abstract void renderSimulationContent(final Graphics2D g);
private float getGridLineWidth() {
return (float) (0.5 / model.getScaleFactor());
}
}
\ No newline at end of file
......@@ -8,16 +8,22 @@ import org.vadere.util.opencl.CLConvolution;
class CLGaussianFilter extends GaussianFilter {
private final CLConvolution convolution;
private final CLConvolution convolution;
CLGaussianFilter(final Rectangle2D scenarioBounds, final double scale, final BiFunction<Integer, Integer, Float> f,
final boolean normalize) throws IOException {
super(scenarioBounds, scale, f, normalize);
this.convolution = new CLConvolution();
}
CLGaussianFilter(final Rectangle2D scenarioBounds, final double scale, final BiFunction<Integer, Integer, Float> f,
final boolean normalize) throws IOException {
super(scenarioBounds, scale, f, normalize);
this.convolution = new CLConvolution(matrixWidth, matrixHeight, kernelWidth, kernel);
this.convolution.init();
}
@Override
public void filterImage() {
outputMatrix = this.convolution.convolveSeparate(inputMatrix, matrixWidth, matrixHeight, kernel, kernelWidth);
}
@Override
public void filterImage() {
outputMatrix = this.convolution.convolve(inputMatrix);
}
@Override
public void destroy() {
this.convolution.clearCL();
}
}
......@@ -10,118 +10,119 @@ import java.util.stream.IntStream;
abstract class GaussianFilter implements IGaussianFilter {
/**
* the scale of the images respect to the scenario width and heigt and based on the
* gridresolution of the potential field grid.
*/
protected final double scale;
/** the width of the scenario. */
protected final int scenarioWidth;
/** the height of the scenario. */
protected final int scenarioHeight;
protected float[] inputMatrix;
protected float[] outputMatrix;
protected float[] kernel;
protected int kernelWidth;
protected int kernelHeight;
protected int matrixWidth;
protected int matrixHeight;
private static Logger logger = LogManager.getLogger(GaussianFilter.class);
GaussianFilter(final Rectangle2D scenarioBounds, final double scale, final BiFunction<Integer, Integer, Float> f,
final boolean noramized) {
this.scale = scale;
this.scenarioWidth = (int) (Math.ceil(scenarioBounds.getWidth())) + 1;