typeof-keyword.azsl 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. class getter
  2. {
  3. float2x2 fval();
  4. };
  5. class intermediate
  6. {
  7. getter getgetter();
  8. };
  9. class top
  10. {
  11. intermediate many[3];
  12. struct inner {};
  13. void innerfunc() {}
  14. };
  15. top gettop();
  16. class A
  17. {
  18. int a;
  19. };
  20. class B : A
  21. {
  22. };
  23. struct Half{};
  24. struct Double{};
  25. half returnThings(Half);
  26. double returnThings(Double);
  27. struct UniformFoo{};
  28. UniformFoo returnSame(int);
  29. UniformFoo returnSame(float1x1);
  30. struct S { int i; };
  31. ShaderResourceGroupSemantic freq
  32. { FrequencyId = 1; }
  33. ShaderResourceGroup MySRG : freq
  34. {
  35. // Buffer-views are chameleons mimicking "T[]" (collapsed to T in azslc)
  36. Buffer<float> m_buf;
  37. RasterizerOrderedBuffer<float> m_rob_f;
  38. RasterizerOrderedStructuredBuffer<struct R { int i; float f; }> m_rosb_R;
  39. struct Ext { R r; };
  40. RWStructuredBuffer<Ext> m_rwsb_E;
  41. RWBuffer<int4x2> m_rwb_i42;
  42. // CB is chameleon to "(one element of) type S"
  43. ConstantBuffer<S> m_cb_S;
  44. StructuredBuffer<S> m_sb_S;
  45. // SRG Constants
  46. int m_i; // scalar
  47. vector<float,2> m_vec_f2; // generic vector
  48. matrix<half,2,2> m_mat_h22; // generic matrix
  49. // other view types
  50. Sampler m_samp {};
  51. Texture2D m_tex;
  52. Texture2D<float4> m_tex_f4;
  53. };
  54. void h()
  55. {
  56. // typeof exists to support the seenat feature.
  57. // therefore the only accepted parameters are dependencies of idExpressions: idExpressions and MemberAccessExpression.
  58. // at level 2, MemberAccessExpression depends on 'expression' but only a subset can return UserDefinedType.
  59. //
  60. // supported:
  61. // idExpressions stuff::name
  62. // MemberAccessExpression stuff.name
  63. // FunctionCallExpression stuff()
  64. // ArrayIndexExpression stuff[i]
  65. // ParenthesizedExpression (stuff)
  66. // CastExpression (stuff)thing
  67. // ConditionalExpression stuff ? thenthat : otherwisethat
  68. // AssignmentExpression stuff = thing
  69. // NumericConstructorExpression float2(0,0)
  70. // LiteralExpression 42
  71. // CommaExpression X, Y
  72. // not supported:
  73. // PostfixUnaryExpression i++
  74. // PrefixUnaryExpression ++i
  75. // BinaryExpression i + j
  76. // e.g. typeof(1 + 3) = <fail>
  77. // mathematics
  78. __azslc_print_message("@check predicate ");
  79. __azslc_print_symbol(typeof(1 + 3), __azslc_prtsym_least_qualified);
  80. __azslc_print_message(" == '<fail>'\n");
  81. // literals
  82. __azslc_print_message("@check predicate ");
  83. __azslc_print_symbol(typeof(1), __azslc_prtsym_least_qualified);
  84. __azslc_print_message(" == 'int'\n");
  85. __azslc_print_message("@check predicate ");
  86. __azslc_print_symbol(typeof(1u), __azslc_prtsym_least_qualified);
  87. __azslc_print_message(" == 'uint'\n");
  88. __azslc_print_message("@check predicate ");
  89. __azslc_print_symbol(typeof(1l), __azslc_prtsym_least_qualified);
  90. __azslc_print_message(" == 'int'\n");
  91. __azslc_print_message("@check predicate ");
  92. __azslc_print_symbol(typeof(1ul), __azslc_prtsym_least_qualified);
  93. __azslc_print_message(" == 'uint'\n");
  94. __azslc_print_message("@check predicate ");
  95. __azslc_print_symbol(typeof(1lu), __azslc_prtsym_least_qualified);
  96. __azslc_print_message(" == 'uint'\n");
  97. __azslc_print_message("@check predicate ");
  98. __azslc_print_symbol(typeof(1.0), __azslc_prtsym_least_qualified);
  99. __azslc_print_message(" == 'float'\n");
  100. __azslc_print_message("@check predicate ");
  101. __azslc_print_symbol(typeof(1.0f), __azslc_prtsym_least_qualified);
  102. __azslc_print_message(" == 'float'\n");
  103. __azslc_print_message("@check predicate ");
  104. __azslc_print_symbol(typeof(1.h), __azslc_prtsym_least_qualified);
  105. __azslc_print_message(" == 'half'\n");
  106. __azslc_print_message("@check predicate ");
  107. __azslc_print_symbol(typeof(1.H), __azslc_prtsym_least_qualified);
  108. __azslc_print_message(" == 'half'\n");
  109. __azslc_print_message("@check predicate ");
  110. __azslc_print_symbol(typeof(1.0L), __azslc_prtsym_least_qualified);
  111. __azslc_print_message(" == 'double'\n");
  112. __azslc_print_message("@check predicate ");
  113. __azslc_print_symbol(typeof(true), __azslc_prtsym_least_qualified);
  114. __azslc_print_message(" == 'bool'\n");
  115. __azslc_print_message("@check predicate ");
  116. __azslc_print_symbol(typeof(false), __azslc_prtsym_least_qualified);
  117. __azslc_print_message(" == 'bool'\n");
  118. __azslc_print_message("@check predicate ");
  119. __azslc_print_symbol(typeof("stuff"), __azslc_prtsym_least_qualified);
  120. __azslc_print_message(" == '<fail>'\n");
  121. // direct type (identity)
  122. __azslc_print_message("@check predicate ");
  123. __azslc_print_symbol(typeof(top), __azslc_prtsym_least_qualified);
  124. __azslc_print_message(" == 'top'\n");
  125. // same, as fully qualified
  126. __azslc_print_message("@check predicate ");
  127. __azslc_print_symbol(typeof(top), __azslc_prtsym_fully_qualified);
  128. __azslc_print_message(" == '/top'\n");
  129. float f;
  130. // local symbol
  131. __azslc_print_message("@check predicate ");
  132. __azslc_print_symbol(typeof(f), __azslc_prtsym_least_qualified);
  133. __azslc_print_message(" == 'float'\n");
  134. // same as fully qualified
  135. __azslc_print_message("@check predicate ");
  136. __azslc_print_symbol(typeof(f), __azslc_prtsym_fully_qualified);
  137. __azslc_print_message(" == '?float'\n");
  138. S s;
  139. // member access
  140. __azslc_print_message("@check predicate ");
  141. __azslc_print_symbol(typeof(s.i), __azslc_prtsym_least_qualified);
  142. __azslc_print_message(" == 'int'\n");
  143. // the qualified unevaluated-expression access can probably also be supported as a bonus:
  144. __azslc_print_message("@check predicate ");
  145. __azslc_print_symbol(typeof(S::i), __azslc_prtsym_least_qualified);
  146. __azslc_print_message(" == 'int'\n");
  147. // legit qualified id (just names a type directly):
  148. __azslc_print_message("@check predicate ");
  149. __azslc_print_symbol(typeof(top::inner), __azslc_prtsym_fully_qualified);
  150. __azslc_print_message(" == '/top/inner'\n");
  151. // class inheritance: parent member access using scope resolution operator
  152. __azslc_print_message("@check predicate ");
  153. __azslc_print_symbol(typeof(B::a), __azslc_prtsym_least_qualified);
  154. __azslc_print_message(" == 'int'\n");
  155. // function call, the return type is returned
  156. __azslc_print_message("@check predicate ");
  157. __azslc_print_symbol(typeof(gettop()), __azslc_prtsym_least_qualified);
  158. __azslc_print_message(" == 'top'\n");
  159. // function type is not a citizen in HLSL nor AZSL.
  160. // the typeof keyword thus simply returns the function symbol itself.
  161. __azslc_print_message("@check predicate ");
  162. __azslc_print_symbol(typeof(gettop), __azslc_prtsym_fully_qualified);
  163. __azslc_print_message(" == '/gettop()'\n"); // resolved to the unique concrete function candidate if no overloads
  164. __azslc_print_message("@check predicate ");
  165. __azslc_print_symbol(typeof(returnThings), __azslc_prtsym_fully_qualified);
  166. __azslc_print_message(" == '/returnThings'\n"); // but remains undetermined in case of the presence of overloads
  167. __azslc_print_message("@check predicate ");
  168. __azslc_print_symbol(typeof(top::innerfunc), __azslc_prtsym_least_qualified);
  169. __azslc_print_message(" == 'top/innerfunc'\n"); // least qualification removes the argument mangling.
  170. __azslc_print_message("@check predicate ");
  171. __azslc_print_symbol(typeof(top::innerfunc), __azslc_prtsym_fully_qualified);
  172. __azslc_print_message(" == '/top/innerfunc()'\n"); // full qualification preserves them
  173. // though call expression should work (this is not a compound because that function reference is an idExpression, be it qualified or not)
  174. __azslc_print_message("@check predicate ");
  175. __azslc_print_symbol(typeof(top::innerfunc()), __azslc_prtsym_least_qualified);
  176. __azslc_print_message(" == 'void'\n");
  177. // overloaded calls also work as long as the resolve of arguments is possible, or the overloadSet has a uniform return type
  178. // resolved arguments
  179. __azslc_print_message("@check predicate ");
  180. __azslc_print_symbol(typeof(returnThings((Half)0)), __azslc_prtsym_least_qualified);
  181. __azslc_print_message(" == 'half'\n");
  182. __azslc_print_message("@check predicate ");
  183. __azslc_print_symbol(typeof(returnThings((Double)0)), __azslc_prtsym_least_qualified);
  184. __azslc_print_message(" == 'double'\n");
  185. // unresolved arguments
  186. __azslc_print_message("@check predicate ");
  187. __azslc_print_symbol(typeof(returnSame(0+0)), __azslc_prtsym_least_qualified);
  188. __azslc_print_message(" == 'UniformFoo'\n");
  189. __azslc_print_message("@check predicate ");
  190. __azslc_print_symbol(typeof(returnSame((float1x1)0+(float1x1)0)), __azslc_prtsym_least_qualified);
  191. __azslc_print_message(" == 'UniformFoo'\n");
  192. // array index
  193. __azslc_print_message("@check predicate ");
  194. __azslc_print_symbol(typeof(top::many[1]), __azslc_prtsym_least_qualified);
  195. __azslc_print_message(" == 'intermediate'\n");
  196. // compound: member access + (function call & array index)
  197. __azslc_print_message("@check predicate ");
  198. __azslc_print_symbol(typeof(gettop().many[1]), __azslc_prtsym_least_qualified);
  199. __azslc_print_message(" == 'intermediate'\n");
  200. // for now array-types are coalesced to their underlying type
  201. __azslc_print_message("@check predicate ");
  202. __azslc_print_symbol(typeof(top::many), __azslc_prtsym_least_qualified);
  203. __azslc_print_message(" == 'intermediate'\n");
  204. // ultimate compound
  205. __azslc_print_message("@check predicate ");
  206. __azslc_print_symbol(typeof(gettop().many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  207. __azslc_print_message(" == 'float2x2'\n");
  208. // ultimate compound with over-qualification in the middle
  209. __azslc_print_message("@check predicate ");
  210. __azslc_print_symbol(typeof(gettop().top::many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  211. __azslc_print_message(" == 'float2x2'\n");
  212. // ultimate compound with full qualification in the middle
  213. __azslc_print_message("@check predicate ");
  214. __azslc_print_symbol(typeof(gettop().::top::many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  215. __azslc_print_message(" == 'float2x2'\n");
  216. // check what's going on with generic predefineds
  217. // SRG Constants
  218. // == check chameleon types ==
  219. // chameleon= have a generic type as parameter, but end up being a forward for its behavior. (like typedef)
  220. // typeof can't see the non-canonicalized type. So we lose the original chameleon type, and all we "see" is its mimicked type: the canonical type.
  221. // from SRG references
  222. // plain Buffer<>
  223. __azslc_print_message("@check predicate ");
  224. __azslc_print_symbol(typeof(MySRG::m_buf), __azslc_prtsym_least_qualified);
  225. __azslc_print_message(" == 'float'\n"); // this is really a Buffer<float> but we see float.
  226. // ROB in SRG
  227. __azslc_print_message("@check predicate ");
  228. __azslc_print_symbol(typeof(MySRG::m_rob_f), __azslc_prtsym_least_qualified);
  229. __azslc_print_message(" == 'float'\n");
  230. // ROSB in SRG
  231. __azslc_print_message("@check predicate ");
  232. __azslc_print_symbol(typeof(MySRG::m_rosb_R), __azslc_prtsym_least_qualified);
  233. __azslc_print_message(" == 'MySRG/R'\n");
  234. // RWB in SRG
  235. __azslc_print_message("@check predicate ");
  236. __azslc_print_symbol(typeof(MySRG::m_rwb_i42), __azslc_prtsym_least_qualified);
  237. __azslc_print_message(" == 'int4x2'\n");
  238. // RWSB in SRG
  239. __azslc_print_message("@check predicate ");
  240. __azslc_print_symbol(typeof(MySRG::m_rwsb_E), __azslc_prtsym_least_qualified);
  241. __azslc_print_message(" == 'MySRG/Ext'\n"); // this is really a RWStructuredBuffer<Ext> but we see Ext.
  242. // SB in SRG
  243. __azslc_print_message("@check predicate ");
  244. __azslc_print_symbol(typeof(MySRG::m_sb_S), __azslc_prtsym_least_qualified);
  245. __azslc_print_message(" == 'S'\n");
  246. // CB
  247. __azslc_print_message("@check predicate ");
  248. __azslc_print_symbol(typeof(MySRG::m_cb_S), __azslc_prtsym_least_qualified);
  249. __azslc_print_message(" == 'S'\n");
  250. // int
  251. __azslc_print_message("@check predicate ");
  252. __azslc_print_symbol(typeof(MySRG::m_i), __azslc_prtsym_least_qualified);
  253. __azslc_print_message(" == 'int'\n");
  254. // vector<float,2> m_vec_f2;
  255. __azslc_print_message("@check predicate ");
  256. __azslc_print_symbol(typeof(MySRG::m_vec_f2), __azslc_prtsym_least_qualified);
  257. //__azslc_print_message(" == 'float2'\n"); // canonicalized form // WIP
  258. __azslc_print_message(" == 'vector'\n");
  259. // matrix<half,2,2> m_mat_h22;
  260. __azslc_print_message("@check predicate ");
  261. __azslc_print_symbol(typeof(MySRG::m_mat_h22), __azslc_prtsym_least_qualified);
  262. //__azslc_print_message(" == 'half2x2'\n"); // WIP
  263. __azslc_print_message(" == 'matrix'\n"); // for now it returns the core type since I didn't create the canonicalization system for GenericArithmetic
  264. // other view types
  265. // Sampler m_samp;
  266. __azslc_print_message("@check predicate ");
  267. __azslc_print_symbol(typeof(MySRG::m_samp), __azslc_prtsym_least_qualified);
  268. __azslc_print_message(" == 'Sampler'\n");
  269. // Texture2D m_tex;
  270. __azslc_print_message("@check predicate ");
  271. __azslc_print_symbol(typeof(MySRG::m_tex), __azslc_prtsym_least_qualified);
  272. __azslc_print_message(" == 'Texture2D'\n");
  273. // Texture2D<float4> m_tex_f4;
  274. __azslc_print_message("@check predicate ");
  275. __azslc_print_symbol(typeof(MySRG::m_tex_f4), __azslc_prtsym_least_qualified);
  276. __azslc_print_message(" == 'Texture2D'\n"); // texture generic types are ignored
  277. // fail get test
  278. __azslc_print_message("@check predicate ");
  279. __azslc_print_symbol(typeof(MySRG::inexistent), __azslc_prtsym_least_qualified);
  280. __azslc_print_message(" == '<fail>'\n");
  281. // from local references (local view-data-types don't have extern binding. they are pure aliases.)
  282. RasterizerOrderedBuffer<float> rob_f;
  283. RasterizerOrderedStructuredBuffer<struct R { int i; float f; }> rosb_R;
  284. struct Ext { R r; }; // using R here is possible in azsl; because above generic clause is not hygienic in the Kohlbecker sense.
  285. RWStructuredBuffer<Ext> rwsb_E;
  286. RWBuffer<int4x2> rwb_i42;
  287. StructuredBuffer<S> sb_S;
  288. vector<float,2> vec_f2;
  289. matrix<half,2,2> mat_h22;
  290. // ROB
  291. __azslc_print_message("@check predicate ");
  292. __azslc_print_symbol(typeof(rob_f), __azslc_prtsym_least_qualified);
  293. __azslc_print_message(" == 'float'\n");
  294. // ROSB
  295. __azslc_print_message("@check predicate ");
  296. __azslc_print_symbol(typeof(rosb_R), __azslc_prtsym_least_qualified);
  297. __azslc_print_message(" == 'R'\n"); // R refers to the 'struct R' passed in rosb_R generic parameter.
  298. // RWB
  299. __azslc_print_message("@check predicate ");
  300. __azslc_print_symbol(typeof(rwb_i42), __azslc_prtsym_least_qualified);
  301. __azslc_print_message(" == 'int4x2'\n");
  302. // RWSB
  303. __azslc_print_message("@check predicate ");
  304. __azslc_print_symbol(typeof(rwsb_E), __azslc_prtsym_least_qualified);
  305. __azslc_print_message(" == 'Ext'\n");
  306. // SB
  307. __azslc_print_message("@check predicate ");
  308. __azslc_print_symbol(typeof(sb_S), __azslc_prtsym_least_qualified);
  309. __azslc_print_message(" == 'S'\n");
  310. // generic vector
  311. __azslc_print_message("@check predicate ");
  312. __azslc_print_symbol(typeof(vec_f2), __azslc_prtsym_least_qualified);
  313. //__azslc_print_message(" == 'float2'\n"); // canonicalized form // WIP
  314. __azslc_print_message(" == 'vector'\n");
  315. // generic matrix
  316. __azslc_print_message("@check predicate ");
  317. __azslc_print_symbol(typeof(mat_h22), __azslc_prtsym_least_qualified);
  318. //__azslc_print_message(" == 'half2x2'\n"); // WIP
  319. __azslc_print_message(" == 'matrix'\n");
  320. // == end check chameleon types ==
  321. // simple (already canonical) vector
  322. half3 h3;
  323. __azslc_print_message("@check predicate ");
  324. __azslc_print_symbol(typeof(h3), __azslc_prtsym_least_qualified);
  325. __azslc_print_message(" == 'half3'\n");
  326. // cast
  327. __azslc_print_message("@check predicate ");
  328. __azslc_print_symbol(typeof((top)0), __azslc_prtsym_fully_qualified);
  329. __azslc_print_message(" == '/top'\n");
  330. // conditional
  331. __azslc_print_message("@check predicate ");
  332. __azslc_print_symbol(typeof(true ? (int)1 : (int)2), __azslc_prtsym_least_qualified);
  333. __azslc_print_message(" == 'int'\n");
  334. // parenthesis
  335. __azslc_print_message("@check predicate ");
  336. __azslc_print_symbol(typeof((s.i)), __azslc_prtsym_least_qualified);
  337. __azslc_print_message(" == 'int'\n");
  338. // cast compounded with typeof
  339. __azslc_print_message("@check predicate ");
  340. __azslc_print_symbol(typeof( (typeof(s.i))0 ), __azslc_prtsym_least_qualified);
  341. __azslc_print_message(" == 'int'\n");
  342. // numeric constructor expression
  343. __azslc_print_message("@check predicate ");
  344. __azslc_print_symbol(typeof(float2(0,0)), __azslc_prtsym_least_qualified);
  345. __azslc_print_message(" == 'float2'\n");
  346. __azslc_print_message("@check predicate ");
  347. __azslc_print_symbol(typeof(uint(0)), __azslc_prtsym_least_qualified);
  348. __azslc_print_message(" == 'uint'\n");
  349. __azslc_print_message("@check predicate ");
  350. __azslc_print_symbol(typeof(uint()), __azslc_prtsym_least_qualified);
  351. __azslc_print_message(" == 'uint'\n");
  352. // comma expression:
  353. int INTVAR;
  354. double DOUBLEVAR;
  355. __azslc_print_message("@check predicate ");
  356. __azslc_print_symbol(typeof(INTVAR, INTVAR, DOUBLEVAR), __azslc_prtsym_least_qualified);
  357. __azslc_print_message(" == 'double'\n");
  358. }