1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package mandel; 26 27 import hat.Accelerator; 28 import hat.ComputeContext; 29 import hat.KernelContext; 30 import hat.backend.Backend; 31 import hat.buffer.S32Array; 32 import hat.buffer.S32Array2D; 33 34 import java.awt.Color; 35 import java.lang.invoke.MethodHandles; 36 37 import hat.ifacemapper.SegmentMapper; 38 import jdk.incubator.code.CodeReflection; 39 import static hat.ifacemapper.MappableIface.*; 40 41 public class Main { 42 @CodeReflection 43 public static void mandel(@RO KernelContext kc, @RW S32Array2D s32Array2D, @RO S32Array pallette, float offsetx, float offsety, float scale) { 44 if (kc.x < kc.maxX) { 45 float width = s32Array2D.width(); 46 float height = s32Array2D.height(); 47 float x = ((kc.x % s32Array2D.width()) * scale - (scale / 2f * width)) / width + offsetx; 48 float y = ((kc.x / s32Array2D.width()) * scale - (scale / 2f * height)) / height + offsety; 49 float zx = x; 50 float zy = y; 51 float new_zx; 52 int colorIdx = 0; 53 while ((colorIdx < pallette.length()) && (((zx * zx) + (zy * zy)) < 4f)) { 54 new_zx = ((zx * zx) - (zy * zy)) + x; 55 zy = (2f * zx * zy) + y; 56 zx = new_zx; 57 colorIdx++; 58 } 59 int color = colorIdx < pallette.length() ? pallette.array(colorIdx) : 0; 60 s32Array2D.array(kc.x, color); 61 } 62 } 63 64 65 @CodeReflection 66 static public void compute(final ComputeContext computeContext, S32Array pallete, S32Array2D s32Array2D, float x, float y, float scale) { 67 68 computeContext.dispatchKernel( 69 s32Array2D.width()*s32Array2D.height(), //0..S32Array2D.size() 70 kc -> Main.mandel(kc, s32Array2D, pallete, x, y, scale)); 71 } 72 73 public static void main(String[] args) { 74 boolean headless = Boolean.getBoolean("headless") ||( args.length>0 && args[0].equals("--headless")); 75 76 final int width = 1024; 77 final int height = 1024; 78 final float defaultScale = 3f; 79 final float originX = -1f; 80 final float originY = 0; 81 final int maxIterations = 64; 82 final int zoomFrames = 200; 83 84 Accelerator accelerator = new Accelerator(MethodHandles.lookup(), Backend.FIRST); 85 86 S32Array2D s32Array2D = S32Array2D.create(accelerator, width, height); 87 //var s32Array2DState = SegmentMapper.BufferState.of(s32Array2D); 88 //System.out.println(s32Array2DState); 89 90 91 92 int[] palletteArray = new int[maxIterations]; 93 94 if (headless){ 95 for (int i = 1; i < maxIterations; i++) { 96 palletteArray[i]=(i/8+1);// 0-7? 97 } 98 palletteArray[0]=0; 99 }else { 100 for (int i = 0; i < maxIterations; i++) { 101 final float h = i / (float) maxIterations; 102 final float b = 1.0f - (h * h); 103 palletteArray[i] = Color.HSBtoRGB(h, 1f, b); 104 } 105 } 106 S32Array pallette = S32Array.createFrom(accelerator, palletteArray); 107 108 accelerator.compute(cc -> Main.compute(cc, pallette, s32Array2D, originX, originY, defaultScale)); 109 110 if (headless){ 111 // Well take 1 in 4 samples (so 1024 -> 128 grid) of the pallette. 112 int subsample = 16; 113 char[] charPallette9 = new char []{' ', '.', ',',':', '-', '+','*', '#', '@', '%'}; 114 for (int y = 0; y<height/subsample; y++) { 115 for (int x = 0; x<width/subsample; x++) { 116 int palletteValue = s32Array2D.get(x*subsample,y*subsample); // so 0->8 117 System.out.print(charPallette9[palletteValue]); 118 } 119 System.out.println(); 120 } 121 122 }else { 123 Viewer viewer = new Viewer("mandel", s32Array2D); 124 viewer.imageViewer.syncWithRGB(s32Array2D); 125 126 while (viewer.imageViewer.getZoomPoint(defaultScale) instanceof Viewer.PointF32 zoomPoint) { 127 float x = originX; 128 float y = originY; 129 float scale = defaultScale; 130 final long startMillis = System.currentTimeMillis(); 131 132 for (int sign : new int[]{-1, 1}) { 133 for (int i = 0; i < zoomFrames; i++) { 134 scale = scale + ((sign * defaultScale) / zoomFrames); 135 final float fscale = scale; 136 final float fx = x - sign * zoomPoint.x / zoomFrames; 137 final float fy = y - sign * zoomPoint.y / zoomFrames; 138 accelerator.compute(cc -> Main.compute(cc, pallette, s32Array2D, fx, fy, fscale)); 139 viewer.imageViewer.syncWithRGB(s32Array2D); 140 141 } 142 } 143 var fps = ((zoomFrames * 2 * 1000) / (System.currentTimeMillis() - startMillis)); 144 viewer.framesSecondSevenSegment.set((int)fps); 145 // System.out.println("FPS = " +fps); 146 } 147 } 148 } 149 }