1 /* 2 * Copyright (c) 2008, 2013, 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 26 package com.sun.scenario.effect.compiler.backend.hw; 27 28 import java.util.HashMap; 29 import java.util.Map; 30 import com.sun.scenario.effect.compiler.JSLParser; 31 import com.sun.scenario.effect.compiler.model.BaseType; 32 import com.sun.scenario.effect.compiler.model.Function; 33 import com.sun.scenario.effect.compiler.model.Qualifier; 34 import com.sun.scenario.effect.compiler.model.Type; 35 import com.sun.scenario.effect.compiler.model.Variable; 36 import com.sun.scenario.effect.compiler.tree.Expr; 37 import com.sun.scenario.effect.compiler.tree.FuncDef; 38 import com.sun.scenario.effect.compiler.tree.ProgramUnit; 39 import com.sun.scenario.effect.compiler.tree.VarDecl; 40 41 /** 42 */ 43 public class HLSLBackend extends SLBackend { 44 45 public HLSLBackend(JSLParser parser, ProgramUnit program) { 46 super(parser, program); 47 } 48 49 private static final Map<String, String> qualMap = new HashMap<String, String>(); 50 static { 51 qualMap.put("const", ""); 52 qualMap.put("param", ""); 53 } 54 55 private static final Map<String, String> typeMap = new HashMap<String, String>(); 56 static { 57 typeMap.put("void", "void"); 58 typeMap.put("float", "float"); 59 typeMap.put("float2", "float2"); 60 typeMap.put("float3", "float3"); 61 typeMap.put("float4", "float4"); 62 typeMap.put("int", "int"); 63 typeMap.put("int2", "int2"); 64 typeMap.put("int3", "int3"); 65 typeMap.put("int4", "int4"); 66 typeMap.put("bool", "bool"); 67 typeMap.put("bool2", "bool2"); 68 typeMap.put("bool3", "bool3"); 69 typeMap.put("bool4", "bool4"); 70 typeMap.put("sampler", "sampler2D"); 71 typeMap.put("lsampler","sampler2D"); 72 typeMap.put("fsampler","sampler2D"); 73 } 74 75 private static final Map<String, String> varMap = new HashMap<String, String>(); 76 static { 77 } 78 79 private static final Map<String, String> funcMap = new HashMap<String, String>(); 80 static { 81 funcMap.put("sample", "tex2D"); 82 funcMap.put("fract", "frac"); 83 funcMap.put("mix", "lerp"); 84 funcMap.put("mod", "fmod"); 85 funcMap.put("intcast", "int"); 86 funcMap.put("any", "any"); 87 funcMap.put("length", "length"); 88 } 89 90 @Override 91 protected String getType(Type t) { 92 return typeMap.get(t.toString()); 93 } 94 95 @Override 96 protected String getQualifier(Qualifier q) { 97 return qualMap.get(q.toString()); 98 } 99 100 @Override 101 protected String getVar(String v) { 102 String s = varMap.get(v); 103 return (s != null) ? s : v; 104 } 105 106 @Override 107 protected String getFuncName(String f) { 108 String s = funcMap.get(f); 109 return (s != null) ? s : f; 110 } 111 112 @Override 113 public void visitFuncDef(FuncDef d) { 114 Function func = d.getFunction(); 115 if (func.getName().equals("main")) { 116 output(getType(func.getReturnType()) + " " + func.getName() + "("); 117 // TODO: it would be better if we scanned the whole JSL program 118 // to see if pos0 or pos1 are used anywhere, but for now there 119 // doesn't seem to be any harm in blindly declaring both here... 120 for (int i = 0; i < 2; i++) { 121 output("in float2 pos" + i + " : TEXCOORD" + i + ",\n"); 122 } 123 // TODO: only need this if pixcoord is referenced somewhere 124 // in the JSL program... 125 output("in float2 pixcoord : VPOS,\n"); 126 output("in float4 jsl_vertexColor : COLOR0,\n"); 127 output("out float4 color : COLOR0"); 128 output(") "); 129 scan(d.getStmt()); 130 } else { 131 super.visitFuncDef(d); 132 } 133 } 134 135 @Override 136 public void visitVarDecl(VarDecl d) { 137 Variable var = d.getVariable(); 138 Type type = var.getType(); 139 Qualifier qual = var.getQualifier(); 140 if (qual == Qualifier.PARAM && type.getBaseType() == BaseType.INT) { 141 // TODO: It seems that constant integer registers have limitations 142 // in SM 3.0... For example, the max number of integer registers 143 // (those specified with i#) is 16; in PS 2.0 these were limited 144 // to flow control instructions only, but according to MSDN this 145 // restriction went away with PS 3.0. However, bad things happen 146 // at runtime if we output: 147 // int variableName : register(c0); 148 // (not sure what the problem is, but bad values seem to be 149 // uploaded if we use SetPixelShaderConstantI() in this case), and 150 // if we use i# instead: 151 // int variableName : register(i0); 152 // the compiler will say this is invalid (it won't complain if 153 // we actually used it in a loop expression though). Until this 154 // problem is better understood, we can work around it by 155 // declaring these params as float variants, e.g.: 156 // float variableName : register(c0); 157 // and using SetPixelShaderConstantF() instead. 158 String t; 159 switch (type) { 160 case INT: 161 t = "float"; 162 break; 163 case INT2: 164 t = "float2"; 165 break; 166 case INT3: 167 t = "float3"; 168 break; 169 case INT4: 170 t = "float4"; 171 break; 172 default: 173 throw new InternalError(); 174 } 175 output(t + " " + var.getName()); 176 } else if (qual == Qualifier.CONST) { 177 // use #define-style definition 178 output("#define " + var.getName()); 179 } else { 180 output(getType(type) + " " + var.getName()); 181 } 182 Expr init = d.getInit(); 183 if (init != null) { 184 if (qual == Qualifier.CONST) { 185 // use #define-style definition (no '=', wrap in 186 // parens for safety) 187 output(" ("); 188 scan(init); 189 output(")"); 190 } else { 191 output(" = "); 192 scan(init); 193 } 194 } 195 if (var.isArray()) { 196 output("[" + var.getArraySize() + "]"); 197 } 198 if (qual == Qualifier.PARAM) { 199 char c = (type.getBaseType() == BaseType.SAMPLER) ? 's' : 'c'; 200 output(" : register(" + c + var.getReg() + ")"); 201 } 202 if (qual == Qualifier.CONST) { 203 // use #define-style definition (no closing ';') 204 output("\n"); 205 } else { 206 output(";\n"); 207 } 208 } 209 }